使用AudioRecord录制语音

来源:互联网 发布:linux mysql配置文件 编辑:程序博客网 时间:2024/06/05 14:25

Android中录制语音最简单的方式是使用MediaRecorder来录制,但是MediaRecorder只能录制几种语音格式,录制的结果也是直接保存到了文件中。如果需要实现自定义的需求,比如录制过程中显示音量的大小,就得使用AudioRecord来录制语音了。

几个概念

在 数字音频基础 中讲到了一些数字音频的基础知识,这里将几个需要用到的概念再解释下:

  1. 采样:录音的本质就是将连续的空气压力变化录制下来。由于时间是连续的,数字化录音就只能在某些时间记录下那时的空气压力变化,这个过程就是采样。
  2. 量化及量化误差:量化就是用数字来表示空气压力的变化值,由于计算机的存储能力有限,无法精确表达所有的空气压力变化值,所以真实的压力值肯定会与量化值有一定的误差。
  3. 通道数:这个就和我们日常所说的左声道、右声道是一个意思,通道数指的就是有多少个声道。
  4. 采样率:即一秒钟采集的次数。

涉及的方法参数解析

在录音的时候,我们需要构造一个AudioRecord对象,然后通过它与硬件设备打交道,来获取语音数据。先看看它的构造函数:

public AudioRecord(int audioSource,                   int sampleRateInHz,                   int channelConfig,                   int audioFormat,                   int bufferSizeInBytes)

audioSource:录音源,指定声音是从哪里录制的,常用的参数有:MIC、VOICE_COMMUNICATION。MIC录制的时候没啥特别的,但是VOICE_COMMUNICATION就有些特别,它表示当前录音是为了语音通信,比如VoIP。在这种场景下,驱动及硬件就可以做一些特殊的处理,比如开启回声消除等算法来达到更好的通话音质。

sampleRateInHz:即前面说的采样率,常用采样率有:8000、16000,CD音质使用的是44.1khz。

channelConfig:声道配置,和日常说的左右声道意思一样,只是这个参数所使用的值是一些规定好的值,比如CHANNEL_IN_MONO表示单声道,CHANNEL_IN_STEREO表示立体声。

audioFormat:这个是指量化所采用的方案,一般使用的是 ENCODING_PCM_16BIT 或ENCODING_PCM_8BIT,PCM表示两个量化值之间是线性关系,而不是类似指数那种关系。16BIT和8BIT指的是使用2个字节来表示一个量化点,还是使用一个字节来表示。

bufferSizeInBytes:用字节表示的缓冲区大小,AudioRecord在收集到语音数据后,会缓存到特定的缓冲区里面,等待调用者读取。缓冲区的大小不能小于getMinBufferSize所返回的值,否则会导致初始化失败。调用者为了防止未能及时获取语音数据,而导致语音数据丢失,可以将这个值设为几倍于最小缓冲区的大小。

public int read(byte[] audioData,                int offsetInBytes,                int sizeInBytes)

在开始录制之后,需要调用这个方法获取语音数据。这个方法是一个阻塞的方法,在audioData填满后,或者发生错误时,这个方法才会返回。

这个缓冲区的大小的设定,一般是和一帧的数据量有关,一帧通常设为20ms。比如在采样率为16000、立体声、ENCODING_PCM_16BIT 的场景下,20ms就需要采样320次(16000/1000*20),每次采样需要采集2个点(左右声道),每个采样点两个字节(16BIT),所以20ms的数据量为1280字节。

录音流程

录音流程比较简单:

  1. 构造AudioRecord对象。
  2. 调用AudioRecord.getState检查AudioRecord对象是否有效,如果无效表示初始化失败,直接结束。
  3. 调用AudioRecord.startRecording开始录音。
  4. 调用AudioRecord.read读取数据,read返回后,将数据写入文件。
  5. 调用AudioRecord.stopRecording结束录音。

该流程使用的是read方法来读取数据,AudioRecord也提供了通知方式来读取数据,即周期性的通知数据到了。

这里就不之间贴代码了,需要的读者可以见该文件。

语音数据的处理

在read返回之后,缓冲区里面存储的就是语音的数据,通过对语音的数据进行一些处理,可以达到某些目的。语音数据排列是按照每个采样点顺序排列的,如果是多声道的语音数据,则两个声道也是按照顺序排列的。通过检查采样点的数值,我们可以做以下两种事情:

  1. 显示当前音量大小:每个采样点的数值及时反馈到UI界面上,给用户反馈,让用户知道当前的声音大小。
  2. 静音检测:如果用户不给应用录音权限的时候,程序读取到的数据都是没有声音的,也就是采样点的值为0。通过检查采样点的数值是否都为0,可以判断出来是否有录音权限。
0 0
原创粉丝点击