1 . AAudio 音频流内部缓冲区本质 : 该缓冲区是在音频设备中进行维护的 , AAudio 音频流会先将数据传入该缓冲区 , 然后才进行播放 ;
2 . 音频数据读写缓冲区 : 是在内存中维护的 , 其本质就是一个 void* 类型的数组 , 其数组字节大小由用户设定 ;
3 . 概念区分 : 注意将 AAudio 音频流内部缓冲区 与 音频数据读写缓冲区 区分清楚 ; 两个是完全不同的概念 ;
下面要区分两个概念 , 一个是缓冲区帧容量 BufferCapacityInFrames , 一个是缓冲区帧大小 BufferSizeInFrames , 这两个开发者都可以设置 ;
做一个形象的比喻 , 水杯有 2L 的容量 , 最大可以装 2L 水 , 2L 相当于缓冲区帧容量 ; 但是我们在水杯的 1.5L 位置画了一个最高水位线 , 表示盛水时不能高于 1.5L , 这个 1.5L 就是我们使用的实际缓冲区帧大小 ;
每帧的样本数就是通道数 , 单声道每帧 1 个样本 , 立体声 每帧 2 个样本 , 每个样本的大小与样本格式有关 , 16 位样本 每个样本 2 字节 ;
AAudio 音频流内部 缓冲区帧容量 : 音频设备的缓冲区最大值 ;
AAudio 音频流内部缓冲区帧大小 : 为音频设备设置了缓冲区最大容量 , 但是我们可能用不了这么大缓冲区 , 只使用其中一部分作为缓冲区 ;
1 . 脉冲串概念 : 音频设备读取 音频内部缓冲区数据时 , 会以离散的脉冲串形式从缓冲区中读取音频数据 , 每个脉冲串都包含多个音频帧 ;
2 . 脉冲串设置 : 脉冲串包含的帧个数 , 以及脉冲串的读取速度 , 这两个属性由 Android 系统控制 , 与音频设备的电路相关 ;
3 . 脉冲串属性固定 : 脉冲串的大小 和 速度 是无法修改的 , 可以根据 内部缓冲区 包含的脉冲串数量 设置内部缓冲区大小 ;
4 . 脉冲串 性能相关 设置 : AAudio 音频流的 内部缓冲区帧大小 是 脉冲串大小的整数倍时 , 音频延迟最短 ;
1 . 写出数据到内部缓冲区 : 使用 AAudio 音频流 播放音频时 , 先将数据写入 AAudio 音频流的内部缓冲区 , 该过程会阻塞线程 , 直到写入完成 ;
该缓冲区为音频设备内部维护的
2 . AAudio 音频流 会以 离散的 脉冲串形式 , 读取内部缓冲区中的音频数据 , 然后播放出来 ;
3 . 图示 : 内部缓冲区工作机制如下图 ;
1 . AAudio 音频流内部缓冲区优化步骤 : 设置一个合适的 缓冲区帧大小 BufferSizeInFrames , 先设置一个较大的缓冲区 , 逐步减小该缓冲区大小 , 监控 XRun ( 超限 或 欠载 ) 数值 , 当出现了上述情况 , 说明缓冲区减小到极限 , 出现了播放问题 , 此时再稍微将缓冲区调大 , 最终的缓冲区大小刚合适 , 兼顾性能与功能 ;
备选方案 : 先设置肯定出问题一个最小值 , 此时肯定会出现缓冲区不足的情况 , 逐步增加缓冲区大小 , 直到流畅读写为止 ;
2 . 调整时间 : 缓冲区大小调整的过程几乎是一瞬间完成的 , 在开始播放第一帧数据时就已经完成 ;
3 . 静音调整 : 缓冲区调整时 , 可以静音初始化缓冲区大小 , 确保用户听不到电流声 ;
4 . 不断调整 : 在音频播放的过程中 , 系统的性能可能随时改变 , 这个缓冲区的大小也要跟着实时修改 , 一旦监测到了 欠载 UnderRun 或 超限 OverRun 就马上调整缓冲区大小 ;
该过程可以参考上一篇博客 : 【Android 高性能音频】AAudio 缓冲区控制 ( XRun | 欠载 UnderRun | 超限 OverRun | 获取缓冲区大小 | 设置缓冲区大小 )
1 . 概念区分 ( AAudio 内部缓冲区 / 音频读写缓冲区 ) : 该缓冲区是由用户自己维护的 , 与 AAudio 音频流缓冲区没有任何关系 , 不要混淆这两个概念 ;
2 . 缓冲区本质 : 音频读写缓冲区是在堆内存中维护的 , 其本质就是一个 void* 类型的数组 , 其数组字节大小由用户设定 ;
3 . 读写缓冲区作用 : 读取音频数据时 , 将音频数据先读取到该缓冲区中 ;
4 . 性能分析 : 该音频数据读写缓冲区 与 采样效率相关 , 采样是需要消耗额外性能的 , 如果该缓冲区很大 , 一次采集很多样本 , 采样的效率会很高 , 但是减少了灵活性 , 如果采样太少 , 就会额外消耗很多性能 ;