ALSA:防止扬声器欠载的方法 [英] ALSA: Ways to prevent underrun for speaker

查看:127
本文介绍了ALSA:防止扬声器欠载的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在以非交错模式播放单声道音频.当我将音频数据写入扬声器时出现欠载:ALSA lib pcm.c:7339:(snd_pcm_recover) underrun发生

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

我是这样写的:

    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有哪些不同的方式/参数配置?

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

(我使用的是 Linux 3.0,ARM)

(I am using Linux 3.0, ARM )

这是使用 snd_pcm_avail() API 的缓冲区测量

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

这是 Marko 要求的输出:

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

推荐答案

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

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

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

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

这篇关于ALSA:防止扬声器欠载的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆