Android音视频开发:AudioRecord录制音频

news/2025/1/7 19:13:13/

简介

AudioRecord是安卓多媒体框架中用于录制音频的工具。它支持录制原始音频数据,即PCM数据,PCM数据不能被播放器直接播放,需要编码压缩成常见音频格式才能被播放器识别。而原生api也提供了AudioTrack播放PCM数据。

录音流程

AudioRecord是通过read方式不断读取来自音源输入的数据流(字节流),进而把数据流保存成PCM数据。

开始录音的时候,AudioRecord需要创建一个缓冲区, 这个缓冲区主要是用来保存新的音频数据,它用于标识一个AudioRecord对象还没有被读取(同步)声音数据前能录多长的音(即一次可以录制的声音容量)。声音数据不断从音频硬件中被读出,每次读取的数据大小不超过初始化缓冲区的容量(录音数据的大小)。

流程如下:

构造一个AudioRecord对象。其中最小录音数据缓存的缓冲区大小可以通过getMinBufferSize方法得到,如果缓冲区容量过小,将导致对象构造的失败。

初始化一个缓冲区,该缓冲区大小大于等于AudioRecord对象用于写声音数据的缓冲区大小,用于缓存读取的音频数据。

startRecording开始录音

创建一个数据流,不断地从AudioRecord中读取声音数据到初始化的缓冲区,然后将缓冲区中的数据输出。

关闭数据流

停止录音

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

示例

下面使用Kotlin代码展示AudioRecord如何录制音频数据:

class AudioActivity : AppCompatActivity() {//音频录制private var audioRecord: AudioRecord? = null//缓冲区大小,缓冲区用于保存音频数据流private var bufferSize: Int = 0//记录是否正在录制音频@Volatile private var isRecording = false//录音线程private var recordThread: Thread? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_media)initRecoder()}/*** 初始化*/private fun initRecoder() {/*getMinBufferSize用于获取成功创建AudioRecord对象所需的最小缓冲区大小,此大小不能保证在负载下能顺利录制,应根据预期的频率选择更高的值,在该频率下,将对AudioRecord实例进行轮询以获取新数据参数介绍:(具体看官网api介绍)sampleRateInHz:采样率,以赫兹为单位channelConfig:音频通道的配置audioFormat:音频数据的格式*/bufferSize = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT)/*构建AudioRecord对象。参数介绍:audioSource:音频来源sampleRateInHz:采样率,以赫兹为单位。目前,只有44100Hz是保证在所有设备上都可以使用的速率(最适合人耳的),但是其他速率(例如22050、16000和11025)可能在某些设备上可以使用channelConfig:音频通道的配置audioFormat:音频数据的格式bufferSizeInBytes:在录制期间写入音频数据的缓冲区的总大小(以字节为单位)*/audioRecord = AudioRecord(MediaRecorder.AudioSource.MIC,44100,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT,bufferSize * 2)}/*** 开始录制*/fun startRecord(view: View) {if (isRecording) {return}isRecording = trueif (recordThread == null) {recordThread = Thread(recordRunnable)}recordThread!!.start()}/*** 停止录制*/fun stopRecord(view: View) {//置为false,表示线程循环就结束了,线程也执行完毕了//也可以直接中断线程isRecording = falseaudioRecord = nullrecordThread = null}/*** 录音线程** 由于需要不断读取音频数据,所以放在子线程操作*/private val recordRunnable = Runnable {//设置线程优先级android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO)//创建文件val tmpFile: File? = FileUtil.createFile("${System.currentTimeMillis()}.pcm")//文件输出流var fos: FileOutputStream = FileOutputStream(tmpFile?.getAbsoluteFile())try {if (audioRecord?.getState() !== AudioRecord.STATE_INITIALIZED) {//没有初始化成功return@Runnable}//开始录制audioRecord?.startRecording()var buffer = 0val bytes = ByteArray(bufferSize)//轮询读取数据while (isRecording) {if (audioRecord != null) {buffer = audioRecord!!.read(bytes, 0, bufferSize)if (buffer == AudioRecord.ERROR_INVALID_OPERATION || buffer == AudioRecord.ERROR_BAD_VALUE) {continue}if (buffer == 0 || buffer == -1) {break}//在此可以对录制音频的数据进行二次处理 如变声,压缩,降噪等操作//也可以直接发送至服务器(实时语音传输) 对方可采用AudioTrack进行播放//这里直接将pcm音频数据写入文件fos.write(bytes)}}} catch (e: Exception) {Log.e("Test", "出错了", e)} finally {try {fos?.close()} catch (ex: IOException) {}audioRecord?.stop()audioRecord?.release()}}
}

如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓


http://www.ppmy.cn/news/474510.html

相关文章

如何进行音频录制?实用的音频录制方法合集

音频录制是一种重要的技能,可以用于各种场合,比如我们可以使用音频录制技术录制不同乐器和声音的音频,并在后期进行处理和混音,制作出完整的音乐作品等等。但是,要想录制出高质量的音频并不容易,需要掌握一…

Linux dd 命令使用

dd命令的使用,等下写

金属元素螯合剂:1189194-64-6,DOTA-(COOt-Bu)3-CH2-Alkynyl,试剂的结构式和CAS分享

文章关键词:双功能螯合剂,大环配体一、试剂基团反应特点(Reagent group reaction characteristics): 西安凯新生物科技有限公司供应的​DOTA-(COOt-Bu)3-CH2-Alkynyl中,​DOTA分子是一种十二元四氮杂大环配…

学习HCIP的day.14

目录 STP生成树协议 生成树协议 一、802.1D 1、根网桥 2、根端口 3、指定端口 4、非指定端口 5、接口状态 802.1D的收敛时间 802.1D算法的缺点 以上cost值的解释 二、PVST 三、PVST 四、快速生成树 五、MSTP/MST/802.1S STP生成树协议 网络三层架构…

什么是序列化与反序列化

序列化:就是将对象转化为字符流的过程。 反序列化:就是将字节流转化为对象的过程。 被序列化的对象类型需要实现Serializable序列化接口,此接口是标志接口。 为保证序列化与反序列化的过程稳定,建议在类中添加序列化版本号。 …

计算机主机sn号怎么查看,笔记本序列号怎么看_笔记本电脑SN序列号的查看方法-win7之家...

序列号就是SN码,通常电脑中都会自带有序列号,可以用来验证真伪或产品是否合法的一组序列号,然而有不少笔记本电脑用户想要查看序列号,就是不知道要怎么看,其实方法有很多,现在就随win7之家小编一起来学习一…

rk3288_android7.1 随机生成SN号问题

问题现象 擦除flash升级后,SN号会被清空,不方便调试;希望擦除flash升级后,可以随机生成SN号 解决方案: system/core/drmservice/drmservice.c 中 SERIALNO_FROM_IDB设为1,会使用工具写入的sn,否…

Android 获取SN号

/*** 根据给定 Key 获取值.** return 如果不存在该 key 则返回空字符串* throws IllegalArgumentException 如果 key 超过 32 个字符则抛出该异常*/public static String get(Context context, String key) throws IllegalArgumentException {String ret;try {ClassLoader cl …