使用AAudio进行音频采集
前提
OpenSL ES对音频的采集方面有的不兼容,准备实现一个通过AAudio进行音频采集。我刚接触只是踩坑。
上网搜了很久,关于AAudio的资料不多。个人觉得参考NDK官网AAudio介绍
和韩曙亮博主的分析
,足够理解AAudio的相关API用处了,具体的demo可参考Oboe项目test部分
(直接搜“GitHub Oboe”就可以)。
我个人只是简单的实现了录音/播放功能。
使用软件和NDK:
- 编辑软件:Android Studio。
- NDK版本:r20。
1. 初始化
1.1头文件
#include <aaudio/AAudio.h> // 调用AAudio库
#include <android/log.h> // 打印log
#include <iostream>
using namespace std;
1.2 相关变量
// AAudio相关变量
AAudioStream *stream;
AAudioStreamBuilder *builder = NULL;
// 存储数据的相关变量
char g_Buffer[1024 * 1024] = {0}; // 音频大小限制为1M,可自行修改
int g_dataSize = 0; // 存放数据大小
int g_readIndex = 0; // 用于定位文件写操作的位置
1.2 初始化StreamBuilder
result=AAudio_createStreamBuilder(&builder);
if(result!=AAUDIO_OK){
LOGE("AAudio_createStreamBuildererror%d",result);
return0;
}
1.3 相关配置
//myAAudioStreamDataCallbackPlay是采集音频数据或者播放音频数据的函数,类似于线程的线程函数。
AAudioStreamBuilder_setDataCallback(builder,myAAudioStreamDataCallbackPlay,this);
//AAUDIO_PERFORMANCE_MODE_LOW_LATENCY是低延迟方式。
AAudioStreamBuilder_setPerformanceMode(builder,AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
1.4 设置具体参数
AAudioStreamBuilder_setDeviceId(builder,18);//设置音频流设备ID
//设置音频流方向,AAUDIO_DIRECTION_INPUT是录音,AAUDIO_DIRECTION_OUTPUT是播放
AAudioStreamBuilder_setDirection(builder,AAUDIO_DIRECTION_OUTPUT);
//设置共享模式,独占模式性能更高,延迟更低;
AAudioStreamBuilder_setSharingMode(builder,AAUDIO_SHARING_MODE_SHARED);
AAudioStreamBuilder_setSampleRate(builder,48000);//设置Rate
AAudioStreamBuilder_setChannelCount(builder,2);//设置音频通道个数
AAudioStreamBuilder_setFormat(builder,AAUDIO_FORMAT_PCM_I16);//设置音频流样本格式
AAudioStreamBuilder_setBufferCapacityInFrames(builder,4096);//在帧中设置缓冲区容量
1.5 获取帧大小
int32_tsizeInFrames = AAudioStream_getBufferSizeInFrames(stream);
LOGI("sizeInFrames = %d",sizeInFrames);
1.6 获取音频流设备ID:
int32_tDeviceId = AAudioStream_getDeviceId(stream);
1.5 打开Stream
result=AAudioStreamBuilder_openStream(builder,&stream);
if(result!=AAUDIO_OK){
LOGE("AAudioStreamBuilder_openStreamerror%d",result);
return0;
}
result=AAudioStream_requestStart(stream);//状态请求。开启音频流,即录音/播放
if(result!=AAUDIO_OK){
LOGE("AAudioStream_requestStarterror%d",result);
return0;
}
2. 数据的采集和播放
2.1 录音
aaudio_data_callback_result_tmyAAudioStreamDataCallback(
AAudioStream*stream,
void*userData,
void*audioData,
int32_tnumFrames){
// 把录音数据存储到本地
//staticFILE*fp=fopen("/sdcard/aaudio_record.pcm","wb");
//if(fp){
// fwrite(audioData,1,2*numFrames*sizeof(short),fp);
//}
//LOGI("myAAudioStreamDataCallbackcall%d,fp:%p",numFrames,fp);
// 把录音数据存储到临时变量中
memcpy(g_Buffer+g_dataSize,audioData,2*numFrames*sizeof(short));
g_dataSize+=2*numFrames*sizeof(short);
returnAAUDIO_CALLBACK_RESULT_CONTINUE;
}
2.2 播放
aaudio_data_callback_result_tmyAAudioStreamDataCallbackPlay(
AAudioStream*stream,
void*userData,
void*audioData,
int32_tnumFrames){
// 从本地视频文件中获取数据
//staticFILE*fp=fopen("/sdcard/aaudio_record.pcm","rb");
//LOGI("myAAudioStreamDataCallbackPlaycall%d,fp:%p",numFrames,fp);
//if(fp){
//size_treadSize=fread(audioData,1,2*numFrames*sizeof(short),fp);
//if(readSize>0){
// returnAAUDIO_CALLBACK_RESULT_CONTINUE;
//}
//}
//returnAAUDIO_CALLBACK_RESULT_STOP;
// 在临时变量中获取数据
LOGI("myAAudioStreamDataCallbackPlaynumFrames:%d,g_dataSize:%d",numFrames,g_dataSize);
constintreadSize=numFrames*2*sizeof(short);
if(g_readIndex+readSize<g_dataSize){
memcpy(audioData,g_Buffer+g_readIndex,readSize);
g_readIndex+=readSize;
returnAAUDIO_CALLBACK_RESULT_CONTINUE;
}else
returnAAUDIO_CALLBACK_RESULT_STOP;
}
其他
关于项目:
- 具体的实现直接设置几个按钮:开始录音,停止录音,开始播放,停止播放就可以了。
- 具体的代码就不上传了,代码量不多,主要时间花费在Android Studio的工程配置上了。
参考资料:
Android NDK中AAudio介绍
由于官网文件都是英文,看着也比较枯燥,我找了个整理好的大佬博客:韩博主的博客主页
其中一篇AAudio的分析博客链接:https://blog.csdn.net/shulianghan/article/details/103005057
PS:对于AAudio只是初学者,如有不对的地方欢迎指出。
来源:CSDN
作者:^Yong^
链接:https://blog.csdn.net/qq_40315987/article/details/103990459