【Android 高性能音频】AAudio 音频流 缓冲区 简介 ( AAudio 音频流内部缓冲区 | 缓冲区帧容量 | 缓冲区帧大小 | 音频数据读写缓冲区 )

2023-03-27 17:42:21 浏览数 (1)

文章目录

代码语言:txt复制
        - [I . AAudio 音频流内部缓冲区 与 音频数据读写缓冲区 概念](https://cloud.tencent.com/developer)
        - [II . AAudio 音频流内部缓冲区 缓冲区帧容量 BufferCapacityInFrames 与 缓冲区帧大小 BufferSizeInFrames 区分](https://cloud.tencent.com/developer)
        - [III . AAudio 音频流内部缓冲区 缓冲区帧容量 BufferCapacityInFrames](https://cloud.tencent.com/developer)
        - [IV . AAudio 音频流内部缓冲区 缓冲区帧大小 BufferSizeInFrames](https://cloud.tencent.com/developer)
        - [V . AAudio 音频流内部缓冲区 脉冲串](https://cloud.tencent.com/developer)
        - [VI . AAudio 音频流内部缓冲区 工作机制 ( 播放音频 )](https://cloud.tencent.com/developer)
        - [VII . AAudio 音频流内部缓冲区 优化](https://cloud.tencent.com/developer)
        - [VIII . 音频数据读写缓冲区](https://cloud.tencent.com/developer)
I . AAudio 音频流内部缓冲区 与 音频数据读写缓冲区 概念

1 . AAudio 音频流内部缓冲区本质 : 该缓冲区是在音频设备中进行维护的 , AAudio 音频流会先将数据传入该缓冲区 , 然后才进行播放 ;

2 . 音频数据读写缓冲区 : 是在内存中维护的 , 其本质就是一个 void* 类型的数组 , 其数组字节大小由用户设定 ;

3 . 概念区分 : 注意将 AAudio 音频流内部缓冲区 与 音频数据读写缓冲区 区分清楚 ; 两个是完全不同的概念 ;

II . AAudio 音频流内部缓冲区 缓冲区帧容量 BufferCapacityInFrames 与 缓冲区帧大小 BufferSizeInFrames 区分

下面要区分两个概念 , 一个是缓冲区帧容量 BufferCapacityInFrames , 一个是缓冲区帧大小 BufferSizeInFrames , 这两个开发者都可以设置 ;

  • ① 缓冲区帧容量 BufferCapacityInFrames : 是音频设备的缓冲区最大值 ;
  • ② 缓冲区帧大小 BufferSizeInFrames : 用户实际使用的缓冲区大小 , 小于等于 缓冲区容量 ;

做一个形象的比喻 , 水杯有 2L 的容量 , 最大可以装 2L 水 , 2L 相当于缓冲区帧容量 ; 但是我们在水杯的 1.5L 位置画了一个最高水位线 , 表示盛水时不能高于 1.5L , 这个 1.5L 就是我们使用的实际缓冲区帧大小 ; 每帧的样本数就是通道数 , 单声道每帧 1 个样本 , 立体声 每帧 2 个样本 , 每个样本的大小与样本格式有关 , 16 位样本 每个样本 2 字节 ;

III . AAudio 音频流内部缓冲区 缓冲区帧容量 BufferCapacityInFrames

AAudio 音频流内部 缓冲区帧容量 : 音频设备的缓冲区最大值 ;

  • ① 设置缓冲区最大容量 : 调用 AAudioStreamBuilder_setBufferCapacityInFrames() 方法可以设置音频设备缓冲区最大容量 ;
  • ② 获取缓冲区最大容量 : 调用 AAudioStream_getBufferCapacityInFrames() 方法可以获取当前音频设备缓冲区的最大容量 ;
IV . AAudio 音频流内部缓冲区 缓冲区帧大小 BufferSizeInFrames

AAudio 音频流内部缓冲区帧大小 : 为音频设备设置了缓冲区最大容量 , 但是我们可能用不了这么大缓冲区 , 只使用其中一部分作为缓冲区 ;

  • ① 缓冲区帧大小 限制 : 缓冲区帧大小 BufferSizeInFrames 只能小于等于 缓冲区帧容量 BufferCapacityInFrames ;
  • ② 设置 缓冲区帧大小 作用 : 增加 缓冲区帧大小 BufferSizeInFrames 会增加音频延迟 , 反之会减小延迟 ;
  • ③ 设置缓冲区帧大小 方法 : AAudioStreamBuilder_setBufferSizeInFrames() ;
  • ④ 获取缓冲区帧大小 方法 : AAudioStreamBuilder_getBufferSizeInFrames() ;
V . AAudio 音频流内部缓冲区 脉冲串

1 . 脉冲串概念 : 音频设备读取 音频内部缓冲区数据时 , 会以离散的脉冲串形式从缓冲区中读取音频数据 , 每个脉冲串都包含多个音频帧 ;

2 . 脉冲串设置 : 脉冲串包含的帧个数 , 以及脉冲串的读取速度 , 这两个属性由 Android 系统控制 , 与音频设备的电路相关 ;

3 . 脉冲串属性固定 : 脉冲串的大小 和 速度 是无法修改的 , 可以根据 内部缓冲区 包含的脉冲串数量 设置内部缓冲区大小 ;

4 . 脉冲串 性能相关 设置 : AAudio 音频流的 内部缓冲区帧大小 是 脉冲串大小的整数倍时 , 音频延迟最短 ;

VI . AAudio 音频流内部缓冲区 工作机制 ( 播放音频 )

1 . 写出数据到内部缓冲区 : 使用 AAudio 音频流 播放音频时 , 先将数据写入 AAudio 音频流的内部缓冲区 , 该过程会阻塞线程 , 直到写入完成 ;

该缓冲区为音频设备内部维护的

2 . AAudio 音频流 会以 离散的 脉冲串形式 , 读取内部缓冲区中的音频数据 , 然后播放出来 ;

3 . 图示 : 内部缓冲区工作机制如下图 ;

VII . AAudio 音频流内部缓冲区 优化

1 . AAudio 音频流内部缓冲区优化步骤 : 设置一个合适的 缓冲区帧大小 BufferSizeInFrames , 先设置一个较大的缓冲区 , 逐步减小该缓冲区大小 , 监控 XRun ( 超限 或 欠载 ) 数值 , 当出现了上述情况 , 说明缓冲区减小到极限 , 出现了播放问题 , 此时再稍微将缓冲区调大 , 最终的缓冲区大小刚合适 , 兼顾性能与功能 ;

备选方案 : 先设置肯定出问题一个最小值 , 此时肯定会出现缓冲区不足的情况 , 逐步增加缓冲区大小 , 直到流畅读写为止 ;

2 . 调整时间 : 缓冲区大小调整的过程几乎是一瞬间完成的 , 在开始播放第一帧数据时就已经完成 ;

3 . 静音调整 : 缓冲区调整时 , 可以静音初始化缓冲区大小 , 确保用户听不到电流声 ;

4 . 不断调整 : 在音频播放的过程中 , 系统的性能可能随时改变 , 这个缓冲区的大小也要跟着实时修改 , 一旦监测到了 欠载 UnderRun 或 超限 OverRun 就马上调整缓冲区大小 ;

该过程可以参考上一篇博客 : 【Android 高性能音频】AAudio 缓冲区控制 ( XRun | 欠载 UnderRun | 超限 OverRun | 获取缓冲区大小 | 设置缓冲区大小 )

VIII . 音频数据读写缓冲区

1 . 概念区分 ( AAudio 内部缓冲区 / 音频读写缓冲区 ) : 该缓冲区是由用户自己维护的 , 与 AAudio 音频流缓冲区没有任何关系 , 不要混淆这两个概念 ;

2 . 缓冲区本质 : 音频读写缓冲区是在堆内存中维护的 , 其本质就是一个 void* 类型的数组 , 其数组字节大小由用户设定 ;

3 . 读写缓冲区作用 : 读取音频数据时 , 将音频数据先读取到该缓冲区中 ;

4 . 性能分析 : 该音频数据读写缓冲区 与 采样效率相关 , 采样是需要消耗额外性能的 , 如果该缓冲区很大 , 一次采集很多样本 , 采样的效率会很高 , 但是减少了灵活性 , 如果采样太少 , 就会额外消耗很多性能 ;

0 人点赞