Android上的低延迟音频播放

Ser*_*les 39 audio android opensl

我目前正在尝试最小化简单应用程序的音频延迟:

我在PC上有一个视频,我正在通过RTP将视频的音频传输到移动客户端.使用非常相似的缓冲算法,我可以在iOS上实现90ms的延迟,但在Android上可以实现±180ms的可怕延迟.

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

然而,在阅读了一下后,我发现了这篇文章,其中指出:

  1. 自Android 4.1/4.2以来,在某些设备中可以使用低延迟音频.

  2. 使用libpd可以实现低延迟音频,libpd是Android的纯数据库.

我有两个问题,与这两个陈述直接相关:

  1. 我在哪里可以找到有关Jellybean中新的低延迟音频的更多信息?这是我能找到的全部,但它缺乏具体的信息.如果这些更改对我来说是透明的,或者是否有一些新的类/ API调用我应该实现我注意到我的应用程序中的任何更改?我正在使用AudioTrack API,我甚至不确定它是否应该从这种改进中获益,或者我是否应该研究其他一些音频播放机制.

  2. 我应该考虑使用libpd吗?在我看来,这是我实现更低延迟的唯一机会,但由于我一直认为PD是一个音频合成实用程序,它是否真的适合于只从网络流中抓取帧并播放它们的项目?我不是在做任何合成.我跟踪错误的踪迹吗?

另外需要注意的是,在有人提到OpenSL ES之前,本文非常清楚地表明使用它时不应期望延迟有所改善:

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

Ian*_*wis 66

对于Android版本4.2.2的最低延迟,您应该执行以下操作,从最少到最明显的顺序排序:

  1. 如果可能,选择支持FEATURE_AUDIO_PRO的设备,否则选择FEATURE_AUDIO_LOW_LATENCY.("低延迟"单向50ms;专业往返20ms.)

  2. 使用OpenSL.Dalvik GC具有较低的摊销成本,但是当它运行时,它需要比低延迟音频线程允许的时间更长的时间.

  3. 处理缓冲区队列回调中的音频.系统在线程中运行缓冲区队列回调,该线程比普通用户模式线程具有更有利的调度.

  4. 使缓冲区大小为AudioManager.getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER)的倍数.否则,您的回调有时会每次拨打两次而不是一次.除非您的CPU使用率非常低,否则这可能会导致故障.(在Android M上,由于缓冲区处理代码中的错误,因此使用EXACTLY系统缓冲区大小非常重要.)

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

  6. 永远不要在缓冲区回调中进行系统调用或锁定同步对象.如果必须同步,请使用无锁结构.为获得最佳效果,请使用完全等待的结构,例如单读取器单写入器环形缓冲区.大量的开发人员错了,最终导致无法预测且难以调试的故障.

  7. 使用向量指令,如NEON,SSE或目标处理器上的等效指令集.

  8. 测试并测量您的代码.跟踪运行所需的时间 - 并记住您需要知道最坏情况的性能,而不是平均值,因为最坏的情况是导致故障的原因.保守.您已经知道,如果处理音频需要花费更多时间而不是播放音频,您将永远不会获得低延迟.但在Android上,这更为重要,因为CPU频率波动很大.您可以将60-70%的CPU用于音频,但请记住,这会随着设备变得更热或更冷,或者因为wifi或LTE无线电的启动和停止而改变,等等.

低延迟音频不再是Android的新功能,但仍需要硬件,驱动程序,内核和框架中特定于设备的更改才能实现.这意味着您可以从不同设备中获得的延迟有很多变化,并且鉴于Android手机销售的价格有多少不同,可能总会存在差异.查找FEATURE_AUDIO_PRO或FEATURE_AUDIO_LOW_LATENCY以识别符合您的应用所需的延迟条件的设备.

  • "在Android M上,由于缓冲区处理代码中的错误,完全使用系统缓冲区大小非常重要"是否有更多信息?我似乎有这个问题.我想人们在这种情况下被迫使用低延迟音频. (3认同)

Mic*_*ael 6

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

  • 音频应为单声道或立体声,线性PCM.

  • 音频采样率应该是相同的相同的采样率输出的原生率(这可能实际上并不需要在某些设备上,因为FastMixer 如果供应商将其配置这样做能够重采样的.但在我的测试中,我得到了非常显着当从上升到44.1到48 kHz时的伪像FastMixer.

  • BufferQueue应该至少有2个缓冲区.(此要求已经放宽了.请参阅Glenn Kasten的这个提交.我不确定这个首次出现的Android版本,但猜测是4.4).

  • 你不能使用某些效果(例如Reverb,Bass Boost,Equalization,Virtualization,......).

SoundPool班还试图利用快速的AudioTrack小号内部可能时(如上采用相同的标准,除了BufferQueue一部分).


And*_*oom 5

在您指向的链接上:

“低延迟音频

从使用OpenSL ES,Soundpool和音调生成器API的Android 4.1版本中对音频输出延迟的改进开始,Android 4.2改进了对低延迟音频播放的支持。这些改进取决于硬件支持-提供这些低延迟音频功能的设备可以通过硬件功能常量向应用程序宣传其支持。”

您完整的引文形式:

“性能

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

因此,用于与驱动程序进行通讯的api是OpenSl(与Opengl处理图形的方式相同)。不过,较早版本的Android在驱动程序和/或硬件方面设计不良。这些问题已通过4.1和4.2版本解决并得到纠正,因此,如果高清硬盘具有强大功能,则使用OpenSL可以降低延迟。

再次,从puredata库网站的注释中可以看出,该库本身使用OpenSL来实现低延迟:

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

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

毫无疑问,Pd for Android尽可能解决了所有这些复杂问题,在可用时提供对新的低延迟功能的访问,同时保持与Android早期版本的向后兼容性。在后台,用于Android的Pd的音频组件将在Android 2.3和更高版本上使用OpenSL,而在Android 2.2和更低版本上则使用Java中的旧AudioTrack / AudioRecord API。