【Android 高性能音频】Oboe 开发流程 ( Oboe 音频帧简介 | AudioStreamCallback 中的数据帧说明 )
文章目录
Oboe GitHub 主页 : GitHub/Oboe
- ① 简单使用 : Getting Started
- ② Oboe 全指南 : Full Guide To Oboe
- ③ Oboe API 参考 : API reference
- ④ Android 音频框架发展 : Android audio history
在 【Android 高性能音频】Oboe 开发流程 ( 导入 Oboe 库 | 使用预构建的二进制库和头文件 | 编译 Oboe 源码 ) 博客中介绍了 如何导入 Oboe 函数库到项目中 , 本博客中在导入 Oboe 函数库的基础上 , 进行 Oboe 播放器功能开发 ;
在 【Android 高性能音频】Oboe 开发流程 ( 包含头 Oboe 头文件 | 创建音频流 | 设置音频流 | 音频流回调类 AudioStreamCallback ) 介绍了如何创建 AudioStreamBuilder , 以及 创建 AudioStreamCallback 回调 ;
在 【Android 高性能音频】Oboe 开发流程 ( 创建并设置 AudioStreamCallback 对象 | 打开 Oboe 音频流 | 日志封装 logging_macros.h ) 博客中介绍了 设置 AudioStreamCallback 对象 , 打开 Oboe 音频流 操作 , 以及 Google 官方提供的日志封装有文件 ;
在 【Android 高性能音频】Oboe 开发流程 ( 检查 Oboe 音频流属性 | 开始播放 | 停止播放 | 关闭 Oboe 音频流 | 重新配置 Oboe 音频流属性 ) 博客中介绍了 如何开始 Oboe 音频流播放 , 以及 播放完毕后的收尾工作 ;
在 【Android 高性能音频】Oboe 开发流程 ( Oboe 完整代码示例 ) 中展示了一个 完整的 Oboe 播放器案例 ;
一、音频帧概念
帧 代表一个 声音单元 , 该单元中的 采样个数 是 声道数 ;
该 声音单元 ( 帧 ) 中的 采样大小 是 样本位数 与 声道数 乘积 ;
下面的代码是 【Android 高性能音频】Oboe 开发流程 ( Oboe 完整代码示例 ) 博客中的 Oboe 音频流创建时 的代码 , 设置 Oboe 音频流 的参数如下 ;
设置的 采样格式 是 oboe::AudioFormat::Float , 每个采样都是一个 float 单精度浮点数 ,
字节 ;
设置的 声道数 是 oboe::ChannelCount::Stereo , 立体声 , 左右双声道 ;
则对应的
个音频帧 中包含
个采样 , 左声道
个采样 , 右声道
个采样 , 每个采样是
字节的单精度浮点类型 float 类型 ;
上述
个音频帧的字节大小是
字节 ;
// 1. 音频流构建器
oboe::AudioStreamBuilder builder = oboe::AudioStreamBuilder();
// 设置音频流方向
builder.setDirection(oboe::Direction::Output);
// 设置性能优先级
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
// 设置共享模式 , 独占
builder.setSharingMode(oboe::SharingMode::Exclusive);
// 设置音频采样格式
builder.setFormat(oboe::AudioFormat::Float);
// 设置声道数 , 单声道/立体声
builder.setChannelCount(oboe::ChannelCount::Stereo);
// 设置采样率
builder.setSampleRate(48000);
// 设置回调对象 , 注意要设置 AudioStreamCallback * 指针类型
builder.setCallback(&myCallback);
如果设置的 采样格式 是 oboe::AudioFormat::I16 , 每个采样都是一个
位整型 ,
字节 , 相当于 short 类型 ;
设置的 声道数 是 oboe::ChannelCount::Stereo , 立体声 , 左右双声道 ;
则对应的
个音频帧 中包含
个采样 , 左声道
个采样 , 右声道
个采样 , 每个采样是
字节的 short 类型 ;
上述
个音频帧的字节大小是
字节 ;
二、AudioStreamCallback 中的音频数据帧说明
在 Oboe 播放器回调类 oboe::AudioStreamCallback 中 , 实现的 onAudioReady 方法 ,
其中的 int32_t numFrames 就是本次需要采样的帧数 ,
注意单位是音频帧 ,
这里的音频帧就是上面所说的
采样格式 是 oboe::AudioFormat::Float , 每个采样都是一个 float 单精度浮点数 ,
字节 ,
声道数 是 oboe::ChannelCount::Stereo , 立体声 , 左右双声道 ,
对应的
个音频帧 中包含
个采样 , 左声道
个采样 , 右声道
个采样 , 每个采样是
字节的单精度浮点类型 float 类型 ;
上述
个音频帧的字节大小是
字节 ;
因此在该方法中的后续采样 , 每帧都要采集
个样本 , 每个样本
字节 , 每帧采集
字节的样本 ,
总共 numFrames 帧需要采集 numFrames 乘以
字节的音频采样 ;
在 onAudioReady 方法中 , 需要 采集
numFrames 字节 的音频数据样本 , 并将数据拷贝到 void *audioData 指针指向的内存中 ;
// Oboe 音频流回调类
class MyCallback : public oboe::AudioStreamCallback {
public:
oboe::DataCallbackResult
onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
// 需要生成 AudioFormat::Float 类型数据 , 该缓冲区类型也是该类型
// 生产者需要检查该格式
// oboe::AudioStream *audioStream 已经转换为适当的类型
// 获取音频数据缓冲区
auto *floatData = static_cast<float *>(audioData);
// 生成正弦波数据
for (int i = 0; i < numFrames; ++i) {
float sampleValue = kAmplitude * sinf(mPhase);
for (int j = 0; j < kChannelCount; j++) {
floatData[i * kChannelCount + j] = sampleValue;
}
mPhase += mPhaseIncrement;
if (mPhase >= kTwoPi) mPhase -= kTwoPi;
}
LOGI("回调 onAudioReady");
return oboe::DataCallbackResult::Continue;
}
};
相关文章
- android开机动画多长时间_Android开机动画原理分析
- 74款android开机动画,修改Android系统开机动画
- delphixe5 android,Delphi XE5 Android手机端转换Ansi字符串
- android activity singletask,Android Activity启动模式之singleTask实例详解
- android vlc 中文字幕,解决Android版vlc中文乱码问题
- android sdk安装过程,图文详解Android 3.0 SDK安装教程
- android 获取收到短信验证码,Android自动获取短信验证码
- android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
- 【Android从零单排系列七】《Android视图控件——EditText》
- 【错误记录】Flutter 混合开发报错 ( Android 端与 Flutter 端 EventChannel 初始化顺序错误导致无法通信 | EventChannel 通信流程 )
- 【Java 虚拟机原理】Android 类加载机制 ( 双亲委派机制 | BootClassLoader | PathClassLoader | DexClassLoader )
- 【Android 逆向】Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
- 【Android 逆向】Dalvik 函数抽取加壳 ③ ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName函数 )
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( ./init-android.sh: 第 37 行: cd: android/contrib/: 没有那个文件或目录 )
- 【Android Gradle 插件】PackagingOptions 配置 ④ ( pickFirsts、merges、excludes 属性配置 Set<String> 类型属性值常用配置方法 )
- Ubuntu 上使用 ADB 备份 Android 数据
- android-async-http详解手机开发
- android画图之贝塞尔曲线讲解详解手机开发
- Android 四种常见的线程池详解手机开发
- Android中的ProgressBar的android:indeterminate详解手机开发
- 新品秀:Dell Cast,让Android平板变身台式PC
- 「唯物」把Windows和Android来Remix一下,就得出了这个东西
- Android开发技巧之ViewStub控件惰性装载
- Android中的android:layout_weight使用详解
- android实现背景平铺的三种方法
- Android中通知栏跳动问题解决方法