簡介
上一篇Android音視頻開發(fā)(一):音頻錄制
我們介紹了如何用AudioRecorder進行錄音,但是我們得到是PCM格式的錄音文件,PCM用平常的軟件是無法播放的,但是我們有不想轉(zhuǎn)換成WAV或者其他格式怎么辦呢,有沒有什么方法可以直接播放PCM格式的文件呢
當然有,那就是使用AudioTrack,可能有的人是第一次見,別擔(dān)心,今天我們就來一起研究下,如何使用AudioTrack播放PCM文件
為什么要使用AudioTrack
有的人可能會說,不能教我們怎么轉(zhuǎn)換成WAV,MP3格式然后直接用MediaPlayer播放嗎,偏偏要用AudioTrack,聽都沒聽過
各位看官別著急,怎么轉(zhuǎn)換格式我之后的章節(jié)會說,我講AudioTrack的目的是因為之后PCM還有更多的應(yīng)用,比如變聲,語音識別等,所以讓我們先學(xué)會怎么播放PCM吧
創(chuàng)建AudioTrack
我們先來創(chuàng)建AudioTrack,創(chuàng)建AudioTrack很簡單,和當時我們創(chuàng)建AudioRecorder差不多
private static final int AUDIO_SAMPLE_RATE = 16000;//采樣率
private static final int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;//編碼格式 PCM 16位
private static final int MODE = AudioTrack.MODE_STREAM;//音頻流的形式
private static final int STREAM_TYPE = android.media.AudioManager.STREAM_MUSIC;//音頻流類型 音樂(用于系統(tǒng)管理)
private static final int AUDIO_OUT_CHANNEL = AudioFormat.CHANNEL_OUT_STEREO;//雙聲道
private int bufferSizeInBytes2 = 0;//最小播放錄音緩存
private AudioTrack mAudioTrack;//AudioTrack
public void createDefaultPlay() {
bufferSizeInBytes2 = AudioTrack.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_OUT_CHANNEL, AUDIO_ENCODING);
mAudioTrack = new AudioTrack(STREAM_TYPE, AUDIO_SAMPLE_RATE, AUDIO_OUT_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes2, MODE);
}
之前我們創(chuàng)建AudioRecorder需要一個叫做最小緩存整數(shù)值,現(xiàn)在我們創(chuàng)建AudioTrack也同樣需要創(chuàng)建一個這樣的值,因為我們播放是以流的形式播放的,也就是一邊讀一邊播,
注意區(qū)分
AudioRecorder創(chuàng)建的細小差別,還有就是要保證采樣率,編碼格式、聲道數(shù)與錄音文件保持一致
這樣,我們的AudioTrack就創(chuàng)建成功了
開始播放
與AudioRecorder有些許不同的是播放不是一開始就啟動的,請注意下面代碼
/**
* 開啟播放子線程
*/
private void startPlayThread() {
new Thread(new Runnable() {
@Override
public void run() {
readDataToAudioTrack();
}
}).start();
}
我們要先開啟播放錄音的子線程,不能直接在主線程操作,因為會阻塞主線程
/**
* 將文件內(nèi)容輸出到AudioTrack
*/
private void readDataToAudioTrack() {
byte[] audioData = new byte[bufferSizeInBytes2];
DataInputStream stream = null;
int readSize = 0;
try {
stream = new DataInputStream(new FileInputStream(mPlayFileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
while (stream.available() > 0) {
readSize = stream.read(audioData);
if (readSize == AudioTrack.ERROR_INVALID_OPERATION || readSize == AudioTrack.ERROR_BAD_VALUE) {
continue;
}
if (readSize > 0) {
mAudioTrack.play();
mAudioTrack.write(audioData, 0, readSize);
}
}
mAudioTrack.stop();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
可以看到,我們是在去讀到文件內(nèi)容后再去調(diào)用mAudioTrack.play()和mAudioTrack.write(audioData, 0, readSize),當然,這也符合邏輯,因為必須得到數(shù)據(jù)才可以去播放,當我們while循環(huán)結(jié)束后,我們就停止播放,并關(guān)閉相應(yīng)的文件流
最后
這樣,我們完整地播放了一段PCM格式的錄音文件,希望大家能喜歡。