前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )

【Android 高性能音频】AAudio 状态机 ( 创建 | 打开 Open | 开始 Started | 暂停 Paused | 刷写 Flushed | 停止 Stopped | 关闭 )

作者头像
韩曙亮
发布2023-03-27 17:35:35
7140
发布2023-03-27 17:35:35
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

I . AAudio 音频流 创建 配置 使用 销毁 流程

红色标题是本博客讲解的内容 , 黑色是前几篇讲过的内容 ;

使用 AAudio 音频库 , 首先需要导入 AAudio.h 头文件 ;

代码语言:javascript
复制
#include <AAudio.h>

创建 AAudio 音频流 , 需要先创建 AAudio 音频流构建器 , 然后在通过该构建器创建音频流 ;

代码语言:javascript
复制
    //创建构建器 , AAudio 音频流通过该构建器创建
    //声明 AAudio 音频流构建器 指针
    AAudioStreamBuilder *builder = nullptr;
    //创建 AAudio 音频流构建器 , 注意传入二维指针
    aaudio_result_t result = AAudio_createStreamBuilder(&builder);

设置音频设备 ID ;

代码语言:javascript
复制
    // 设置音频流设备 ID
    AAudioStreamBuilder_setDeviceId(builder, playbackDeviceId_);

设置音频流方向 ;

代码语言:javascript
复制
    // 设置音频流方向
    AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);

设置音频设备共享模式 ;

代码语言:javascript
复制
    // 设置共享模式 , 独占模式性能更高 , 延迟更低 ; 如果 该音频设备正在被使用 , 设置失败会自动设置成 共享模式
    AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);

设置性能模式 ;

代码语言:javascript
复制
    // 设置性能模式
    AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);

设置 AAudio 音频流通道数 :

代码语言:javascript
复制
    // 设置通道个数
    AAudioStreamBuilder_setChannelCount(builder, sampleChannels_);

设置 AAudio 音频流样本格式 :

代码语言:javascript
复制
    // 设置音频格式
    AAudioStreamBuilder_setFormat(builder, sampleFormat_);

设置 AAudio 音频流缓冲区大小 : 这里的缓冲区是播放器的缓冲区 , 单位是帧 , 每帧的采样数就是通道数 , 单声道 每帧 1 个采样, 双声道立体声每帧 2 个采样 , 分别对应左右声道的采样 ;

代码语言:javascript
复制
    // 设置每帧的缓冲区大小 , 可以通过该设置达到尽可能低的延迟
    AAudioStream_setBufferSizeInFrames(playStream_, framesPerBurst_);

创建 AAudio 音频流 : 创建 AAudio 音频流 , 就是打开音频流 , 注意要在音频流参数设置完毕后才能打开音频流 ;

代码语言:javascript
复制
    // 打开音频流 ( 该步骤就是创建音频流 )
    aaudio_result_t result = AAudioStreamBuilder_openStream(builder, &playStream_);

销毁 AAudio 音频流构建器 : 在音频流创建 ( 打开 ) 完毕后 , 应该马上销毁 AAudio 音频流构建器 ;

代码语言:javascript
复制
    //销毁音频流构建器
    AAudioStreamBuilder_delete(builder);

使用 AAudio 音频流 进行 录音 或 播放操作 , 使用完毕后需要 销毁 AAudio 音频流 ;

停止 AAudio 音频流 : 如果 AAudio 音频流不再使用 , 需要马上销毁 AAudio 音频流 , 销毁前需要先将音频流停止 , 然后才能销毁 ;

代码语言:javascript
复制
    //先停止音频流 , 然后才能关闭
    aaudio_result_t result = AAudioStream_requestStop(playStream_);

关闭 AAudio 音频流 : 如果 AAudio 音频流不再使用 , 需要马上销毁 AAudio 音频流 , 该流会占据音频设备资源 , 不用应马上销毁 ;

代码语言:javascript
复制
    //关闭音频流 , 关闭后 , 该音频流就彻底释放了 , 如果在使用 , 必须重新创建
    result = AAudioStream_close(playStream_);
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 状态时 , 接触阻塞 , 继续执行下面的代码 ;
代码语言:javascript
复制
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 状态 ) , 或者超时 , 阻塞解除 , 继续执行下面的代码 ;
代码语言:javascript
复制
//设置当状态与该状态不一致时解除阻塞
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 音频流 ;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
    • I . AAudio 音频流 创建 配置 使用 销毁 流程
      • II . AAudio 音频流 稳定状态 与 过渡状态
        • III . AAudio 音频流 状态改变 监听
          • IV . AAudio 音频流 状态改变 监听 实例 ( 暂停操作 )
            • V . AAudio 音频流 状态改变 监听 注意事项
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档