ALSA: Ways to prevent underrun for speaker

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

I am playing a single channel audio in non-interleaved mode. I am getting underrun when I am writing aduio data into speaker : ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred

Here is how I write:

    printf("%d",snd_pcm_avail (spkhandle));       ret = snd_pcm_writen(spkhandle, pSpeakerBuf , framesIn18Millisec);     if(ret < 0)     {         snd_pcm_recover(spkhandle, ret, 0);     } 

What are the different ways/parameter configurations to prevent ALSA under run ?

(I am using Linux 3.0, ARM )

Edit: Here is a buffer measurement using snd_pcm_avail() API

      snd_pcm_avail = 2304      << snd_pcm_writen call 1 success       snd_pcm_avail = 2160      << snd_pcm_writen call 2 success       snd_pcm_avail = 2016      << snd_pcm_writen call 3 success       snd_pcm_writen error -32 Broken pipe  << snd_pcm_writen call 4 failure       ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred  << And displays this message 

Here is the output that Marko requested for:

snd_output_t* out; .... // Do alsa parameters init ....  .... snd_output_stdio_attach(&out, stderr, 0); snd_pcm_dump_sw_setup(spkhandle, out);    tstamp_mode  : NONE   period_step  : 1   avail_min    : 144   period_event : 0   start_threshold  : 288   stop_threshold   : 2304   silence_threshold: 0   silence_size : 0   boundary     : 1207959552 

回答1:

I assume this code runs in a tight loop and is intended to block on snd_pcm_writen(). The sample-rate isn't given; I assume 48kHz since the numbers all divide nicely.

What I think is going here is as follows:

  • snd_pcm_write() doesn't guarantee to write all frames provided (the return value is only ever checked for error conditions). Judging from the logging of snd_pcm_avail() it's in fact consuming avail_min or 144 frames on each. This is 3ms of audio.
  • Assuming that audio is not running at this point, after two writes, the number of frames in the buffer is equal to start_threshold - at 288 samples; audio output starts
  • calls to printf() block, and I seem to remember that snd_pcm_avail() has to synchronise with the audio output hardware and might also block. Since you are now 6ms ahead of the playback, it's entirely possible that the buffer is running dry during the time of the third call of snd_pcm_writen()

In summary, you shouldn't be calling printf() at this point, and you probably need to compensate for fact that snd_pcm_writen() isn't consuming all of the frames in pSpeakerBuf



回答2:

It is the buffer underrun,You can try increasing the buffer size by explicitly mentioning it in your ~/.asoundrc file ?



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!