低延迟音频

低延迟音频让游戏感觉更真实、响应更灵敏。

完成以下核对清单,在您的 Android 游戏中启用低延迟音频

  1. 使用 Oboe
  2. 请求性能模式“低延迟”
  3. 请求共享模式“独占”
  4. 使用 48000 Hz 或 Oboe 采样率转换器
  5. 将用法设置为 AAUDIO_USAGE_GAME
  6. 使用数据回调
  7. 避免在回调中执行阻塞操作
  8. 将缓冲区大小调整为“双缓冲区”

1. 使用 Oboe API

Oboe API 是一个 C++ 封装器,可在 Android 8.1(API 级别 27)或更高版本上调用 AAudio。在更早的 Android 版本上,Oboe 使用 OpenSL ES。

Oboe 可在 GitHub 上获取,也可作为预构建二进制文件使用。Oboe 还包含一个 QuirksManager,可纠正在特定设备上的问题,从而使您的应用兼容更多设备。如果您无法使用 Oboe,请直接使用 AAudio。

2. 请求低延迟模式

通过 Oboe 或 AAudio,请求低延迟模式。否则,默认情况下会获得更高的延迟模式。

Oboe

builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);

AAudio

AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

3. 请求独占模式

您还可以请求对 MMAP 缓冲区的独占访问权限。您的应用可能无法获得独占访问权限,但如果获得,您的应用将直接写入由 DSP 读取的缓冲区,从而为您的应用提供可能的最低延迟。

Oboe

builder.setSharingMode(oboe::SharingMode::Exclusive);

AAudio

AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

4. 避免采样率转换

使用设备的自然采样率。您可以通过不指定采样率来实现这一点,您几乎肯定会得到 48000 Hz。如果您指定了采样率,音频框架会通过不同的路径发送您的数据,这可能会导致更高的延迟。

如果您确实需要使用不同的采样率,请使用 Oboe 进行采样率转换

builder->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium);

5. 正确声明您的用例

指定应用播放音频的原因对于系统应用正确的路由、音量和性能设置至关重要。例如,游戏应指明用途为 AAUDIO_USAGE_GAME,以充分利用延迟优化,尤其是在连接到蓝牙耳机时。

Oboe

builder.setUsage(oboe::Usage::Game);

AAudio

AAudioStreamBuilder_setUsage(builder, AAUDIO_USAGE_GAME);

6. 使用回调函数

为输出流使用回调。如果您使用阻塞写入且设备不支持 AAudio MMAP 模式,则延迟可能会高得多。

Oboe

builder.setDataCallback(&myCallbackObject);

AAudio

AAudioStreamBuilder_setDataCallback(builder, &my_callback_proc);

7. 避免在回调中阻塞

当您使用低延迟流时,回调之间的时间可能非常短,只有几毫秒。因此,在回调中不执行任何可能长时间阻塞的操作非常重要。如果回调被阻塞,缓冲区将欠载,音频中会出现毛刺。

避免在回调中执行以下操作

  • 分配或释放内存
  • 文件或网络 I/O
  • 等待互斥锁或锁
  • 睡眠
  • 繁重的单次 CPU 计算

回调应以均匀的速度进行计算,以实现流畅且无毛刺的播放。

8. 调整缓冲区大小

一旦您的应用打开音频流,您就需要调整可用缓冲区大小以实现最佳延迟。Oboe 会自动将缓冲区大小设置为两次突发。但对于 AAudio,默认值要高得多。通过将缓冲区大小设置为突发大小的两倍来实现双缓冲。突发大小是最大回调大小。

AAudio

int32_t frames = AAudioStream_getFramesPerBurst() * 2;
AAudioStream_setBufferSizeInFrames(stream, frames);

如果缓冲区大小太小,您可能会因缓冲区欠载而出现毛刺。您可以通过调用 AAudioStream_getXRunCount(stream) 获取毛刺计数。根据需要增加缓冲区大小。

有关缓冲区相关术语的解释,请参阅 GitHub Oboe 文档

OpenSL ES

如果您支持 Android 8.1 之前的版本,则必须使用 OpenSL ES。如果您使用 Oboe,可以配置您的应用以改善延迟。请参阅 GitHub 文档中的获取最佳延迟

核对清单结果

下表包含 OboeTester 对往返(输入到输出)延迟的测量结果。

配置 延迟 (ms)
遵循所有建议 20
性能模式非低延迟 205
非独占 (共享) 26
44100 Hz (AAudio) 160
44100 Hz (Oboe SRC) 23
未使用输出回调 (MMAP) 21
未使用输出回调 (非 MMAP) 62
缓冲区大小设置为最大值 53