文章目录
I . AAudio 音频流 创建 配置 使用 销毁 流程
II . AAudio 音频流 稳定状态 与 过渡状态
III . AAudio 音频流 状态改变 监听
IV . AAudio 音频流 状态改变 监听 实例 ( 暂停操作 )
V . AAudio 音频流 状态改变 监听 注意事项
I . AAudio 音频流 创建 配置 使用 销毁 流程
红色标题是本博客讲解的内容 , 黑色是前几篇讲过的内容 ;
使用 AAudio 音频库 , 首先需要导入 AAudio.h 头文件 ;
#include <AAudio.h>
创建 AAudio 音频流 , 需要先创建 AAudio 音频流构建器 , 然后在通过该构建器创建音频流 ;
//创建构建器 , AAudio 音频流通过该构建器创建 //声明 AAudio 音频流构建器 指针 AAudioStreamBuilder *builder = nullptr; //创建 AAudio 音频流构建器 , 注意传入二维指针 aaudio_result_t result = AAudio_createStreamBuilder(&builder);
设置音频设备 ID ;
// 设置音频流设备 ID
AAudioStreamBuilder_setDeviceId(builder, playbackDeviceId_);
1
2
设置音频流方向 ;
// 设置音频流方向
AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
1
2
设置音频设备共享模式 ;
// 设置共享模式 , 独占模式性能更高 , 延迟更低 ; 如果 该音频设备正在被使用 , 设置失败会自动设置成 共享模式
AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);
1
2
设置性能模式 ;
// 设置性能模式
AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
1
2
设置 AAudio 音频流通道数 :
// 设置通道个数
AAudioStreamBuilder_setChannelCount(builder, sampleChannels_);
1
2
设置 AAudio 音频流样本格式 :
// 设置音频格式
AAudioStreamBuilder_setFormat(builder, sampleFormat_);
1
2
设置 AAudio 音频流缓冲区大小 : 这里的缓冲区是播放器的缓冲区 , 单位是帧 , 每帧的采样数就是通道数 , 单声道 每帧 1 个采样, 双声道立体声每帧 2 个采样 , 分别对应左右声道的采样 ;
// 设置每帧的缓冲区大小 , 可以通过该设置达到尽可能低的延迟
AAudioStream_setBufferSizeInFrames(playStream_, framesPerBurst_);
1
2
创建 AAudio 音频流 : 创建 AAudio 音频流 , 就是打开音频流 , 注意要在音频流参数设置完毕后才能打开音频流 ;
// 打开音频流 ( 该步骤就是创建音频流 )
aaudio_result_t result = AAudioStreamBuilder_openStream(builder, &playStream_);
1
2
销毁 AAudio 音频流构建器 : 在音频流创建 ( 打开 ) 完毕后 , 应该马上销毁 AAudio 音频流构建器 ;
//销毁音频流构建器
AAudioStreamBuilder_delete(builder);
1
2
使用 AAudio 音频流 进行 录音 或 播放操作 , 使用完毕后需要 销毁 AAudio 音频流 ;
停止 AAudio 音频流 : 如果 AAudio 音频流不再使用 , 需要马上销毁 AAudio 音频流 , 销毁前需要先将音频流停止 , 然后才能销毁 ;
//先停止音频流 , 然后才能关闭 aaudio_result_t result = AAudioStream_requestStop(playStream_);
关闭 AAudio 音频流 : 如果 AAudio 音频流不再使用 , 需要马上销毁 AAudio 音频流 , 该流会占据音频设备资源 , 不用应马上销毁 ;
//关闭音频流 , 关闭后 , 该音频流就彻底释放了 , 如果在使用 , 必须重新创建
result = AAudioStream_close(playStream_);
1
2
II . AAudio 音频流 稳定状态 与 过渡状态
1 . AAudio 音频流有 6 种稳定状态 :
① Open : 音频流打开后的状态 , 就是 Open 状态 , 该状态时间很短 , 马上回自动转到下一状态 ;
② Started : 音频流打开后 , 会自动从 Open 状态转为 Started 状态 , 该状态下音频流的音频数据 , 处于流动状态 , 这个过程占生命周期的 99.999% 的时间 ;
③ Paused : 暂停状态 , 在 Started 状态下 , 如果调用 AAudioStream_requestPause() 方法 , 就会进入该状态 ; 此时播放器是暂停的 , 可以随时恢复播放 , 调用 AAudioStream_requestStart() 方法 , 可以恢复播放 , 进入 Started 状态 ;
④ Flushed : 刷写状态 , 在 Paused 状态下 , 调用 AAudioStream_requestFlush() 方法 , 就会进入该状态 , 这是将播放器缓冲区中的数据播放完毕 , 可以清空缓冲区 ; 调用 AAudioStream_requestStart() 方法 , 可以恢复播放 , 进入 Started 状态 ;
⑤ Stopped : 停止状态 , 在 Started 状态下 , 如果调用 AAudioStream_requestStop() 方法 , 就会进入该状态 ; 此时如果要恢复成 Started 状态 , 需要调用 AAudioStream_requestStart() 方法 ;
⑥ Closed : 关闭状态 , 在 Stopped 状态下 , 如果调用 AAudioStream_close() 方法 , 就会进入 Closed 状态 ; 该状态意味着 AAudio 音频流被销毁 , 无法再继续使用 ;
总结 :
处于 暂停 ( Paused ) , 停止 ( Stopped ) , 刷写 ( Flushed ) 状态下 , 可以调用 AAudioStream_requestStart() 方法 , 恢复成 Started 状态 ;
刷写 ( Flushed ) 状态 必须 有前置状态 暂停状态 ( Paused ) 才能进入该状态 , 其它状态下是无法进入 刷写状态的 ;
2 . AAudio 音频流有 5 种 过渡状态 : 过渡状态是两种稳定状态之间的状态 ;
① Starting 状态 : Open 状态 与 Started 状态 之间的 过渡状态 ;
② Pausing 状态 : Started 状态 与 Paused 状态之间的 过渡状态 ;
③ Flushing 状态 : Paused 状态 与 Flushed 状态之间的 过渡状态 ;
④ Stopping 状态 : Started 状态 与 Stopped 状态 之间的过渡状态 ;
⑤ Closing 状态 : Stopped 状态 与 Closed 状态 之间的过渡状态 ;
3 . 11 个状态之间的状态机转化关系如下图 :
III . AAudio 音频流 状态改变 监听
1 . AAudio 音频流状态监听简介 :
① 没有回调函数 : AAudio 没有提供 监听 音频流状态的 回调函数 ;
② 等待变更方法 : 目前只能使用 AAudioStream_waitForStateChange() 方法 , 该方法调用后 , 开始阻塞 , 等待 AAudio 音频流变更成 不同于 开发者指定的状态 的 其它状态后 , 继续执行下面的代码 ;
2 . AAudioStream_waitForStateChange 方法简介 :
① 函数原型 : 调用该函数时 , 当前状态应该是 inputState 状态 , 之后一直阻塞 , 该函数会等待 当前状态 , 不是 inputState 状态时 , 接触阻塞 , 继续执行下面的代码 ;
AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange( AAudioStream *stream, aaudio_stream_state_t inputState, aaudio_stream_state_t *nextState, int64_t timeoutNanoseconds
② 参数 1 AAudioStream *stream : 状态机所属的 AAudio 音频流 ;
③ 参数 2 aaudio_stream_state_t inputState : 初始状态 , 调用该方法时的状态 ; 当 AAudio 音频流状态不是该状态时 , 方法阻塞解除 ;
④ 参数 3 aaudio_stream_state_t *nextState : 下一个状态的指针 , 指向一个状态值 , 该值是 解除阻塞的时刻的 AAudio 音频流状态 ; 用于在后续执行时获取当前是什么状态 ;
⑤ 参数 4 int64_t timeoutNanoseconds : 超时时间 , 该方法不可能一直阻塞代码执行 , 当超过一定时间后 , 继续执行后续的代码 ;
⑥ 返回值 aaudio_result_t : 如果成功 , 返回 AAUDIO_OK , 如果失败会返回对应的错误码 ;
IV . AAudio 音频流 状态改变 监听 实例 ( 暂停操作 )
1 . 监听暂停操作 : 在 Started 状态下 , 调用 AAudioStream_requestPause() 方法 , 设置 AAudio 音频流暂停操作 ;
2 . 理论上的状态改变 : 方法调用后 , AAudio 音频流 会立刻进入 Pausing 过渡状态 , 然后处理过渡操作 , 处理完毕后 , 进入 Paused 状态 ;
3 . 代码实现 :
① 申请暂停 : 调用 AAudioStream_requestPause() 方法之后 ;
② 当前状态 : 申请暂停后 , 当前状态马上切换成了 Pausing 状态 ;
③ 阻塞程序 : 此时 立刻调用 AAudioStream_waitForStateChange() 方法 , 其中的 第二个参数 inputState 设置成 Pausing 状态 , 该方法阻塞了程序运行 ;
④ 解除阻塞 : 当状态由 Pausing 转为其它状态 ( 一般是 Paused 状态 ) , 或者超时 , 阻塞解除 , 继续执行下面的代码 ;
//设置当状态与该状态不一致时解除阻塞 aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_PAUSING; //用于记录下一个状态 , 将其地址传入 AAudioStream_waitForStateChange 方法 第三个参数 aaudio_stream_state_t nextState = AAUDIO_STREAM_STATE_UNINITIALIZED; //超时时间 int64_t timeoutNanos = 100 * AAUDIO_NANOS_PER_MILLISECOND; //申请暂停 , 方法执行后 , 状态立刻变成 Pausing 状态 result = AAudioStream_requestPause(stream); //阻塞程序 , 直到状态由 Pausing 转为 Paused 状态 , 或超时 , 才能解除阻塞 result = AAudioStream_waitForStateChange(stream, inputState, &nextState, timeoutNanos);
V . AAudio 音频流 状态改变 监听 注意事项
1 . 申请关闭 操作 无法监听状态 : 当前如果是 Stopped 状态 , 调用 AAudioStream_close() 方法后 AAudio 音频流会直接被删除 , 无法调用 AAudioStream_waitForStateChange 方法监听 音频流 状态 ;
2 . 监听时不要关闭流 : 如果调用了 AAudioStream_waitForStateChange () 方法监听 AAudio 音频流 状态 , 当前线程虽然在阻塞状态 , 无法操作 , 但是不要在另外的线程中关闭该 AAudio 音频流 ;