我为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()中。
可能是什么问题以及解决方案?
请注意,我故意写的样本少于期间大小。
Linux内核4.9.87版,libasound2版本1.1.4.1-r0,ARM(Colibri iMX6)平台