【Android 高性能音频】AAudio 音频流 PCM 采样 的 采样 缓冲 播放 的 连续机制 ( 数据回调机制 | 数据回调函数指针 | 实现数据回调函数 | 设置数据回调函数 )

简介: 【Android 高性能音频】AAudio 音频流 PCM 采样 的 采样 缓冲 播放 的 连续机制 ( 数据回调机制 | 数据回调函数指针 | 实现数据回调函数 | 设置数据回调函数 )

文章目录

I . AAudio 音频流 采样 缓冲 播放 的连续机制

II . AAudio 音频流 数据回调函数 函数指针类型定义

III . AAudio 音频流 数据回调函数 实现

IV . AAudio 音频流 数据回调函数 设置



I . AAudio 音频流 采样 缓冲 播放 的连续机制


1 . AAudio 音频流的 采样 缓冲 播放 流程 : 样本采样完成后 , 存入缓冲区 , 然后将其通过 AAudio 播放出来 , 采样阶段采集 n nn 个样本 , 然后将其放入缓冲区 , 将缓冲区的数据 写出到 AAudio 音频流中播放出来 ;



2 . 采样速度高于播放速度 : 如果采样采集多了 , 不能立刻播放 , 此时就会产生延迟 , 并且如果超出缓冲区大小 , 超出部分采样就会溢出 , 造成数据损失 , 样本不连续 , 就会产生电流 ;



3 . 采样速度低于播放速度 : 如果采样少了 , 不能向 AAudio 音频流中写入足够的数据 , 就会造成电流杂音等情况 ;



4 . 数据回调函数 引入 : 数据回调函数就是为了解决上述问题 , 引入的机制 ;



5 . 数据回调函数 简介 :


① 采样缓冲 : 采样后 , 将采集的样本存入缓冲区 ;

② 播放采样 : 将缓冲区中的样本写入 AAudio 音频流 ;

③ 调用回调函数 : AAudio 音频流如果播放完当前数据 , AAudio 就会自动调用 开发者按照 规范开发的 回调函数 申请后续采样数据 ;

④ 回调函数内容 : 开发者自己实现该回调函数 , 在这个函数中实现采样 并将采样设置给 AAudio 音频流 , 之后继续播放音频采样 ;

之后如果采样播放完毕 , 继续调用回调函数 ;



下面会着重讲解该数据回调函数的细节




II . AAudio 音频流 数据回调函数 函数指针类型定义


数据回调函数原型 : AAudio 只定义了一个函数类型 , 该函数的实际内容需要开发者自己开发 , 一般是 采样 , 然后 设置数据给 AAudio 音频流 的操作 ;


t

ypedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames);


① 函数类型 : 该数据回调函数类型如下 , 其返回值是 aaudio_data_callback_result_t 类型 , 四个参数分别如下 ;

aaudio_data_callback_result_t (*)(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames)


② 函数别名 : 使用 typedef 关键字为 上述函数指针类型 赋予一个类型别名 AAudioStream_dataCallback ;

③ 参数一 AAudioStream *stream : AAudio 音频流指针 ;

④ 参数二 void *userData : 该参数用于传递一些额外数据 , 与 AAudioStreamBuilder_setCallback() 中的 第三参数 void *userData 参数指向的地址一致 ;

⑤ 参数三 void *audioData : 指向音频采样数据的指针 , AAudio 会自动将该数据输出或输入到音频流中 ;

⑥ 参数四 int32_t numFrames : 要处理的帧数 , 需要将多少帧的 audioData 指针指向的音频采样数据 , 输入 或 输出到 AAudio 音频流中 ;



III . AAudio 音频流 数据回调函数 实现


aaudio_data_callback_result_t (*)(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames)


1 . 数据回调函数设置给 AAudio 音频流 : AAudio 中通过 AAudioStreamBuilder_setDataCallback() 函数 , 将用户自己实现的 AAudioStream_dataCallback 回调函数的函数指针设置给 AAudio 音频流 , 当 AAudio 音频流需要数据时会自动回调该函数 ;



2 . 输出流回调函数实现内容 : 在该函数中需要 按照 AAudio 音频流的当前数据格式 ( 通道数/每帧样本数 , 采样率 ) , 采集 numFrames 帧的 PCM 音频样本数据 ( 每帧的采样数与通道数一致 ) , 将这些样本数据写出到 void *audioData 指针指向的内存中 , 之后这些数据会被自动输出到 AAudio 音频流中 ;



3 . 输入流回调函数实现内容 : 在函数中需要从 void *audioData 指针指向的内存中 , 读取 numFrames 帧 ( 每帧的采样数与通道数一致 ) 的采样数据 , 注意需要按照当前的 采样格式 ( 通道数/每帧样本数 , 采样率 ) 计算读取的字节大小 ;



4 . 采样数据自动传输 ( 不需要手动干预 ) : 在回调函数中 , 将 numFrames 帧的数据传递给 void *audioData , AAudio 在该回调函数执行完毕后 , 会自动将这些数据 读/写 到 AAudio 音频流中 , 不需要 开发者 手动调用 AAudioStream_read() 或 AAudioStream_write() 方法 , 一调用必出错 ;



5 . 每次读写的帧数 int32_t numFrames :


① 固定帧数 : 通过调用 AAudioStreamBuilder_setFramesPerDataCallback() 方法可以设置每次回调都读写固定帧数的音频采样 ;

② 自由帧数 : 如果用户没有指定帧数 , 那么在每次回调函数中的 numFrames 帧数可以由用户自己设置 ;


6 . 不能执行耗时操作 : 在该回调函数中 , 不能执行太耗时的操作 或 阻塞操作 , 如果阻塞时间超过了采样播放的时间 , 就会造成后续采样无法及时 读取 或 写入 到 AAudio 音频流中 , 出现音频故障 ;



7 . 回调函数中不能执行的操作 : 该回调函数的回调频率很高 , 可能达到每秒几百到几千次 , 因此有很多 耗时操作 或 访问本地资源 的逻辑不能再该函数中运行 , 尽可能只对内存数据进行操作 ;


① 内存操作 : 使用 malloc() 或 new 分配堆内存 , 极大可能造成内存泄漏或内存溢出 ;

② 文件操作 : 打开 open , 关闭 close , 读取 read , 写出 write 等针对文件的操作 ;

③ 网络操作 : 访问网络操作 , 从网络中读取数据 , 或向远程端口发送数据 ;

④ 同步线程 : 线程间的同步操作会造成阻塞 ;

⑤ 休眠阻塞 : sleep 方法不能执行 , 会造成阻塞 ;

⑥ 关音频流 : 停止 或 关闭 流操作 会造成不可预知故障 ;

⑦ 读写操作 : 该函数中不用刻意调用 AAudioStream_read() 和 AAudioStream_write() 方法进行读写操作 ;


8 . 回调函数中可以进行的操作 :


① 调用 AAudioStream_getXXX() 类方法 : 如下图中列举的方法可以直接调用 , 获取 AAudio 音频流的各种属性 ;

image.png

② 调用 AAudio_convertResultToText() 方法 : 将返回值转为对应的 ASCII 字符 ;


9 . 非阻塞技术 : 如果需要在回调函数中 读取 或 输出 数据 , 建议使用非阻塞技术 , 如 FIFO 技术 ;




IV . AAudio 音频流 数据回调函数 设置


1 . 数据回调函数设置方法 :


① 函数原型 : 该方法用于设置 AAudio 音频流回调函数 , 当 AAudio 需要 读取 / 写出数据时 , 会自动回调该 AAudioStream_dataCallback 类型 函数 ;

AAUDIO_API void AAudioStreamBuilder_setDataCallback(
  AAudioStreamBuilder *builder,
  AAudioStream_dataCallback callback,
  void *userData


② 参数 一 AAudioStreamBuilder *builder : AAudio 音频流指针 ;

③ 参数 二 AAudioStream_dataCallback callback : AAudioStream_dataCallback 是函数指针类型 , 开发者自己实现该函数 , 然后将函数的地址当做参数设置到此处 ;

typedef aaudio_data_callback_result_t (*AAudioStream_dataCallback)(
        AAudioStream *stream,
        void *userData,
        void *audioData,
        int32_t numFrames);


④ 参数 三 void *userData : 该指针 与 AAudioStream_dataCallback 函数指针类型的第二个参数指向的地址是相同的 , 相当于传入一个用户自定义的指针 , 可以是任意类型任意数据任意变量 ;

2 . 音频数据传递方式 : 在 AAudioStream_dataCallback 函数指针类型的回调函数中 , 音频流的数据不是通过 AAudioStream_read 或 AAudioStream_write 方法进行读写的 , 只要将音频采样数据设置给函数的第三个参数 audioData 指针即可 , 第四个参数 numFrames 用于说明读写数据的帧数 , 每帧的采样数 就是 采样的通道数 ;


3 . 数据回调函数工作机制 :


① 第一次回调 : 在 AAudio 音频流调用 AAudioStream_requestStart() 方法后 , 会立刻回调该数据回调函数 , 然后第一次 读写采样数据到 AAudio 音频流中 ;

② 循环回调 : 当 AAudio 音频流 读取或写出数据完毕后 , 会自动回调该数据回调函数 , 在回调函数中准备下一次的采样 , 读写到 AAudio 音频流中 , 之后继续循环 , 直到 AAudio 音频流关闭销毁 ;

③ 实时线程 : AAudio 拥有一个实时线程 , 该数据回调函数就是运行在这个线程上的 ;


目录
相关文章
|
4月前
|
存储 安全 Android开发
探索Android与iOS的隐私保护机制
在数字化时代,移动设备已成为我们生活的一部分,而隐私安全是用户最为关注的问题之一。本文将深入探讨Android和iOS两大主流操作系统在隐私保护方面的策略和实现方式,分析它们各自的优势和不足,以及如何更好地保护用户的隐私。
|
5月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
68 2
|
4月前
|
Linux Android开发 iOS开发
深入探索Android与iOS的多任务处理机制
在移动操作系统领域,Android和iOS各有千秋,尤其在多任务处理上展现出不同的设计理念和技术实现。本文将深入剖析两大平台在后台管理、资源分配及用户体验方面的策略差异,揭示它们如何平衡性能与电池寿命,为用户带来流畅而高效的操作体验。通过对比分析,我们不仅能够更好地理解各自系统的工作机制,还能为开发者优化应用提供参考。
|
4月前
|
算法 Linux 调度
深入探索安卓系统的多任务处理机制
【10月更文挑战第21天】 本文旨在为读者提供一个关于Android系统多任务处理机制的全面解析。我们将从Android操作系统的核心架构出发,探讨其如何管理多个应用程序的同时运行,包括进程调度、内存管理和电量优化等方面。通过深入分析,本文揭示了Android在处理多任务时所面临的挑战以及它如何通过创新的解决方案来提高用户体验和设备性能。
105 1
|
5月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
5月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
83 1
|
5月前
|
存储 安全 数据安全/隐私保护
探索安卓与iOS的隐私保护机制####
【10月更文挑战第15天】 本文深入剖析了安卓和iOS两大操作系统在隐私保护方面的策略与技术实现,旨在揭示两者如何通过不同的技术手段来保障用户数据的安全与隐私。文章将逐一探讨各自的隐私控制功能、加密措施以及用户权限管理,为读者提供一个全面而深入的理解。 ####
168 1
|
5月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
140 2
|
6月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
115 8
|
6月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
404 3

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 5
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
  • 6
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 8
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
  • 9
    Android实战经验之Kotlin中快速实现MVI架构
  • 10
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
  • 1
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
    66
  • 2
    android FragmentManager 删除所有Fragment 重建
    25
  • 3
    Android实战经验之Kotlin中快速实现MVI架构
    42
  • 4
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    42
  • 5
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    46
  • 6
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    158
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    55
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    73
  • 9
    Android历史版本与APK文件结构
    182
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    54