Android OpenSL ES水晶频率

时间:2013-07-08 17:23:36

标签: android audio android-ndk opensl

我们有一个应用程序,其中移动音频客户端使用低级OpenSL ES编写,以实现麦克风的低延迟输入。比我们发送封装在UDP数据报中的10ms帧到服务器。

在服务器上,我们正在进行一些后处理,这在很大程度上取决于假设来自移动客户端的帧以固定间隔(例如,每帧10毫秒)进行,因此我们可以对齐它们。

手机上的内部晶体频率似乎变化很大,因此,我们在几分钟后就开始完美对齐,但对齐不良。

我知道,Linux上的ALSA可以告诉您晶体的准确频率 - 因此您可以根据此更正您的计数。不幸的是,我不知道如何在Android中获取这些信息。

寻求帮助

1 个答案:

答案 0 :(得分:3)

您遇到的问题的实质是您在具有不同本地振荡器的不同系统上具有ADC和DAC。你可能是针对第3个(可能是第4个)CPU时钟计数你的数据包。

这个问题的正确解决方案是某种clock recovery算法。要做到这一点,你需要一些精确时间戳(例如比特精度)传输数据包的方法,然后使用PLL来驱动接收器采样时钟的时钟速率。这正是IEEE1394音频和MPEG2传输流使用的方法。

由于可能无法执行上述任何一项操作,因此您的方法很可能会定期丢弃或重复采样(甚至整个数据包),以防止接收缓冲区过流或过流。

USB音频类似缺乏对时钟恢复的硬件支持,并且那里使用的方法可能适用于您的情况。

依赖网络数据包的传输和接收时间是一个可怕的想法。交付时间的抖动是可怕的 - 特别是对于Wifi或蜂窝连接。建议你完全不要依赖它,而是像IEEE1394音频和MPEG 2 TS那样做,即使用模型FIFO将音频数据传输与消耗分离,其中数据以恒定速率消耗并以不可靠的时间包传送给它。

对于ALSA,它所能做的就是(除非有精确的外部定时参考)是测量音频接口的采样时钟和CPU时钟之间的漂移。这不会产生任何东西的“确切频率”,因为两个振荡器都不可能准确,并且两者都可能随温度而变化。