在之前的文章安卓实现录音/播放/暂停/继续的功能中介绍了通过MediaRecorder和MediaPlayer实现简单的录音和播放功能,但相比于安卓二次封装后的API,AudioRecord和AudioTrack更接近底层,可通过获取的PCM数据,进行二次的算法处理,实现更加接近需求的声音。
AndioRecord类的主要功能是让各种JAVA应用能够管理音频资源,以便它们通过此类能够录制声音相关的硬件所收集的声音。此功能的实现就是通过”pulling”(读取)AudioRecord对象的声音数据来完成的。在录音过程中,应用所需要做的就是通过后面三个类方法中的一个去及时地获取AudioRecord对象的录音数据. AudioRecord类提供的三个获取声音数据的方法分别是read(byte[], int, int), read(short[], int, int), read(ByteBuffer, int). 无论选择使用那一个方法都必须事先设定方便用户的声音数据的存储格式。
AudioRecord的使用比较简单,获取音频缓冲区buffer后创建AudioRecord对象,buffer用来保存新的录像数据,该buffer是通过api获取的与设备硬件、设置的参数等相关,如果过大导致超过整个录像的数据,过小导致构造AudioRecord对象失败。
使用流程:
下面结合代码分析流程
BufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_HERTZ,
CHANNEL_CONFIG, AUDIO_FORMAT);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE_HERTZ, CHANNEL_CONFIG, AUDIO_FORMAT, BufferSize);
其中构建AudioRecord对象的对象参数意义如下:
除了上面介绍的几个概念外,还有一个常见的名称:比特率,又称码率,是指每秒传输的数据大小,单位为bps(Bit Per Second),该值越大,说明包括的音视频数据越多,音视频质量越好,基本的计算公式为:
基本的算法是:【码率】(kbps)=【文件大小】(字节)X8/【时间】(秒)× 1000
FileOutputStream PcmFos = new FileOutputStream(new File(path));
//开始录制
mAudioRecord.startRecording();
//不断读取音频缓冲区的数据
while (true == isRecord && !isInterrupted()) {
int read = mAudioRecord.read(bytes, 0, bytes.length);
//若读取数据没有出现错误,将数据写入文件
if (AudioRecord.ERROR_INVALID_OPERATION != read) {
PcmFos.write(bytes, 0, read);
PcmFos.flush();
}
}
mAudioRecord.stop();//暂停录制,如果是单独调用该方法,表示暂停录制操作
mAudioRecord.release();//停止录制
PcmFos.close();//关流
在执行停止或暂停操作时,可通过getState()获取当前的运行状态。
对于通过AudioRecord获取的音频数据是不经过编解码处理的数据,因此不能被常见的音频播放器播放,可通过AdobeAudition软件播放,同样安卓调用时需要通过AudioTrack播放,常见的MediaPlayer也无法正常播放,下面讲解一下AudioTrack的使用。
与AudioRecord类似,也需要先获取播放缓冲区,然后构建AudioTrack对象,主要流程如下:
BufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE_HERTZ,
AudioFormat.CHANNEL_OUT_STEREO, AUDIO_FORMAT);
mAudioTrack = new AudioTrack.Builder()
.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.setAudioFormat(new AudioFormat.Builder()
.setEncoding(AUDIO_FORMAT)
.setSampleRate(SAMPLE_RATE_HERTZ)
.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
.build())
.setBufferSizeInBytes(BufferSize)
.setTransferMode(AudioTrack.MODE_STREAM)
.build();
这里需要注意以下几点:
FileInputStream fis = new FileInputStream(autoFile);
mAudioTrack.play();
byte[] bytes = new byte[BufferSize];
while (true == isRecord) {
int read = fis.read(bytes);
//若读取有错则跳过
if (AudioTrack.ERROR_INVALID_OPERATION == read
|| AudioTrack.ERROR_BAD_VALUE == read) {
continue;
}
if (read != 0 && read != -1) {
mAudioTrack.write(bytes, 0, BufferSize);
} else {
isRecord = false;
}
获取到音频的pcm文件后,开始根据buffer的大小读取文件数据,写入到AudioTrack进行播放,该过程可通过添加状态变量isRecord 来循环遍历读取播放。
mAudioTrack.pause();//暂停
mAudioTrack.stop();//停止
mAudioTrack.release();//释放资源
fis.close();//关流
//状态获取
int state = mAudioTrack.getState();
PCM(Pulse Code Modulation—-脉码调制录音)。所谓PCM录音就是将声音等模拟信号变成符号化的脉冲列,再予以记录。PCM信号是由[1]、[0]等符号构成的数字信号,而未经过任何编码和压缩处理。与模拟信号比,它不易受传送系统的杂波及失真的影响。动态范围宽,可得到音质相当好的影响效果。也就是说,PCM就是没有压缩的编码方式,PCM文件就是采用PCM这种没有压缩的编码方式编码的音频数据文件。
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几!
PCM是一种直接记录数字信号(0或1)的无损压缩方式,而WAV是通过在PCM的基础上增加其特有的头文件形成的一种音频格式。其添加方法可参考河北-宝哥。
API | 优点 | 缺点 |
---|---|---|
AudioRecord | 获取最底层的音频数据,使用更加灵活,可针对获取的音频数据进行处理,例如压缩、网传或算法处理 | 常见的播放器无法正常播放,数据量较大 |
MediaRecorder | android在AudioRecord基础上二次封装的API,便于应用层的开发,使用简单方便,适用于常见的音频播放器 | 无法实施音频处理 |
AudioTrack | 可播放延迟要求低,无须解码的pcm数据 | 无法播放需要解码的音频文件 |
MediaPlayer | 可播放需要解码的常见音频文件,例如MP3、AAC和WAV等数据 | 资源占用较高,需要解码处理,延时较高 |
本文涉及的demo链接
参考链接:
1、https://www.jianshu.com/p/1f78c4211ab7?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
2、https://blog.csdn.net/haovip123/article/details/52356024