【发布时间】:2014-09-13 21:43:00
【问题描述】:
我正在用 C 语言编写一个小模块来处理全双工音频系统的抖动和漂移。它作为一个非常原始的语音聊天模块,连接到一个使用独立时钟的外部调制解调器,独立于我的主系统时钟(即:它不从系统主时钟的奴隶)。
源代码基于此处在线提供的现有示例:http://svn.xiph.org/trunk/speex/libspeex/jitter.c
我有 4 个音频流:
- 网络上行(我的声音,经过处理,送到远端扬声器)
- 网络下行(远端的声音,在处理之前,来到我这里)
- 扬声器输出(远端的声音,经过处理后,发送到本地扬声器)
- 麦克风输入(我的声音,在处理之前,来自本地麦克风)
我有两个独立的执行线程。一个处理本地设备和缓冲区(即:将处理后的音频播放到扬声器,并从麦克风捕获数据并将其传递给 DSP 处理库以消除背景噪声、回声等)。另一个线程负责拉取网络下行信号并将其传递给处理库,并从库中取出处理后的数据并通过上行连接推送。
两个线程使用互斥锁和一组共享的循环/环形缓冲区。我正在寻找一种方法来实现可靠(安全可靠)的抖动和漂移校正机制。抖动是指具有可变占空比的时钟,但与理想时钟的频率相同。
我需要纠正的另一个潜在问题是漂移,假设两个时钟都使用理想的 50% 占空比,但它们的基本频率偏离了 ±5%。
最后,这两个问题可以同时发生。理想的方法是什么?我目前的方法是使用一种抖动缓冲器。它们只是实现移动平均值以计算其平均“填充”水平的数据缓冲区。如果一个线程试图从缓冲区读取,但没有足够的数据可用并且存在缓冲区下溢,我只是通过提供一个备用的清零数据包或复制一个数据包即时为其生成数据(即:丢包隐藏)。如果数据来得太快,我会丢弃整个数据包,然后继续。这会处理抖动部分。
问题的后半部分是漂移校正。这就是平均填充水平指标派上用场的地方。对于所有缓冲区,我可以计算各种缓冲区中的相对增长/减少水平,并每隔一段时间添加或减去少量样本,以使所有缓冲区水平徘徊在一个共同的平均“填充”水平附近。
这种方法是否有意义,是否有更好的或“行业标准”的方法来处理这个问题?
谢谢。
参考文献
-
字时钟 - 抖动和频率漂移有什么区别?,2014 年 9 月 13 日访问,
<http://www.apogeedigital.com/knowledgebase/fundamentals-of-digital-audio/word-clock-whats-the-difference-between-jitter-and-frequency-stability/> -
Jitter.c,于 2014 年 9 月 13 日访问,
<http://svn.xiph.org/trunk/speex/libspeex/jitter.c>
【问题讨论】:
标签: c multithreading audio clock