我正在用C编写一个小模块来处理全双工音频系统的抖动和漂移。它充当一个非常原始的语音聊天模块,连接到使用独立时钟的外部调制解调器,独立于我的主系统时钟(即:它不受系统主时钟限制)。
该来源基于在线提供的现有示例:http://svn.xiph.org/trunk/speex/libspeex/jitter.c
我有4个音频流:
我有两个独立的执行线程。一个处理本地设备和缓冲区(即:将处理后的音频播放到扬声器,从麦克风捕获数据并将其传递到DSP处理库以消除背景噪声,回声等)。另一个线程处理拉动网络下行链路信号并将其传递到处理库,并从库中获取处理后的数据并通过上行链路连接推送它。
两个线程使用互斥锁和一组共享循环/环形缓冲区。我正在寻找一种方法来实现一个确定的(安全可靠的)抖动和漂移校正机制。通过抖动,我指的是一个具有可变占空比但与理想时钟频率相同的时钟。
我需要纠正的另一个潜在问题是漂移,假设两个时钟都使用理想的50%占空比,但它们的基频偏差为±5%。
最后,这两个问题可以同时发生。什么是理想的方法?我目前的方法是使用一种抖动缓冲区。它们只是数据缓冲区,它实现移动平均值来计算它们的平均“填充”级别。如果一个线程试图从缓冲区读取,并且没有足够的数据可用并且存在缓冲器下溢,我只需通过提供备用的归零数据包或通过复制数据包即时生成数据(即:丢包隐藏)。如果数据进入太快,我会丢弃整个数据包,并继续前进。这会处理抖动部分。
问题的后半部分是漂移校正。这是平均填充水平指标有用的地方。对于所有缓冲区,我可以计算各种缓冲区中的相对增长/减少水平,并且每隔一段时间增加或减少少量样本,以便所有缓冲区水平都悬停在共同的平均“填充”水平附近。
这种方法是否有意义,是否有更好或“行业标准”的方法来处理这个问题?
谢谢。
参考
<http://www.apogeedigital.com/knowledgebase/fundamentals-of-digital-audio/word-clock-whats-the-difference-between-jitter-and-frequency-stability/>
<http://svn.xiph.org/trunk/speex/libspeex/jitter.c>
答案 0 :(得分:2)
我很想知道这是否可行。我会扔掉我的两位。
我是一名新手程序员,但学习过音频工程/互动音频。
我的第一个假设是这是不可能的。至少不是基于样本到样本。尤其不适用于复杂的音频数据和人类语音等波形。该程序可能没有预期波形“应该”的样子。
这就是具有温度控制内部时钟的高端音频接口的原因。
另一方面,也许有一个库可以检测出抖动的症状,不知何故...... 在这种情况下,我会很好奇地听到它。
就漂移校正而言,我可能不了解编程方面的内容,但是你不应该以特定的采样率拉动音频吗?我相信采样率/漂移是在硬件级别处理的。
我真的希望这会有所帮助。你可能不得不让我离家更近。
答案 1 :(得分:2)
我遇到了一个类似但虽然简单的问题。我无法完全回答你的问题,但我希望分享我遇到的一些实际问题的解决方案,无论如何都会让你受益。
去年我正在开发一个系统,它应该同时记录和呈现多个音频设备,每个音频设备可能会勾选不同的时钟。最明显的例子是2个设备上的双工流,但它也只处理多个输入/输出。总而言之,比你的情况(单线程和没有网络i / o)简单一点。最后,我不相信处理2个以上的设备比2更难,任何有多个时钟的系统都必须处理同样的问题。
我学到了一些东西:
总而言之,我说你的解决方案看起来很合理,虽然我不确定&#34;丢弃整个数据包的事情&#34;我绝对会选择一个流作为主人来同步。为了完整性,我最终提出了解决方案:
这个方案对我来说非常好,虽然还有一些事情需要考虑:
此外,PortAudio(开源音频项目)实施了类似的方案,请参阅http://www.portaudio.com/docs/proposals/001-UnderflowOverflowHandling.html。浏览邮件列表并查看有哪些问题/解决方案可能是值得的。
请注意,到目前为止我所说的一切只是与音频硬件的互动,我不知道这是否能够与网络流同样有效,但我看不出任何明显的为什么不呢。只需选择1个音频流作为主设备,然后将另一个音频流同步到它,并对网络流执行相同操作。这样,您最终会得到两个或多或少的独立系统,这些系统仅由环形缓冲器连接,每个系统都有一个内部一致的时钟,每个时钟都运行在它自己的线程上。如果您的目标是降低音频延迟,那么您还需要删除互斥锁并选择某种类型的无锁FIFO。