Linux ALSA:防止扬声器欠载的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14601666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:51:28  来源:igfitidea点击:

ALSA: Ways to prevent underrun for speaker

clinuxaudioalsa

提问by Lunar Mushrooms

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

我正在以非交错模式播放单声道音频。当我将音频数据写入扬声器时,我的速度不足: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 ?

防止 ALSA 运行的不同方式/参数配置有哪些?

(I am using Linux 3.0, ARM )

(我使用的是 Linux 3.0,ARM)

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

编辑:这是使用 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:

这是 Marko 要求的输出:

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

采纳答案by marko

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.

我假设这段代码在一个紧密的循环中运行,并且旨在阻止snd_pcm_writen(). 没有给出采样率;我假设 48kHz,因为数字都很好地划分。

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_minor 144frames 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 288samples; 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()
  • snd_pcm_write()不保证写入提供的所有帧(返回值只检查错误情况)。从snd_pcm_avail()它的日志记录来看,它实际上是消耗avail_min144每个帧。这是 3 毫秒的音频。
  • 假设音频不会在这一点上运行时,两个写之后,在缓冲器中的帧的数目等于start_threshold-在288样本; 音频输出开始
  • 调用printf()阻塞,我似乎记得它snd_pcm_avail()必须与音频输出硬件同步,也可能阻塞。由于您现在比回放提前 6 毫秒,因此在第三次调用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

总之,此时您不应该调用printf(),并且您可能需要补偿snd_pcm_writen()没有消耗所有帧的事实pSpeakerBuf

回答by Rahul

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

这是缓冲区不足,您可以尝试通过在 ~/.asoundrc 文件中明确提及来增加缓冲区大小?