Я схожу с ума от ложных ошибок опустошения при вызовах 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)