Android OpenSL ES 晶振频率

标签 android audio android-ndk opensl

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

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

手机内部晶体频率似乎变化很大,正因为如此,我们在开始时得到了完美的对齐,但几分钟后对齐不佳。

我知道,Linux 上的 ALSA 可以告诉你晶体的确切频率——所以你可以根据这个来纠正你的计数。不幸的是,我不知道如何在 Android 中获取这些信息。

谢谢帮助

最佳答案

您面临的问题的本质是您在具有不同本地振荡器的不同系统上拥有一个 ADC 和一个 DAC。您可能正在根据第三个(也可能是第四个)CPU 时钟来计时您的数据包。

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

由于可能无法执行这些操作,因此您的方法很可能涉及定期丢弃或重复样本(甚至整个数据包),以防止接收缓冲区不足或溢出。

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

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

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

关于Android OpenSL ES 晶振频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17532520/

相关文章:

android - 带有 Google API 的三星 Galaxy Tab AVD?

android - 使用 FirebaseRecyclerAdapter 进行 Firebase 搜索 (Firebase UI 3.2.2)

c++ - 这个 GetDefaultAudioEndpoint 程序有什么问题?

android - 无法写入 ARM 寄存器 R4 : feature or bug?

android - 交叉编译 Android 和依赖项

android - 在 Mac 上编译 x264 : "No working C compiler found" and "arm-linux-androideabi-gcc: command not found"

android - 如何使选项菜单始终显示在屏幕上

android - 使用xml进行布局有什么好处?

python 合唱效果和音频数据的含义

ios - Swift 合并音视频 Swift3