前言
之前學(xué)習(xí)了AudioRecord錄制pcm音頻,與之對(duì)應(yīng)的就是AudioTrack播放pcm音頻(MediaPlayer、SoundPool有其他應(yīng)用場(chǎng)景),它有兩種數(shù)據(jù)加載模式(MODE_STATIC、MODE_STREAM)。
模式
-
MODE_STATIC:這種模式下,一次將所有的數(shù)據(jù)放入一個(gè)固定的buffer,然后寫入到AudioTrack中,后續(xù)就不用繼續(xù)write了。這種模式占用的內(nèi)存較小,適用于短小的音頻,例如手機(jī)鈴聲和系統(tǒng)提示音等。
-
MODE_STREAM:這種模式會(huì)持續(xù)的把音頻數(shù)據(jù)寫入AudioTrack中,write動(dòng)作將堵塞直到數(shù)據(jù)流從java層傳輸?shù)絥ative層,適用于大文件或者播放時(shí)間較長(zhǎng)的文件。
STATIC模式流程
1.另起線程,將音頻文件寫入固定buffer。
2.寫入完成后,初始化AudioTrack(參數(shù)在上一節(jié)有詳細(xì)介紹),接收buffer并播放(play)。
public void initStatic() {
if (staticThread != null) {
staticThread.interrupt();
}
staticThread = new Thread(new Runnable() {
@Override
public void run() {
FileInputStream fileInputStream = null;
try {
File file = new File(filePath);
fileInputStream = new FileInputStream(file);
long size = fileInputStream.getChannel().size();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(audiodata.length);
int byteValue = 0;
long startTime = System.currentTimeMillis();
while ((byteValue = fileInputStream.read()) != -1) {
byteArrayOutputStream.write(byteValue);
}
LogUtils.i("初始化完成" + (System.currentTimeMillis() - startTime));
audiodata = byteArrayOutputStream.toByteArray();
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, audiodata.length, AudioTrack.MODE_STATIC);
audioTrack.write(audiodata, 0, audiodata.length);
audioTrack.play();
LogUtils.i("Static播放");
} catch (Exception e) {
e.printStackTrace();
LogUtils.e(e);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
staticThread.start();
}
STREAM模式流程
1.初始化AudioTrack。
2.另起線程,一邊寫入音頻流文件,一邊播放。
3.播放結(jié)束,關(guān)閉流。
public void startStream() {
if (streamThread != null) {
streamThread.interrupt();
}
if (audioTrack != null) {
audioTrack = null;
}
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, 1600, AudioTrack.MODE_STREAM);
streamThread = new Thread(new Runnable() {
@Override
public void run() {
FileInputStream fileInputStream = null;
File file = new File(filePath);
try {
audioTrack.play();
fileInputStream = new FileInputStream(file);
int byteValue = 0;
while ((byteValue = fileInputStream.read(audiodata)) != -1) {
audioTrack.write(audiodata, 0, byteValue);
}
} catch (Exception e) {
e.printStackTrace();
LogUtils.e(e);
} finally {
if (audioTrack != null) {
audioTrack.stop();
audioTrack = null;
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
streamThread.start();
}
結(jié)語(yǔ)
其實(shí)MediaPlayer底層同樣使用了AudioTrack,但它封裝得比較全面,能支持多種格式得聲音,如MP3,AAC,WAV,OGG等,但是無(wú)法直接播放pcm文件。我們使用AudioTrack,它能控制和播放每一幀的音頻數(shù)據(jù),更接近底層。
本期博客參考:
灰色飄零博客園文章來源:http://www.zghlxwxcb.cn/news/detail-420801.html
需要源碼的盆友也可以訪問我的gitlub,源碼文章來源地址http://www.zghlxwxcb.cn/news/detail-420801.html
到了這里,關(guān)于安卓音視頻開發(fā)(3)—— AudioTrack兩種方式播放pcm音頻的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!