Android:声音API(确定性、低延迟)

Android:声音API(确定性、低延迟),android,android-ndk,Android,Android Ndk,我正在回顾各种Android声音API,我想知道我应该使用哪一种。 我的目标是获得低延迟音频,或者至少是关于播放延迟的确定性行为 我们遇到了很多问题,而且Android声音API似乎是垃圾,所以我正在探索各种可能性 我们的问题是,sound\u out.write(sound\u samples)之间存在明显的延迟和扬声器播放的实际声音。通常是300毫秒左右。问题是,在所有设备上,它都是不同的;有些并没有这个问题,但大多数是残废的(然而,CS调用的延迟为零)。这种荒谬延迟的最大问题是,在某些设备

我正在回顾各种Android声音API,我想知道我应该使用哪一种。 我的目标是获得低延迟音频,或者至少是关于播放延迟的确定性行为

我们遇到了很多问题,而且Android声音API似乎是垃圾,所以我正在探索各种可能性

我们的问题是,
sound\u out.write(sound\u samples)之间存在明显的延迟和扬声器播放的实际声音。通常是300毫秒左右。问题是,在所有设备上,它都是不同的;有些并没有这个问题,但大多数是残废的(然而,CS调用的延迟为零)。这种荒谬延迟的最大问题是,在某些设备上,这种延迟似乎是某个随机值(即,它并不总是300ms)

我正在阅读有关OpenSL ES的文章,我想知道是否有人有过使用它的经验,或者它是相同的东西,但包装在不同的包中

我更喜欢本机访问,但我不介意Java层间接寻址,只要我可以获得确定性行为:要么延迟必须是恒定的(对于给定的设备),要么我想访问当前播放位置,而不是猜测它的误差范围为±300毫秒


编辑:
1.5年后,我尝试了多部android手机,以了解如何获得最佳的实时语音通信延迟。我使用专用工具测量了waveout路径的延迟。最好的结果是超过100毫秒,大多数手机都在180毫秒范围内。有人有想法吗?

您可以从SoundPool获得最低延迟。用这种方式播放的声音大小是有限制的,但如果低于限制(1Mb,IIRC),则延迟相当低。尽管如此,这也可能不是40毫秒

但至少以我的经验来看,它比流媒体更快

警告:您可能会看到三星设备上的SoundPool偶尔出现崩溃。我有一个理论,只有当你从多个线程访问声音池时,才会发生这种情况,但我还没有证实这一点


编辑:OpenSL ES显然在Kindle Fire上具有极高的延迟,而SoundPool要好得多,但在其他平台上可能正好相反。

IIRC,OpenSL通过与AudioTrack相同的接口,因此它最多只能与AudioTrack匹配。(FWIW,我目前正在使用OpenSL进行“低延迟”输出)

可悲的事实是,Android上没有低延迟音频。甚至没有一种基于音频延迟来标记和/或过滤设备的正确方法

您希望使用什么接口来最小化延迟将取决于您尝试执行的操作。 如果你想有一个音频流,你将看到OpenSL或AudioTrack


如果您想触发一些静态oneshots,您可能需要使用SoundPool。对于静态oneshots,当样本预加载到硬件时,SoundPool将具有较低的延迟。我认为也可以使用OpenSL预加载oneshots,但我没有尝试过。

SoundPool是大多数设备上延迟最低的接口,因为该池存储在音频进程中。所有其他音频路径都需要进程间通信。如果SoundPool不能满足您的需求,OpenSL是最佳选择

为什么是OpenSL?AudioTrack和OpenSL具有相似的延迟,但有一个重要区别:AudioTrack缓冲区回调在Dalvik中提供服务,而OpenSL回调在本机线程中提供服务。Dalvik的当前实现无法以极低的延迟为回调提供服务,因为在音频回调期间无法挂起垃圾收集。这意味着AudioTrack缓冲区的最小大小必须大于OpenSL缓冲区的最小大小,以保持无故障播放

在大多数Android版本中,AudioTrack和OpenSL之间的差异根本没有任何区别。但是有了Jellybean,Android现在有了一个低延迟的音频路径。实际延迟仍然取决于设备,但可能比以前低很多。例如,在Galaxy Nexus上使用384个帧缓冲区,总输出延迟不到30毫秒。这需要音频线程大约每8毫秒为缓冲区服务一次,这在以前的Android版本中是不可行的。在Dalvik线程中仍然不可行


这个解释假设了两件事:首先,您正在从OpenSL请求尽可能小的缓冲区,并在缓冲区回调中而不是使用缓冲区队列进行处理。其次,您的设备支持低延迟路径。在大多数当前设备上,您不会看到AudioTrack和OpenSL ES之间有多大区别。但在支持Jellybean+和低延迟音频的设备上,OpenSL ES将为您提供最低延迟路径。

关于确定性/恒定延迟的问题,您可以在这里找到一篇有趣的文章:

他们调查的核心是:由于音频HAL是音频路径的深层次之一,负责音频回调事件的计时,由供应商实施,因此相对延迟可能会有所不同,特别是在廉价硬件中。 因此,他们提出了两种方法来减少延迟的变化。一种是通过以固定的间隔插入音频来处理回调时间,另一种是通过应用平滑过滤器来过滤回调时间,以估计发生恒定延迟回调的时间。 使用这两种方法,可以显著减少延迟的变化

还应该提到的是,有一个新的原生Android音频API,AAudio

它可以从Android Oreo 8.1(API级别27)获得/稳定。 还有一个包装器,它可以在OpenSL ES和AAudio之间动态选择,并且更容易编写OpenSL ES。它仍在开发者预览中


在Android上实现本地代码低延迟的最佳方法是使用双簧管

双簧管