低延迟音频让游戏感觉更真实、响应更灵敏。
完成以下核对清单,在您的 Android 游戏中启用低延迟音频
- 使用 Oboe
- 请求性能模式“低延迟”
- 请求共享模式“独占”
- 使用 48000 Hz 或 Oboe 采样率转换器
- 将用法设置为 AAUDIO_USAGE_GAME
- 使用数据回调
- 避免在回调中执行阻塞操作
- 将缓冲区大小调整为“双缓冲区”
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 |