当前位置: 首页 > news >正文

AAOS系列之(七) --- AudioRecord录音逻辑分析(一)

一文讲透AAOS架构,点到为止不藏私
📌 这篇帖子给大家分析下 AudioRecord的初始化

1. 场景介绍:

在 AAOS 的 Framework 开发中,录音模块几乎是每个项目都会涉及的重要组成部分。无论是语音控制、车内对讲(同行者模式),还是集成科大讯飞等语音识别引擎,都高度依赖系统 Framework 层向 App 层提供稳定、可用的录音数据。

在实现录音功能时,有几个关键参数必须严格设置:采样率、通道数和音频格式。其中,采样率尤为关键。如果设置不当,录制下来的音频数据可能无法被正常解码和回放,从而导致语音引擎识别失败,严重影响用户体验。

因此,在平台开发阶段就需要明确并统一这些参数配置,确保整个语音链路的稳定性和兼容性。

APP端录音的基础代码如下:
// 音频获取源privateintaudioSource=MediaRecorder.AudioSource.MIC;// 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025privatestaticintsampleRateInHz=16000;// 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道privatestaticintchannelConfig=AudioFormat.CHANNEL_IN_STEREO;// 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。privatestaticintaudioFormat=AudioFormat.ENCODING_PCM_16BIT;privateintbufferSizeInBytes=0;privateAudioRecordaudioRecord;privatevoidcreatAudioRecord(){// true: 内建APP使用的录音方式; false:三方APP使用的录音方式.booleanisBuild=true;if(isBuild){// MIC1+MIC2+REF1+REF2bufferSizeInBytes=5120;finalAudioFormataudioFormat1=newAudioFormat.Builder().setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(sampleRateInHz).setChannelIndexMask(0xf)// 设置了这个参数, 采集的就是4通道的数据.build();audioRecord=newAudioRecord.Builder().setAudioFormat(audioFormat1).build();}else{//channelConfig = AudioFormat.CHANNEL_IN_STEREO | AudioFormat.CHANNEL_IN_FRONT_BACK;// 获得缓冲区字节大小bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat);Log.d(TAG,"creatAudioRecord: bufferSizeInBytes = "+bufferSizeInBytes);audioRecord=newAudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,bufferSizeInBytes);}

调用到AudioRecord.java的构造方法,常规APP,比如Hicar,微信, 都是通过标准的API 来调用录音的接口:

//channelConfig = AudioFormat.CHANNEL_IN_STEREO | AudioFormat.CHANNEL_IN_FRONT_BACK;// 获得缓冲区字节大小bufferSizeInBytes=AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig,audioFormat);Log.d(TAG,"creatAudioRecord: bufferSizeInBytes = "+bufferSizeInBytes);// 调用AudioRecord的构造方法.audioRecord=newAudioRecord(audioSource,sampleRateInHz,channelConfig,audioFormat,bufferSizeInBytes);

接下来, 我们来看下AudioRecord.java这个类的方法:

1.调用AudioRecord 的构造方法:
publicclassAudioRecordimplementsAudioRouting,MicrophoneDirection,AudioRecordingMonitor,AudioRecordingMonitorClient{// 标准的APP接口publicAudioRecord(intaudioSource,intsampleRateInHz,intchannelConfig,intaudioFormat,intbufferSizeInBytes)throwsIllegalArgumentException{this((newAudioAttributes.Builder()).setInternalCapturePreset(audioSource).build(),(newAudioFormat.Builder())// 2.这里有个将channelConfig 转换成ChannelMask的流程..setChannelMask(getChannelMaskFromLegacyConfig(channelConfig,true/*allow legacy configurations*/)).setEncoding(audioFormat).setSampleRate(sampleRateInHz).build(),bufferSizeInBytes,AudioManager.AUDIO_SESSION_ID_GENERATE);}}
2.调用getChannelMaskFromLegacyConfig(),将channelConfig转换成ChannelMask:
// 调用这个方法, 我们传入的参数是:CHANNEL_IN_STEREO = 12;privatestaticintgetChannelMaskFromLegacyConfig(intinChannelConfig,booleanallowLegacyConfig){intmask;switch(inChannelConfig){caseAudioFormat.CHANNEL_IN_DEFAULT:// AudioFormat.CHANNEL_CONFIGURATION_DEFAULTcaseAudioFormat.CHANNEL_IN_MONO:caseAudioFormat.CHANNEL_CONFIGURATION_MONO:mask=AudioFormat.CHANNEL_IN_MONO;break;// 传入立体声通道,设置mask为CHANNEL_IN_STEREO,没有改变caseAudioFormat.CHANNEL_IN_STEREO:caseAudioFormat.CHANNEL_CONFIGURATION_STEREO:mask=AudioFormat.CHANNEL_IN_STEREO;break;case(AudioFormat.CHANNEL_IN_FRONT|AudioFormat.CHANNEL_IN_BACK):mask=inChannelConfig;break;default:thrownewIllegalArgumentException("Unsupported channel configuration.");}if(!allowLegacyConfig&&((inChannelConfig==AudioFormat.CHANNEL_CONFIGURATION_MONO)||(inChannelConfig==AudioFormat.CHANNEL_CONFIGURATION_STEREO))){// only happens with the constructor that uses AudioAttributes and AudioFormatthrownewIllegalArgumentException("Unsupported deprecated configuration.");}// 返回mask, 这里的值就是CHANNEL_IN_STEREO = 12returnmask;}

3.调用setChannelMask(),把计算后的mask值设置给AudioRecorder:

这个方法没有什么复杂的逻辑,只是把channelMask直接保存到成员变量mChannelMask

public@NonNullBuildersetChannelMask(intchannelMask){if(channelMask==CHANNEL_INVALID){thrownewIllegalArgumentException("Invalid zero channel mask");}elseif(/* channelMask != 0 && */mChannelIndexMask!=0
http://www.jsqmd.com/news/896062/

相关文章:

  • 终极指南:Hap QuickTime编解码器 - 现代GPU加速视频压缩完整教程
  • 如何高效下载B站大会员视频:5分钟快速上手完整指南
  • 国家中小学智慧教育平台电子课本下载:三步轻松获取PDF教材的完整解决方案
  • 用VTK Glyph3D为流线图注入方向感
  • 深度伪造时代:构建四层防御体系的证据工作流升级指南
  • 多模态大模型技术原理与融合机制深度解析
  • 南昌雅特机电设备:南昌发电机维修哪家靠谱 - LYL仔仔
  • 多智能体协作实战:框架选型vs自研,企业到底怎么选?
  • ECDICT:免费开源英汉词典数据库的终极指南,轻松构建你的语言学习应用
  • 2026年西安净化板厂家推荐排行榜:手工/机制净化板,彩钢岩棉/硅岩/硫氧镁/中空玻镁板,50-100mm厚多规格源头工厂优选 - 品牌企业推荐师(官方)
  • 3分钟免费激活Windows:智能激活工具终极指南
  • 【Agent智能体7 | 智能体设计模式】
  • arXiv论文管理神器:如何用开源工具高效追踪AI研究动态
  • 保姆级教程:从零搞定Sentinel-2 L2A数据下载与Python读取(附避坑指南)
  • 从像素到代码:Mesen如何让NES游戏在现代电脑上重生
  • FanControl:Windows风扇控制终极指南,3步实现零噪音电脑
  • 3步实现HoneySelect2完整汉化与MOD整合:HS2-HF Patch终极指南
  • Adobe GenP 3.0:如何为Adobe Creative Cloud软件实现批量功能解锁
  • 大模型推理优化与工程落地核心技术详解
  • Nigate技术实现深度解析:macOS NTFS读写解决方案架构设计
  • JSON操作封装
  • 2026浙江鞋样设计培训行业标杆名录:5家学校的办学实力与选校参考 - 深度智识库
  • [实战] 扫描图纸怎么添加气泡?制造业质量检验图纸数字化处理全指南
  • CefFlashBrowser:一款免费Flash浏览器,轻松重温经典Flash游戏与内容
  • KMS_VL_ALL_AIO:智能激活引擎的技术赋能之旅
  • Vue集成腾讯云TRTC:从零构建实时音视频通话应用
  • 图片去水印用什么工具好用|2026 免费图片去水印工具推荐与实测对比
  • AI记忆技术:从向量数据库到智能体,如何突破上下文限制实现个性化
  • DPABI实战入门:从零搭建静息态fMRI分析环境与排错指南
  • 永磁节能潜水搅拌机http://www.llhjkj.com/的故障性能特点 - 品牌推荐大师