采样率偏差和声音播放位置

Sampling rate deviation and sound playing position

本文关键字:播放 位置 声音 采样率      更新时间:2023-10-16

当您将声卡速率设置为例如44100时,无法保证实际速率等于44100。在我的案例中,应用程序和ALSA之间的流量测量值(以样本/秒为单位)为44066…44084。

这不应该与重新采样问题有关:即使只有-48000个硬件也必须在"44100"模式下以44100的速率"吃掉"数据。

当我试图在播放波形时将光标绘制在波形上时,就会出现问题。我使用从WAV文件读取的"理想"采样率(22050,…,44100,…,48000)和播放开始后花费的毫秒来计算光标位置,使用以下C++函数:

long long getCurrentTimeMs(void)
{
    boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
    boost::posix_time::ptime    epoch_start(boost::gregorian::date(1970,1,1));
    boost::posix_time::time_duration dur = now - epoch_start;
    return dur.total_milliseconds();
}

QTimer用于为光标动画生成帧,但我不依赖于QTimer的精度,因为我通过每帧获取CurrentTimeMs()来请求时间(假设它足够精确),所以我可以使用不同的帧速率。

播放2-3分钟后,我看到我听到的和看到的有点不同——光标位置比播放位置大了大约1/20秒。

当我测量通过ALSA回调的流量时,我得到44083.7个样本/秒的平均值。然后我在屏幕绘制函数中使用这个值作为实际速率。现在问题消失了。这个程序是跨平台的,所以我稍后会在windows和另一个声卡上测试这个测量值。

但是有更好的方法来同步声音和屏幕吗?例如,是否有一些不太消耗CPU的方式来询问声卡的实际播放样本数?

这是一种已知的效果,例如在Windows中,通过Rate Matching解决,在此处Live Sources进行了描述。

在播放时,通常通过使用音频硬件作为"时钟"并同步到音频播放而不是"实际"时钟来解决效果。也就是说,例如,在音频采样率为44100的情况下,25fps视频的下一视频帧与44100/25采样回放同步呈现,而不是使用1/25系统时间增量。这补偿了不精确的有效播放速率。

在捕获时,硬件本身的行为就好像它正以所请求的速率传递数据一样。我认为你能做的最好的事情就是测量有效率,并将音频从有效率重新采样到正确的采样率。