ALSA неожиданная неудача с, казалось бы, правильными таймингами - PullRequest
0 голосов
/ 03 ноября 2018

Я схожу с ума от ложных ошибок опустошения при вызовах snd_pcm_writei ().

Я использую настройку блокировки:

snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);

Вот вывод snd_pcm_dump_sw_setup ():

  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1764
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 3528
  silence_threshold: 0
  silence_size : 0
  boundary     : 1849688064

При настройке параметров оборудования я регистрирую результаты вызовов snd_pcm_hw_params_set_rate_near (), snd_pcm_hw_params_set_periods_near (), snd_pcm_hw_params_set_period_size_near ():

3719.1287 D [AlsaSound] SOUND: setupWithFreq sampling rate: 44100, dir: 0
3719.1288 D [AlsaSound] SOUND: number of periods: 2, dir: 0
3719.1289 D [AlsaSound] SOUND: period size: 1764 frames, dir: 0

Вот соответствующая часть из цикла заполнения, которая вызывается неоднократно:

log.debug("play %d samples", n);
while ((ret = snd_pcm_writei(handle, playBuf, n)) != (long)n) {
    if (ret < 0) {
        log.warn("ALSA error: %s\n", snd_strerror(ret));
        if ((ret = snd_pcm_recover(handle, ret, 0)) < 0) {
            log.error("ALSA error after recover: %s\n", snd_strerror(ret));
            checkFatalAlsaError(snd_pcm_prepare(handle), "ALSA irrecoverable error: %s");
        }
    } else {
        log.warn("ALSA short write...?\n");
        break;
    }
}

Вот журнал, когда все хорошо:

3751.3029 D [AlsaSound] Starting square sound, nsamples: 3528, nPeriods: 2, nFrames: 1764
3751.3030 D [AlsaSound] play 1739 samples
3751.3037 D [AlsaSound] play 1739 samples
3751.3046 D [AlsaSound] play 50 samples
3751.3048 D [AlsaSound] Stop sound

И иногда я получаю это:

3752.8764 D [AlsaSound] Setup square sound, time: 800, nsamples: 3528
3752.8769 D [AlsaSound] Starting square sound, nsamples: 3528, nPeriods: 2, nFrames: 1764
3752.8770 D [AlsaSound] play 1739 samples
3752.8779 D [AlsaSound] play 1739 samples
3752.8782 W [AlsaSound] ALSA error: Broken pipe
ALSA lib ../../../alsa-lib-1.1.4.1/src/pcm/pcm.c:8323:(snd_pcm_recover) underrun occurred
3752.8792 D [AlsaSound] play 50 samples
3752.8793 D [AlsaSound] Stop sound

Из временных меток журнала видно, что опустошение происходит в течение 2 мс после первой записи - что записывает ~ 40 мсек выборок. Два показанных примера идентичны в любом другом случае, устройство не воспроизводит звук и является prepare () 'd.

В чем может быть проблема, и решение?

Обратите внимание, что намеренно я пишу меньше выборок, чем размер периода.

ядро ​​Linux версии 4.9.87, libasound2 версии 1.1.4.1-r0, платформа ARM (Colibri iMX6)

...