【问题标题】:ALSA Capture missing framesALSA 捕获丢失的帧
【发布时间】:2020-04-20 02:57:46
【问题描述】:

我继承了一段代码,它使用 ALSA 来捕获 8KHz、8 位、1 通道的音频输入。代码看起来很简单,它将通道设置为 1,速率设置为 8000,周期大小设置为 8000。该程序的目标是一次收集 30 多分钟的音频数据。

主循环看起来像

int retval;
snd_pcm_uframes_t numFrames = 8000;

while (!exit)
{
   // Gather data
   while( (unsigned int)(retval = snd_pcm_readi ( handle, buffer, numFrames ) ) != numFrames )
   {
      if( retval == -EPIPE )
      {
         cerr << "overrun " << endl;
         snd_pcm_prepare( handle );
      } 
      else if ( reval < 0 )
      {
         cerr << "Error : " << snd_strerror( retval ) << endl;
         break;
      }
   }

   // buffer processing logic here
}

我们遇到了行为问题(每秒没有获得完整的 8K 样本,而且时间很奇怪),所以我在 snd_pcm_readi 循环周围添加了 gettimeofday 时间戳,以查看时间是如何使用的,我得到了以下信息:

循环 1:1.017 秒 循环 2:2.019 秒 循环 3:0(小于 1ms) 循环 4:2.016 秒 循环 5:.001 秒

.. 2 循环模式继续(偶数运行 2.01x 秒,奇数运行 0-1 毫秒)在剩余的运行中。这意味着我平均每秒获得的样本少于 8000 个(每运行 10 分钟损失似乎约为 3 秒)。这与其他收集的数据不能很好地同步。此外,我们希望以大约 1 秒的间隔处理数据,而不是每 2 秒左右有 2 个背靠背进程。 作为附加检查,我打印出缓冲区值正在设置硬件参数,我得到以下信息:

缓冲区大小:43690 周期 : 5 期间大小:8000 周期时间:1000000 费率:8000

所以最后我有两个问题:

1) 为什么我得到低于 8 Khz 的实际数据? (可能的理论,实际硬件并不完全是 8KHz,即使 ALSA 认为它可以做到)。

2) 为什么读取的 2 秒/0 秒循环应该是 1 秒?怎样才能让它达到真正的 1 秒周期?

感谢您的帮助。 戴尔·彭宁顿

【问题讨论】:

    标签: c++ alsa


    【解决方案1】:

    snd_pcm_readi() 返回尽可能多的可用样本。如果设备处于非阻塞模式,它不会等待更多。

    您只有retval 样本。如果您想一次处理 8000 个样本,请在循环中使用剩余缓冲区调用 snd_pcm_readi()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-28
      • 2011-04-26
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 2020-05-25
      • 2014-01-24
      • 1970-01-01
      相关资源
      最近更新 更多