Android上的低延迟audio播放

我目前正试图最小化一个简单的应用程序的audio延迟:

我在PC上有一个video,我通过RTP将video的audio传输到移动客户端。 使用非常相似的缓冲algorithm,我可以在iOS上实现90毫秒的延迟,但在Android上可达到±180毫秒。

我猜测这种差异源于Android上众所周知的延迟问题 。

然而,在阅读了一下之后, 我发现了这篇文章 ,里面写道:

  1. 低延迟audio从某些设备的Android 4.1 / 4.2版本开始可用。

  2. 低延迟audio可以使用libpd(Android的Pure Data library)来实现 。

我有两个问题,直接关系到那两个陈述:

  1. 我在哪里可以find有关Jellybean中新的低延迟audio的更多信息? 这是我能find的所有东西,但缺乏具体的信息 。 如果这些变化对我来说是透明的,还是有一些新的类/ API调用,我应该为我注意到我的应用程序中的任何变化? 我正在使用AudioTrack API,我甚至不知道是否应该从这种改进中获益,或者我应该考虑用于audio播放的其他机制。

  2. 我应该看看使用libpd吗? 在我看来,这是我获得较低延迟的唯一机会,但是由于我一直认为PD是一个audio合成实用程序,它是否真的适合于从networkingstream中抓取帧并播放它的项目? 我没有真正做综合。 我跟着错误的线索?

另外还有一点需要注意的是,在有人提到OpenSL ES之前, 这篇文章明确表示,不应该期望延迟的改进。

“由于OpenSL ES是一个本地C API,调用OpenSL ES的非Dalvik应用程序线程没有Dalvik相关的开销,例如垃圾收集暂停,但除此之外,使用OpenSL ES没有额外的性能优势。特别是使用OpenSL ES不会导致比平台通常提供的更低的audio延迟,更高的调度优先级等。

对于Android 4.2.2以来的最低延迟,您应该执行以下操作,从最不明显的顺序排列:

  1. 如果可能,select支持FEATURE_AUDIO_PRO的设备,否则selectFEATURE_AUDIO_LOW_LATENCY。 (“低延迟”是50ms,单程<20ms)。

  2. 使用OpenSL。 Dalvik GC具有较低的分摊成本,但是在运行时需要比低延迟audio线程所允许的更多的时间。

  3. 在缓冲区队列callback中处理audio。 系统在比正常用户模式线程更有利的调度的线程中运行缓冲区队列callback。

  4. 使您的缓冲区大小为AudioManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER)的倍数。 否则,你的callback偶尔会得到每个时间片两个电话,而不是一个。 除非你的CPU使用率真的很低,否则这可能会出现问题。 (在Android M上,由于缓冲区处理代码中的错误,使用EXACTLY系统缓冲区大小非常重要。)

  5. 使用AudioManager.getProperty提供的采样率(PROPERTY_OUTPUT_SAMPLE_RATE)。 否则,您的缓冲区将绕行系统重采样器。

  6. 切勿在缓冲区callback中进行系统调用或locking同步对象。 如果您必须同步,请使用无锁结构。 为了获得最佳效果,请使用完全等待的结构,如单读取器单写入器环形缓冲区。 开发人员的负担得到这个错误,并最终出现难以预料,难以debugging的故障。

  7. 使用向量指令,例如NEON,SSE或任何等效指令集在目标处理器上。

  8. testing和测量你的代码。 跟踪运行需要多长时间 – 请记住,您需要了解最差情况的performance,而不是平均水平,因为最糟糕的情况是导致毛刺的原因。 并保守。 您已经知道,如果处理audio比播放audio要花费更多的时间,则永远不会得到低延迟。 但在Android上这一点更为重要,因为CPU频率波动很大。 您可以使用大约60-70%的CPUaudio,但请记住,随着设备变热或变凉,或WiFi或LTE无线电开始和停止等等,这将会改变。

低延迟audio不再是Android的一项新function,但它仍然需要在硬件,驱动程序,内核和框架上进行特定于设备的更改。 这意味着不同设备的延迟可能会有很大的变化,并且考虑到Android手机销售的价格有多less,可能总会有差异。 查找FEATURE_AUDIO_PRO或FEATURE_AUDIO_LOW_LATENCY,以确定符合您应用所需延迟标准的设备。

使用OpenSL ES时,您应该满足以下要求,以在Jellybean和更高版本的Android上获得低延迟输出:

  • audio应该是单声道或立体声,线性PCM。

  • audio采样率应该与输出本地速率相同(在某些设备上实际上可能不需要,因为如果供应商configuration它, FastMixer可以重新采样,但是在我的testing中, FastMixer从44.1到48 kHz的上采样时出现明显的伪像)。

  • 你的BufferQueue应该至less有2个缓冲区。 (这个要求已经被放宽了,见Glenn Kasten的这个提交 ,我不确定哪个Android版本最初出现,但猜测是4.4)。

  • 您不能使用某些效果(例如,混响,低音增强,均衡,虚拟化…)。

在可能的情况下, SoundPool类也将尝试在内部使用快速AudioTrack (除了BufferQueue部分外,与上述相同的标准也适用)。

从您的链接点1:

“低延迟audio

Android 4.2改进了对低延迟audio播放的支持,从使用OpenSL ES,Soundpool和audio发生器API的Android 4.1发行版对audio输出延迟的改进开始。 这些改进取决于硬件支持 – 提供这些低延迟audiofunction的设备可以通过硬件function常数向应用宣传其支持。“

您完整的引用forms:

“性能

由于OpenSL ES是本地C API,调用OpenSL ES的非Dalvik应用程序线程没有Dalvik相关的开销,例如垃圾收集暂停。 但是,除此之外,使用OpenSL ES没有额外的性能优势。 特别是,使用OpenSL ES不会导致比平台通常提供的更低的audio延迟,更高的调度优先级等。 另一方面,随着Android平台和特定设备实现的不断发展,OpenSL ES应用程序可望从未来的系统性能改善中受益。“

所以,api与驱动程序交stream,然后hw是OpenSl(与Opengl用graphics相同的方式)。 虽然早期版本的Android在驱动程序和/或hw中的devise都很糟糕。 这些问题已经在4.1和4.2版本中得到了解决和纠正,所以如果高清有这个function,那么使用OpenSL就会获得较低的延迟。

同样,从puredata图书馆网站的这个注释中可以看出,图书馆使用OpenSL本身来实现低延迟:

对兼容设备的低延迟支持最新版本的Android版Pd(截至2012年12月28日)支持低延迟audio,以支持兼容的Android设备。 更新副本时,请确保从GitHub中获取最新版本的pd-for-android和libpd子模块。

在撰写本文时,Galaxy Nexus,Nexus 4和Nexus 10为audio输出提供低延迟音轨。 为了达到低延迟的轨道,应用程序必须使用OpenSL,并且必须以正确的采样率和缓冲区大小运行。 这些参数取决于设备(Galaxy Nexus和Nexus 10工作在44100Hz,而Nexus 4工作在48000Hz;每个设备的缓冲区大小不同)。

就像它的习惯一样,Pd for Android尽可能地复杂了所有这些复杂性,提供了新的低延迟function,同时保持向后兼容早期版本的Android。 在此基础上,Android的Pd的audio组件将使用Android 2.3及更高版本的OpenSL,而在Android 2.2及更早版本的Java中则会回落到原来的AudioTrack / AudioRecord API。

audio等待时间和缓冲区大小的另一个数据库使用:

http://superpowered.com/latency/#table

源代码:

https://github.com/superpoweredSDK/SuperpoweredLatency

您对Android的10毫秒问题(即Android上的低延迟audio)更感兴趣。 我们在Superpowered创build了Androidaudiopath延迟解释器。 请看这里:

http://superpowered.com/androidaudiopathlatency/#axzz3fDHsEe56

测量sampleRate和bufferSize的应用程序: https : //code.google.com/p/high-performance-audio/source/checkout和http://audiobuffersize.appspot.com/结果数据库;