Android音频处理-采集

录音功能一般使用MediaRecorder来进行,这种录音方式比较简单,设置好声音源、采样率和编码格式等参数即可,最终得到的是编码压缩后的数据。不过由于我们需要对音频原始数据进行处理,例如混音、变声等操作,所以MediaRecorder不能满足我们的要求。这里介绍下另一种录音工具类 AudioRecord。通过它我们可以对原始音频数据进行采集,以便于后续加工。

AudioRecord

AudioRecord的初始化:

1
2
3
4
5
6
7
int sampleRate = 44100; //音频采样率
int channelConfig = AudioFormat.CHANNEL_IN_STEREO; //音频录制通道,默认为立体声
int audioFormat = AudioFormat.ENCODING_PCM_16BIT; //音频录制格式,默认为PCM16Bit
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);//设置bufferSize为AudioRecord所需最小bufferSize的两倍
AudioRecord mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
channelConfig, audioFormat, bufferSize);//初始化录音器
mRecorder.startRecording();

AudioRecord构造参数:
audioSource 音源,MediaRecorder.AudioSource.MIC 代表音源是麦克风
sampleRate 采样率,由于声音是一种连续的模拟信号,我们要对其进行取样,从而将模拟信号转为离散的数字信号加以利用。采样率则决定了每秒对模拟信号进行采样的次数,这里采样率为44100,也就是通常所说的44.1khz的采样率
channelConfig 音频通道的设置,通常设置为立体声
audioFormat 音频格式,这里设置为16位PCM,也就是每次采样数据为一个short
bufferSize 每次读取数据的最小size,小于这个会导致单次读取的数据不完整

输出PCM文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//生成PCM文件
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/demo.pcm");
//如果存在,就先删除再创建
if (file.exists())
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
throw new IllegalStateException("未能创建" + file.toString());
}
try {
//输出流
OutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
//设置bufferSize为AudioRecord所需小bufferSize的两倍
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat) * 2;
short[] buffer = new short[bufferSize];
isRecording = true;
while (isRecording) {
int bufferReadResult = mRecorder.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
mRecorder.stop();
dos.close();
} catch (Exception e) {
e.printStackTrace();
}

上面的代码将收集到的PCM数据保存到demo.pcm文件,因为是16位PCM格式,所以每个音元均为short型,这点很重要,后面不管是播放还是混音,都要以转换成short型再进行操作。

AudioTrack

一般播放音频我们使用MediaPlayer即可,MediaPlayer支持的音频格式较多,如mp3,aac,wma等,而且调用方式也比较简单,其原理是将输入的音频数据先进行解码,最终MediaPlayer的底层还是要用到AudioTrack来播放解码后的PCM数据,上面我们已经采集到了PCM数据,这里将AudioRecord采集到的数据进行播放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if (file == null) {
file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/demo.pcm");
}
//读取文件
int musicLength = (int) (file.length() / 2);
short[] music = new short[musicLength];
try {
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate, channelConfig,
AudioFormat.ENCODING_PCM_16BIT,
(int) file.length(),
AudioTrack.MODE_STREAM);
audioTrack.play();
InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0) {
music[i] = dis.readShort();
i++;
}
audioTrack.write(music, 0, musicLength);//写入数据
audioTrack.stop();
dis.close();
} catch (Exception e) {
}

AudioTrack有两种播放方式,static和streaming,上面的播放方式为streaming,需要先启动AudioTrack,然后可以将音频数据分段写入(上面的代码中并没有进行分段,可以从后半段数据开始写入,则只播放后半段音频),这里采用了16位PCM的格式,所以每次写入的数据都要为short型的整数倍。而static模式则会一次写入所有的音频数据,然后再启动AudioTrack,这种方式适用于音频数据量较小的情况。

总结

以上为PCM音频数据的采集和播放,这只是最初的一步,有了PCM数据我们就可以进行混音、变音等操作,最终还要进行编码后才能与视频流进行混合。Android音频系统博大精深,之前看到一篇文章,对整个音频系统分析的很透彻,令人叹为观止,有兴趣的同学都可以学习下。

文章目录
  1. 1. AudioRecord
    1. 1.1. AudioRecord的初始化:
    2. 1.2. 输出PCM文件
  2. 2. AudioTrack
  3. 3. 总结
|