7

我在非交错模式下播放单声道音频。当我将音频数据写入扬声器时,我遇到了不足:ALSA lib pcm.c:7339:(snd_pcm_recover) underrun occurred

这是我的写作方式:

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

有哪些不同的方式/参数配置可以防止 ALSA under run ?

(我使用的是 Linux 3.0、ARM)

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

这是 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
4

2 回答 2

6

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

我认为这里的情况如下:

  • snd_pcm_write()不保证写入提供的所有帧(返回值只检查错误情况)。从记录来看,snd_pcm_avail()它实际上是消耗avail_min144每个框架。这是 3ms 的音频。
  • 假设此时音频没有运行,两次写入后,缓冲区中的帧数等于start_threshold- at 288samples;音频输出开始
  • 调用printf()阻塞,我似乎记得snd_pcm_avail()必须与音频输出硬件同步,也可能阻塞。由于您现在比播放时间提前了 6 毫秒,因此在第三次调用snd_pcm_writen()

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

于 2013-01-30T15:30:28.793 回答
1

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

于 2013-01-30T10:33:08.330 回答