【发布时间】: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 秒周期?
感谢您的帮助。 戴尔·彭宁顿
【问题讨论】: