我正在审核各种Android声音API,我想知道应该使用哪一种。 我的目标是获得低延迟音频,或者至少是关于播放延迟的确定性行为。
我们遇到了很多问题,似乎Android声音API是废话,所以我正在探索各种可能性。
我们遇到的问题是sound_out.write(sound_samples);
与扬声器播放的实际声音之间存在显着延迟。通常它大约是300毫秒。问题是在所有设备上它都是不同的;有些人没有这个问题,但大多数人都瘫痪了(但是,CS呼叫的延迟为零)。这种荒谬的延迟最大的问题是,在某些设备上,这种延迟似乎是一些随机值(即它并不总是300毫秒)。
我正在阅读有关OpenSL ES的内容,我想知道是否有人有过使用它的经验,或者它是相同的狗屎而是包装在不同的包中?
我更喜欢本机访问,但我不介意Java层间接,只要我能获得确定性行为:延迟必须是常量(对于给定设备),或者我想要访问到当前播放位置,而不是用±300 ms的误差范围猜测...
编辑: 1。1年后,我尝试了多款Android手机,看看如何为实时语音通信获得最佳延迟。使用专业工具我测量了波浪路径的延迟。最佳结果超过100毫秒,大多数手机都在180毫秒范围内。有人有想法吗?
答案 0 :(得分:27)
SoundPool是大多数设备上延迟最低的接口,因为池存储在音频过程中。所有其他音频路径都需要进程间通信。如果SoundPool不能满足您的需求,OpenSL是最佳选择。
为什么选择OpenSL? AudioTrack和OpenSL具有类似的延迟,但有一个重要的区别:AudioTrack缓冲区回调在Dalvik中提供服务,而OpenSL回调在本机线程中提供服务。 Dalvik的当前实现无法以极低的延迟为回调提供服务,因为在音频回调期间无法暂停垃圾收集。这意味着AudioTrack缓冲区的最小大小必须大于OpenSL缓冲区的最小大小,以维持无故障播放。
在大多数Android版本中,AudioTrack和OpenSL之间的差异完全没有区别。但是对于Jellybean,Android现在有一个低延迟的音频路径。实际延迟仍取决于设备,但可能比以前低得多。例如,http://code.google.com/p/music-synthesizer-for-android/在Galaxy Nexus上使用384帧缓冲区,总输出延迟低于30毫秒。这要求音频线程大约每8ms一次服务缓冲区,这在之前的Android版本中是不可行的。在Dalvik线程中它仍然不可行。
这个解释假设有两件事:第一,你是从OpenSL请求最小的缓冲区,并在缓冲区回调而不是缓冲区队列中进行处理。其次,您的设备支持低延迟路径。在大多数现有设备上,您不会发现AudioTrack和OpenSL ES之间存在太大差异。但是在支持Jellybean +和低延迟音频的设备上,OpenSL ES将为您提供最低延迟的路径。
答案 1 :(得分:2)
令人遗憾的是,Android上没有低延迟音频这样的东西。甚至没有一种基于音频延迟标记和/或过滤设备的正确方法。
您希望使用哪种界面来最小化延迟取决于您要执行的操作。 如果你想要一个音频流,你将会看到OpenSL或AudioTrack。
如果你想触发一些静态的射击,你可能想要使用SoundPool。对于静态单触发,当样本预加载到硬件时,SoundPool将具有低延迟。我认为也可以使用OpenSL预加载onehots,但我还没试过。
答案 2 :(得分:1)
您可以获得的最低延迟来自SoundPool。你可以用这种方式播放声音有多大限制,但是如果你达到极限(1Mb,IIRC),它的延迟相当低。尽管那可能不是40毫秒。
但它比你通过流媒体获得的速度更快,至少根据我的经验。
警告:您可能会在三星设备上的SoundPool中偶尔看到崩溃。我有一个理论,它只会在你从多个线程访问SoundPool时发生,但我还没有验证过。
编辑:OpenSL ES在Kindle Fire上显然具有极高的延迟,而SoundPool则要好得多,但在其他平台上则相反。答案 3 :(得分:0)
关于确定性/恒定延迟的问题,在这里您可以找到有趣的文章:
APPROACHES FOR CONSTANT AUDIO LATENCY ON ANDROID
他们研究的核心是:由于音频HAL是音频路径的更深层之一,负责音频回调事件的计时,因此由供应商实现,相对延迟可能会有所不同,尤其是在便宜的硬件。 因此,他们提出了两种方法来减少延迟的差异。一种是通过以固定的时间间隔插入音频来照顾回调定时,另一种是通过应用平滑滤波器来过滤回调时间,以估计应发生恒定等待时间回调的时间。 通过这两种方法,可以显着减少延迟的差异。
还应该提到的是,有一个新的本地Android-Audio-API,即AAudio。
它在Android Oreo 8.1(API级别27)中可用/稳定。 还有一个包装器,可以在OpenSL ES和AAudio之间动态选择,并且更容易编码OpenSL ES。它仍在开发人员预览中。
答案 4 :(得分:0)
在Android上降低本机代码延迟的最佳方法是使用Oboe。
https://github.com/google/oboe
Oboe将AAudio包装在较新的设备上。 AAudio提供了最低的延迟路径。如果AAudio不可用,则Oboe会调用OpenSL ES。 Oboe比OpenSL ES更易于使用。
AAudio通过AudioTrack或新的MMAP数据路径进行调用。由于您可以保留一些未指定的参数,因此AAudio使其更容易获得FAST轨道。然后,AAudio将选择FAST轨道所需的正确参数。