AAudio 是 Android 系统提供的一种高性能、低延迟的原生 C API 音频库。源码下的使用样例及测试程序frameworks/av/media/libaaudio/examples/write_sine/为什么可以做到低延时1.使用mmap机制减少拷贝。在支持的硬件上AAudio 可以进入 MMAP 模式。在普通模式下音频数据需要在应用层、系统音频引擎和硬件驱动之间多次拷贝。而在 MMAP 模式下数据直接写入一个应用和硬件共享的内存区域。这种方式极大地降低了 CPU 占用和延迟。AAudio Sharing Mode分为两种AAUDIO_SHARING_MODE_SHAREDAAUDIO_SHARING_MODE_EXCLUSIVESHARED模式为默认模式可以支持多应用程序同时使用多个客户端播放时会在AAudio Server中进行混音所以会多出一个缓冲区这种模式下拥有双重缓冲区会增加时延。AAudioStream_setBufferSizeInFrames和AAudioStreamBuilder_setBufferCapacityInFrames ** 主要也是针对AAudio Server中的缓冲区进行设定capacity最大可设定为32x1024。另一个缓冲区是HAL层创建的“共享内存”。EXCLUSIVE模式只有一个缓冲区即HAL层创建的共享内存capacity size和burst size是由HAL来决定但buffer size依然是由上层设定。2.减小buffer size降低延时。在确保不发生underrun的情况下尽量使用最小buffer size。AAudioStream_getFramesPerBurst每次消耗的数据大小。AAudioStream_setBufferSizeInFramesringbuffer size由应用层设置一般要为burst frames的整数倍默认是2倍。可以在播放过程中动态调整。AAudioStreamBuilder_setBufferCapacityInFramesringbuffer size最大限制由应用层设置动态调整buffer size时不能超过这个值。buffer size较小的时候cpu稍微抖动就会发生underrun出现断音闲置情况单独使用write_sine播放使用512的buffer size不会发生断音此时延时也最低。3.使用实时高优先级回调线程取数据AAudio数据传输有两种模式Read/Write同步模式callback回调异步模式write_sine对应的是同步模式线程优先级低所以很容易被cpu抖动产生影响其它进程有操作时断音明显。write_sine_callback 对于的是回调模式AAudio 会在一个专门的高优先级线程中自动调用它优先级极高且由系统调度不容易受应用主线程或其他繁忙任务的影响。分别对比同步模式和异步模式两种情况下线程的状态1|RTD1325A16:/ # ps -T -p 5973 -o USER,PID,TID,PRI,RTPRIO,SCHED,PCY,CMD USER PID TID PRI RTPRIO SCH PCY CMD root 5973 5973 19 - 0 fg write_sine_call root 5973 5974 19 - 0 fg binder:5973_1 root 5973 5975 19 - 0 fg binder:5973_2 root 5973 5982 42 2 1 fg AAudio_1 RTD1325A16:/ # ps -T -p 3467 -o USER,PID,TID,PRI,RTPRIO,SCHED,PCY,CMD USER PID TID PRI RTPRIO SCH PCY CMD root 3467 3467 19 - 0 fg write_sine root 3467 3468 19 - 0 fg binder:3467_1 root 3467 3469 19 - 0 fg binder:3467_2可以看到回调模式下会多出一个AAudio创建的线程其优先级(PRI)更高并且属于实时线程(RTPRIO)调度模式(SCH)为FIFO普通线程调度模式为NORMAL。如何配置audio_policy_configuration.xmlmixPort namemmap_no_irq_out rolesource flagsAUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ profile name formatAUDIO_FORMAT_PCM_16_BITsamplingRates44100 48000channelMasksAUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_5POINT1//mixPortA good blog for reference.AA【Android Audio】AAudio 架构讲解以及实现范例 (附带visio流程图)_aaudio demo-CSDN博客open流程shared模式流程会复用exclusive mode如果只是exclusive mode会跳过2-10步。1 Aaudiostreambuilder_openstream 2 AudioStreamInternalPlay::open 这部分 AudioStreamInternalPlay 运行在client进程下。share mode 为AAUDIO_SHARING_MODE_SHARED 3 AudioStreamInternal::open 4 AAudioService::openStream 5 AAudioServiceStreamShared::open 6 AAudioServiceStreamBase::open 7 AAudioEndpointManager::openEndpoint 8 AAudioEndpointManager::openSharedEndpoint 9 AAudioServiceEndpointPlay::open AAudioMixer::allocate这里创建第一个缓冲区同时在构造方法中创建 AAudioServiceEndpointShared将 AudioStreamInternalPlay 作为参数传入。 10 AAudioServiceEndpointShared::open 将share mode设置为 AAUDIO_SHARING_MODE_EXCLUSIVE 再次打开 AudioStreamInternalPlay。 11 AudioStreamInternalPlay::open 此时 AudioStreamInternalPlay 运行在service进程下share mode 为 AAUDIO_SHARING_MODE_EXCLUSIVE 12 AudioStreamInternal::open 13 AAudioService::openStream 14 AAudioServiceStreamMMAP::open 15 AAudioServiceStreamBase::open 16 AAudioEndpointManager::openEndpoint 17 AAudioEndpointManager::openExclusiveEndpoint 18 AAudioServiceEndpointMMAP::open 19 AAudioServiceEndpointMMAP::openWithConfig 20 MmapStreamInterface::openMmapStream 21 AudioFlinger::openMmapStream MmapStreamInterface::createMmapBuffer 这里最终到HAL层创建第二个缓冲区start 流程与open流程类似需要注意的是它会在aaudio service中会创建一个混音线程。 AAudioServiceEndpointShared::startStream 第一个请求 sartStream 的时候创建混音线程 AAudioServiceEndpointShared::startSharingThread_lwrite 流程AAudioStream_write() AudioStreamInternalPlay::write AudioStreamInternalPlay::processDataNow AAudioFlowGraph::process() 写入第一个缓冲区 FIFO RingBuffer AAudioServiceEndpointPlay::callbackLoop 唤起混音线程处理所有客户端传过来的buffer AAudioMixer::mix AAudioServiceEndpointShared::write AudioStreamInternalPlay::processDataNow AAudioFlowGraph::process() 写入第二个缓冲区HAL创建的共享缓冲区