一、AAudio介绍
AAudio 是一个自 Android O 引入的新的 Android C API。它主要是为需要低延迟的高性能音频应用设计的。应用程序通过直接从流中读取或向流中写入数据来与 AAudio 通信,但它只包含基本的音频输入输出能力。AAudio 在应用程序和 Android 设备上的音频输入输出之间移动音频数据。应用程序传入音频流和从音频流读取数据来实现这种音频数据的传递。AAudio 的实现围绕音频数据传递,围绕音频流进行。
AAudio 的数据传递主要有两种工作模式,一种是 MMap 模式,此时客户端 AAudio 库从 media.aaudio 服务获得一块共享内存,并通过这块共享内存将数据传给设备;另一种是所谓的传统模式,此时客户端 AAudio 的接口基于传统的 android::AudioTrack 和 android::AudioRecord 实现,与 Java 的 AudioTrack 和 AudioRecord 实现使用相同的组件。真正能够实现 AAudio 文档中说明的性能和延迟优势的是基于 mmap 的共享内存与设备传递数据的工作模式。
AAudio 库的实现主要包括这样几个模块,其源码目录结构也按照模块组织:
API 接口:它们直接实现了在应用程序中调用的 AAudio C 接口,相关代码位于 libaaudio/src/core 目录;
legacy:基于传统的 android::AudioTrack 和 android::AudioRecord 接口实现的音频流,相关代码位于 libaaudio/src/legacy 目录;
binding:客户端绑定,主要用于与 media.aaudio 服务通信,如向 media.aaudio 发送请求,或接收 media.aaudio 服务的事件通知,相关代码位于 libaaudio/src/binding 目录;
fifo:主要用于与 media.aaudio 服务或设备进行数据传递,AAudio 通过 binding 模块拿到了与共享内存绑定的 fd,这个 fd 在当前进程中需要重新 mmap,fifo 模块的相关类用于通过这些 mmap 的共享内存与 media.aaudio 服务或设备进行数据传递,相关代码位于 libaaudio/src/fifo 目录;
flowgraph:用 AAudio 播放数据时,会对数据做一些简单的处理,如通道数转换等,flowgraph 模块用于完成这些处理,相关代码位于 libaaudio/src/flowgraph 目录;
client:基于 binding、fifo 和 flowgraph 等模块实现的音频流,相关代码位于 libaaudio/src/client 目录;
utility:一些实用程序,相关代码位于 libaaudio/src/utility 目录。
从模块的视角来看,AAudio 库的实现结构如下图所示:
AAudio 是一种新的本地 C API,可提供 Open SL ES 的替代方案。它使用“构建器”设计模式来创建音频流。
AAudio 提供了一个低延迟数据路径。在“专有”模式下,使用该功能可将客户端应用代码直接写入与 ALSA 驱动程序共享的内存映射缓冲区。在“共享”模式下,MMAP 缓冲区由 AudioServer 中运行的混音器使用。在“专有”模式下,由于数据会绕过混音器,延迟时间会明显缩短。
在“专有”模式下,服务可从 HAL 请求 MMAP 缓冲区并管理资源。MMAP 缓冲区将在 NOIRQ 模式下运行,因此没有共享的读/写计数器来管理缓冲区的访问权限。相反,客户端会维护硬件的计时模型,并预测将在何时读取缓冲区。
在下图中,我们可以看到脉冲编码调制 (PCM) 数据通过 MMAP FIFO 向下流入 ALSA 驱动程序。AAudio 服务会定期请求时间戳,然后通过原子消息队列将其传递给客户端的计时模型。
二、AAudio相关API
aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder): 创建音频流
Create a StreamBuilder that can be used to open a Stream.
void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder, int32_t deviceId):
Request an audio device identified by an ID. 设置音频流设备 ID
void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder, aaudio_direction_t direction):
Request the direction for a stream. 设置音频流方向
void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder, aaudio_sharing_mode_t sharingMode):
Request a mode for sharing the device. 设置共享模式 , 独占模式性能更高 , 延迟更低 ; 如果 该音频设备正在被使用 , 设置失败会自动设置成 共享模式
void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder, aaudio_performance_mode_t mode):
Set the requested performance mode. 设置性能模式
void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder, int32_t channelCount) :
Request a number of channels for the stream. 设置通道个数
void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder, int32_t sampleRate):
Request a sample rate in Hertz. 设置波特率
void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder, aaudio_format_t format):
Request a sample data format, for example {@link #AAUDIO_FORMAT_PCM_I16}. 设置音频格式
aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream, int32_t numFrames)
This can be used to adjust the latency of the buffer by changing the threshold where blocking will occur. 设置每帧的缓冲区大小 , 可以通过该设置达到尽可能低的延迟
aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder, AAudioStream** stream):
Open a stream based on the options in the StreamBuilder. 打开音频流
aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* builder):
Delete the resources associated with the StreamBuilder. 销毁音频流构建器
aaudio_result_t AAudioStream_close(AAudioStream* stream) :
Delete the internal data structures associated with the stream created by AAudioStreamBuilder_openStream(). 关闭音频流 , 关闭后 , 该音频流就彻底释放了 , 如果在使用 , 必须重新创建
aaudio_result_t AAudioStream_release(AAudioStream* stream):
Free the audio resources associated with a stream created by AAudioStreamBuilder_openStream(). 释放音频相关的资源
aaudio_result_t AAudioStream_read(AAudioStream* stream, void *buffer, int32_t numFrames, int64_t timeoutNanoseconds)
Read data from the stream. 读取音频流
aaudio_result_t AAudioStream_write(AAudioStream* stream, const void *buffer, int32_t numFrames, int64_t timeoutNanoseconds)
Write data to the stream. 写入音频流
void AAudioStreamBuilder_setChannelMask(AAudioStreamBuilder* builder, aaudio_channel_mask_t channelMask):
Set audio channel mask for the stream. 为流设置音频通道掩码。
void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder, aaudio_usage_t usage):
Set the intended use case for the output stream. 设置输出流的use case。
aaudio_r