我继承了一段使用ALSA捕获8 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-1ms)。这意味着我平均每秒得到的样本少于8000个(每10分钟的运行损失似乎是3秒)。这与其他收集的数据不能很好地同步。此外,我们希望以大约1秒的间隔处理数据,而不是每隔2秒左右进行2个背靠背的处理。作为额外的检查,我打印出了设置硬件参数的缓冲值,并得到了以下结果:
缓冲区大小: 43690周期:5周期大小: 8000周期时间: 1000000速率: 8000
所以最后我有两个问题:
1)为什么会得到小于8 Khz的实际数据?(可能的理论是,实际的硬件频率不是8 8KHz,即使ALSA认为它可以做到)。
2)为什么读取需要2秒/0秒的周期,每次读取应该是1秒?那么,怎样才能让它达到真正的1秒周期呢?
谢谢你的帮助。戴尔·彭宁顿
发布于 2020-01-02 15:18:02
snd_pcm_readi()会返回尽可能多的可用样本。如果设备处于非阻塞模式,它将不会等待更多。
您只有retval示例。如果您希望一次处理8000个样本,请使用剩余的缓冲区在循环中调用snd_pcm_readi()。
https://stackoverflow.com/questions/59546482
复制相似问题