Android录音
条评论介绍 Android 中录音功能的实现
录音方法
Android 中的录音主要有两种方式 MediaRecorder 和 AudioRecord
MediaRecorder(基于文件)
可以录制音、视频;
封装了录制、编码、压缩、线程等功能,直接生成可播放的音频文件;
优点:封装度高,操作简单
缺点:编码格式有限,.aac .amr .3gp,但是没有 mp3、wav 格式
AudioRecord(基于字节流)
只能录制音频;
输出的是 PCM 的声音数据,如果保存成文件是不能直接播放的,需要编码;
可以捕获音频流,边录制边处理,比如编码、变声、添加背景音乐。
优点:更灵活
缺点:需自行处理编码、开线程等工作
应用场景:语音聊天、汤姆猫、K歌…
PCM:Pulse Code Modulation(脉冲编码调制),是对连续变化的模拟信号进行抽样、量化和编码产生的数字信号。
它不是一种音频格式,它是声音文件的元数据,也就是声音的内容,没有文件头。经过某种格式的压缩、编码算法处理以后,再加上这种格式的文件头,才是这种格式的音频文件。
音频参数
- 采样频率:
自然界的声音转换成数字格式时,要对它进行采样,每秒钟采样的次数就是采样率。就好比电影的1秒24帧画面。最常用:44.1kHz。
- 采样位数:
一个采样样本用多少位二进制数编码,最常用:16位。
- 声道数:
分为单声道和双声道,双声道又叫立体声,双声道音频文件比单声道大一倍。
- 比特率(码率):
每秒钟音频文件所占的 bit 数。单位 :kbps(每秒千比特数)。比特率(原始音频 PCM) = 采样频率 x 采样位数 x 声道数,这是未经压缩的比特率,压缩后会远小于这个值。
采用44.1kHz采样频率、16位采样位数、双声道编码的原始音频 PCM 比特率为:1411.2 kbps 。而最常见的 mp3 格式的比特率为:128kbps,约 1MB/分钟。
- 编码格式:
将原始音频 PCM 采用特定压缩算法处理后,加上文件头,所保存成的文件的格式。例如 mp3、wav、aac…
编码格式
- mp3
是当今最流行的一种数字音频编码和有损压缩格式,就是将 PCM 通过算法进行压缩,常规 mp3 文件约为 1MB/分钟。
- aac
是 mp3 的下一代格式,也是有损压缩,相对于mp3,aac 格式的音频更佳,文件更小。ios 平台也支持,跨平台性好。
- wav
最流行的非压缩数据格式,微软开发。
- amr
压缩比比较大,但相对其他的压缩格式质量比较差,多用于人声,通话录音。
riff:一种文件描述的格式,wav文件就采用了riff描述,前面44字节就是 riff 描述内容,就是文件头。
MediaRecorder
首先在 AndroidManifest 配置文件中添加录音权限:
1 | <uses-permission android:name="android.permission.RECORD_AUDIO"/> |
Android 6.0 以上还要动态获取权限。
1 | // 录音对象声明 |
录音是耗时操作,但是,由于MediaRecorder
已经封装了线程,故以上代码放在主线程即可。MediaRecorder
是很占资源的,使用完毕需要释放掉:
1 | private void stopRecording() { |
AudioRecord
首先在 AndroidManifest 配置文件中添加录音权限:
1 | <uses-permission android:name="android.permission.RECORD_AUDIO"/> |
当然 Android 6.0 以上还要动态获取权限,具体实现方式请百度之。
1 | // 录音状态 |
1 | /** |
以下是停止录音的方法:
1 | private void stopRecording() { |
边录边播(AudioRecord + AudioTrack)
1 | // 录音状态 |
停止录音和播放:
1 | private void stop() { |
录制mp3格式音频
众多周知,mp3 是跨平台性最好的音频格式,由于采用了压缩率更高的有损压缩算法,文件大小是大约每分钟1M,使其在网络中传输更快,占用存储空间也更少;与此同时,它的声音质量也不错,尤其是人声(相声、评书、脱口秀),当然追求无损音乐的除外。
Android 中没有提供录制 mp3 的 API,需要使用开源库 lame,lame 是专门用于编码 mp3 的轻量高效的 c 代码库。由于采用 c 语言编写,故需要用到 jni。
下载lame库
- lame库下载(以下使用的是
lame
v3.100)
https://sourceforge.net/projects/lame/files/lame/
源码导入
解压下载的lame库,把libmp3lame
文件夹下后缀为.c .h
的文件(不包括子文件夹i386和vector下的)复制到cpp/lame文件夹内,同时把include
目录下的lame.h也复制到cpp/lame文件夹内,此时 lame文件夹内包含42个文件。
(可参考https://github.com/xmaihh/MFSocket/tree/master/liblame/src/main/cpp/lame)
修改库文件
打开刚刚拷贝的lame库文件,修改:
- util.h 文件,把 570 行的两处 ieee754_float32_t 改为 float 因为Android下并不支持该类型
- set_get.h 文件,把头部的 #include <lame.h> 改为 #include “lame.h”
- fft.c 文件,删除第47行 #include “vector/lame_intrin.h”
- id3tag.c和machine.h两个文件里,將HAVE_STRCHR和HAVE_MEMCPY的ifdef结构体删除或者注释
1 |
|
可参考以下完整修改文件
1 | diff --git a/VbrTag.c b/VbrTag.c |
编写CmakeList.txt
1 | cmake_minimum_required(VERSION 3.6.0) |
(可参考https://github.com/xmaihh/MFSocket/blob/master/liblame/CMakeLists.txt)
编写 java 类和 c 文件
1 | public class MP3Recorder { |
生成.h文件
编写MP3Recorder.c
1 |
|
配置build.gradle
1 | android { |
点一下小锤子 :hammer: MakeProject。
编译生成 so库。
录制MP3格式音频
1 | // 录音状态 |
音频解码
想要转换音频格式(如 mp3格式转 wav格式)或者添加背景音乐,都需要解码声音文件。
Android SDK 中提供了解码的 API,它就是 MediaCodec,也就是音频解码器,我们用它实现 mp3格式音频的解码:
把mp3格式转wav格式
1 | public void startDecoding() { |
录音添加背景音乐并实时播放,类似K歌效果
K歌类 APP 都是录音加伴奏,这里实现 mp3 格式的背景音乐解码,与录音合并,并最终输出 mp3 格式的文件。即边录音边解码边合成,录音结束即合并结束。
1 |
|
Reference
Android 录音详解(一)—— MediaRecorder、AudioRecord、生成wav格式、边录边播
Android 录音详解(二)—— 录制 mp3 格式音频( lame 库的编译及使用)
Android 录音详解(三)—— 音频解码
Android 录音详解(四)—— 录音添加背景音乐
本文标题:Android录音
文章作者:xmaihh
发布时间:2019-07-30
最后更新:2019-07-30
原始链接:https://xmaihh.github.io/blog/2019/07/30/android-lu-yin/
版权声明:采用[CC BY-NC-SA 4.0许可协议]进行许可
分享