【Android 高性能音频】AAudio 音频流 读写操作 ( 音频流读写数据 | 阻塞时间设定 | 注意事项 | AAudioStream_read | AAudioStream_write )

简介: 【Android 高性能音频】AAudio 音频流 读写操作 ( 音频流读写数据 | 阻塞时间设定 | 注意事项 | AAudioStream_read | AAudioStream_write )

文章目录

I . AAudio 音频流 读写操作 简介

II . AAudio 音频流 读写操作 阻塞时间设定

III . AAudio 音频流 读取 固定帧数 操作 注意点

IV . AAudio 音频流 写出音频数据 操作 注意点

V . AAudio 音频流 读取方法 AAudioStream_read 原型

VI . AAudio 音频流 读取方法 简介

VII . AAudio 音频流 写出方法 AAudioStream_write 原型



I . AAudio 音频流 读写操作 简介


1 . 创建 AAudio 音频流 : 使用 AAudio 音频流构建器 AAudioStreamBuilder 创建 AAudio 音频流后 , 调用 AAudioStreamBuilder_openStream 打开 AAudio 音频流 , 此时音频流正式创建 ;



2 . 开启 AAudio 音频流播放 : 调用 AAudioStream_requestStart 方法 , 即可开始 AAudio 音频流的播放 ;



3 . 读写操作前提 ( Started 状态 ) : 当 AAudio 处于 Started 状态后 , 便可进行 AAudio 音频流的读写操作 ;



4 . 读写操作函数 :


① 读取操作 : 从 AAudio 音频流中读取数据到内存中 , AAudioStream_read(stream, buffer, numFrames, timeoutNanos) ;

② 写出操作 : 将内存中的数据写出到 AAudio 音频流中 , AAudioStream_write(stream, buffer, numFrames, timeoutNanos) ;


5 . 读写数据格式 : AAudio 音频流读写数据的格式 , 与 AAudioStream_getDataFormat() 方法返回的格式 的 采样率 , 样本格式 必须一致 , 否则会出错 ;




II . AAudio 音频流 读写操作 阻塞时间设定


阻塞时间设定 :


① 指定帧数读写 : 如果要读写固定帧数的数据 , 需要设置一个大于 0 的超时时间 , 因为可能会在很长时间内无法读取到足够的数据 , 而一直阻塞 , 导致程序无法执行下去 , 这里设置一个超时时间避免这种情况发生 ;

② 不限定帧数读写 : 如果读写数据不限定帧数 , 则可以将超时时间设置成 0 , 读写的帧数就是实际操作的帧数 ;



III . AAudio 音频流 读取 固定帧数 操作 注意点


AAudio 音频流数据读取 :


① 帧数验证 : 从 AAudio 音频流中读取数据时 , 需要验证当前读取的帧数 ;

② 超时读取 : 如果读取时在超时时间内未能读取到指定 的 numFrames 帧数的数据 , 则也会继续执行, 此时 audioData 中除了读取的数据之外 , 还有一部分未知数据 ;

③ 未知数据 : 因为读取的数据中可能包含未知数据 , 如果将未知数据当做音频采样数据 , 会造成不可预知后果 , 出现电流等干扰 ;

④ 处理方法 : 将非读取的数据使用 0 填充 , 这些数据播放出来就是静音的效果, 没有意外的电流或杂音 ;

⑤ 代码示例 :

设定读取 numFrames 帧数据到 audioData 指针指向的内存中 , 如果 timeout 纳秒内还没读取完毕 , 继续执行下面的代码 , 之后首先判定是否完整读取了 numFrames 帧的数据 , 如果读取了帧数小于 numFrames 需要将后半部分的随机数据设置为 0 ;
//读取 numFrames 帧数据 , 如果帧数不够则一直阻塞 , 直到 timeout 毫秒后 超时 , 然后才能解除阻塞继续执行 ;
aaudio_result_t result =
    AAudioStream_read(stream, audioData, numFrames, timeout);
//如果出现了错误 , 进行错误处理逻辑 ;
if (result < 0) {
  // 错误处理逻辑
}
//如果实际读取的帧数 与 设定读取的帧数不一致 , 一般是读取的帧数小于设定的读取帧数 , 这是由于超时造成的 ; 
if (result != numFrames) {
  // 将 audioData 指针指向的内存中 除 numFrames 帧音频采样数据之外的 剩余其它数据设置成 0 , 即静音效果 ; 
  memset(static_cast<sample_type*>(audioData) + result * samplesPerFrame, 0,
      sizeof(sample_type) * (numFrames - result) * samplesPerFrame);
}




IV . AAudio 音频流 写出音频数据 操作 注意点


AAudio 音频流数据写出 :


① 缓冲区 : 先将数据放入缓冲区 , 该缓冲区大小 与 AAudio 音频流整体性能相关 ;

② 启动音频流 : 将缓冲区中的数据写入 AAudio 音频流 , 将 音频流 启动 ;

③ 超时设置 : 写出数据时 , timeoutNanos 参数必须设置成 0 , 代表其超时时间是 0 纳秒 , 保证该操作是非阻塞操作 ;

④ 缓冲区数据格式 : 缓冲区中存储的音频数据格式 与 AAudioStream_getDataFormat() 方法返回的格式必须一致 ;



V . AAudio 音频流 读取方法 AAudioStream_read 原型


AAudioStream_read 方法简介 :


① 函数原型 : 从 AAudio 音频流中读取数据 , 用于录音 ;

AAUDIO_API aaudio_result_t AAudioStream_read(
  AAudioStream *stream,
  void *buffer,
  int32_t numFrames,
  int64_t timeoutNanoseconds


② AAudioStream *stream 参数 : AAudio 音频流 ;

③ void *buffer 参数 : 从 AAudio 音频流中读取的音频数据指针 , 该指针指向的内存地址中存储读取的音频数据 ;

④ int32_t numFrames 参数 : 读取的帧数 , 每帧的样本数就是通道数 ;

⑤ int64_t timeoutNanoseconds 参数 : AAudio 读取音频流的超时时间 , 如果在这个 timeoutNanoseconds 纳秒内没有读取到 numFrames 帧数据 , 就会解除阻塞 , 继续执行后续代码 ;

⑥ 返回值 : aaudio_result_t 类型 , 返回实际读取到的帧数 , 如果出现错误 , 会返回错误码 ;



VI . AAudio 音频流 读取方法 简介


1 . 方法阻塞时间 : AAudioStream_read 方法执行时会阻塞当前线程 , 满足下面两种条件的任意一种 , 线程阻塞解除 ;


① 执行完毕 : 从 AAudio 音频流中读取了指定帧数的音频数据 ;

② 执行超时 : 没有读取到足够的帧数 , 但是超过了指定的超时时间 , 这种情况返回值返回的是实际读取的音频数据帧数 ;


2 . 方法非阻塞设置 : 如果将 AAudioStream_read 方法的 timeoutNanoseconds 参数设置成 0 , 那么该方法不会阻塞 , 尝试读取一次 , 不管读取到多少数据 , 都会立刻继续执行后续代码 ;



3 . 超时时间说明 : 超时时间 timeoutNanoseconds 纳秒值 , 是一个相对的时间 , 如果线程 sleep 后 , 该时间也会继续计时 , 如果 sleep 结束 , 发现超时时间已过 , 会瞬间解除 AAudioStream_read 方法的阻塞 ;




VII . AAudio 音频流 写出方法 AAudioStream_write 原型


AAudioStream_write 写出方法 :


① 方法原型 : 向 AAudio 音频流中写出音频数据 , 用于播放音频 ;

AAUDIO_API aaudio_result_t AAudioStream_write(
  AAudioStream *stream,
  const void *buffer,
  int32_t numFrames,
  int64_t timeoutNanoseconds


② AAudioStream *stream 参数 : AAudio 音频流 ;

③ void *buffer 参数 : 向 AAudio 音频流中写出的音频数据指针 , 该指针指向的内存地址中存储读取的音频数据首地址 ;

④ int32_t numFrames 参数 : 要写出的帧数 , 每帧的样本数就是通道数 ;

⑤ int64_t timeoutNanoseconds 参数 : AAudio 写出音频流的超时时间 , 如果在这个 timeoutNanoseconds 纳秒内没有写出 numFrames 帧数据 , 就会解除阻塞 , 继续执行后续代码 ;

⑥ 返回值 : aaudio_result_t 类型 , 返回实际写出到 AAudio 音频流的帧数 , 如果出现错误 , 会返回错误码 ;


目录
相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
211 4
|
5月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
|
2月前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
74 2
|
7月前
|
XML 存储 JSON
51. 【Android教程】JSON 数据解析
51. 【Android教程】JSON 数据解析
174 2
|
8月前
|
数据库 Android开发
Android 通过升级SettingsProvider数据强制覆盖用户的设置项
Android 通过升级SettingsProvider数据强制覆盖用户的设置项 【5月更文挑战第7天】
214 5
|
5月前
|
XML Android开发 数据格式
android中两个Activity同时设定了intent-filter的category为android.intent.category.LAUNCHER,会发生什么情况?
本文通过案例分析了在Android中当两个Activity都设置了`android.intent.category.LAUNCHER`类别时,会导致它们同时在应用启动器的"所有应用"页面显示为不同的启动入口。
148 2
android中两个Activity同时设定了intent-filter的category为android.intent.category.LAUNCHER,会发生什么情况?
|
3月前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
111 0
|
5月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
121 1
|
5月前
|
缓存 API Android开发
Android经典实战之Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate
本文介绍了Kotlin中`Flow`的`debounce`、`buffer`及`conflate`三个操作符。`debounce`过滤快速连续数据,仅保留指定时间内的最后一个;`buffer`引入缓存减轻背压;`conflate`仅保留最新数据。通过示例展示了如何在搜索输入和数据流处理中应用这些操作符以提高程序效率和用户体验。
61 6
|
5月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用