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

标签 c++ audio callback synchronization alsa

例如,当您将声卡速率设置为 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 的精度,因为我通过 getCurrentTimeMs() 询问时间(假设它足够精确)每一帧,所以我可以使用不同的帧率。

播放 2-3 分钟后,我发现听到的和看到的略有不同 - 光标位置大于播放位置大约 1/20 秒。

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

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

最佳答案

这是一个已知的效果,例如在 Windows 中通过速率匹配解决,此处描述 Live Sources .

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

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

关于c++ - 采样率偏差和声音播放位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9767009/

相关文章:

c++ - 使用 Boost datetime 如何创建一个用零填充的月份字符串?

android - 如何在 Android 中通过 1/4"电缆从连接到 3.5mm 音频插孔的乐器捕获音频信号?

android - 每次按下按钮时重复声音

javascript - 嵌套的、依赖的回调函数

c++ - Qt 实例 const_cast

c++ - 如何检查分配给调用运算符结果的类型?

C++:使用动态内存创建动态数组

android - Android 浏览器中的 HTML5 音频/视频加载问题

android - 分享消息后从whatsapp回调

javascript - 如何确定 javascript 回调中必要的参数