AAudio进行音频采集的实现

使用AAudio进行音频采集

介绍

	AAudio 是在Android 8.0版本中引入的一种基于C语言的本地音频API。
	Android 8.1版本具有增强功能,可在支持MMAP的HAL和驱动程序结合使用时缩短延迟时间。
	AAUdio提供 OpenSL ES 的替代方案,使用“生成器”设计模式来创建音频流。
	AAudio 提供了一个低延迟数据路径。
	在“专有”模式下,该功能可让客户端应用代码直接写入到与 ALSA 驱动程序共享的内存映射缓冲区。
	在“共享”模式下,MMAP 缓冲区由在 AudioServer 中运行的混音器使用。
	在“专有”模式下,由于数据会绕过混音器,延迟时间会明显缩短。

在下图中,我们可以看到脉冲编码调制 (PCM) 数据通过 MMAP FIFO 向下流入 ALSA 驱动程序。AAudio 服务会定期请求时间戳,然后通过原子消息队列将其传递给客户端的计时模型。
在这里插入图片描述
PS:AAudio是在OpenSL ES的基础上调用的,如果成功则使用AAudio,如果失败则使用OpenSL ES。

前提

	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,1);//设置音频通道个数
	
	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;
	}

其他

关于项目:

  1. 具体的实现直接设置几个按钮:开始录音,停止录音,开始播放,停止播放就可以了。
  2. 具体的代码就不上传了,代码量不多,主要时间花费在Android Studio的工程配置上了。

参考资料:
Android NDK中AAudio介绍
由于官网文件都是英文,看着也比较枯燥,我找了个整理好的大佬博客:韩博主的博客主页
其中一篇AAudio的分析博客链接:https://blog.csdn.net/shulianghan/article/details/103005057

PS:对于AAudio只是初学者,如有不对的地方欢迎指出。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Android Studio中使用AAudio播放音频需要进行以下配置和步骤: 1. 首先,确保你的项目已经使用了最新的Android SDK和NDK版本。 2. 在你的项目的build.gradle文件中,添加以下依赖项: ``` implementation 'androidx.media:media:1.3.0' ``` 3. 在你的代码中,创建一个AAudio流对象并进行初始化: ``` AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); AudioFormat audioFormat = new AudioFormat.Builder() .setSampleRate(44100) .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) .build(); int bufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); AAudioStream aaudioStream = new AAudioStream.Builder() .setAudioFormat(audioFormat) .setBufferSizeInFrames(bufferSize) .setPerformanceMode(AAudioStream.PERFORMANCE_MODE_LOW_LATENCY) .setSharingMode(AAudioStream.SHARING_MODE_SHARED) .setDirection(AAudioStream.DIRECTION_OUTPUT) .build(); ``` 4. 创建一个音频缓冲区,并将音频数据写入AAudio流: ``` byte\[\] audioData = // 从文件或其他来源获取音频数据 int result = aaudioStream.write(audioData, 0, audioData.length, 0); ``` 5. 播放音频数据: ``` aaudioStream.requestStart(); ``` 这样就可以使用AAudioAndroid Studio中播放音频了。请注意,以上代码只是一个简单的示例,你可能需要根据你的具体需求进行适当的修改和调整。同时,还可以考虑使用oboe库来封装AAudio和OpenSL ES,以便在不同版本的Android设备上实现最佳的音频性能。 #### 引用[.reference_title] - *1* *2* [Android-Native开发系列之利用AAudio播放音频](https://blog.csdn.net/qq_34902522/article/details/128893756)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Android使用AAduio实现高性能音频](https://blog.csdn.net/u011686167/article/details/122830491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值