前言
之前学习了AudioRecord录制pcm音频,与之对应的就是AudioTrack播放pcm音频(MediaPlayer、SoundPool有其他应用场景),它有两种数据加载模式(MODE_STATIC、MODE_STREAM)。
模式
-
MODE_STATIC:这种模式下,一次将所有的数据放入一个固定的buffer,然后写入到AudioTrack中,后续就不用继续write了。这种模式占用的内存较小,适用于短小的音频,例如手机铃声和系统提示音等。
-
MODE_STREAM:这种模式会持续的把音频数据写入AudioTrack中,write动作将堵塞直到数据流从java层传输到native层,适用于大文件或者播放时间较长的文件。
STATIC模式流程
1.另起线程,将音频文件写入固定buffer。
2.写入完成后,初始化AudioTrack(参数在上一节有详细介绍),接收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.播放结束,关闭流。
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();
}
结语
其实MediaPlayer底层同样使用了AudioTrack,但它封装得比较全面,能支持多种格式得声音,如MP3,AAC,WAV,OGG等,但是无法直接播放pcm文件。我们使用AudioTrack,它能控制和播放每一帧的音频数据,更接近底层。
本期博客参考:
灰色飘零博客园文章来源:https://www.toymoban.com/news/detail-420801.html
需要源码的盆友也可以访问我的gitlub,源码文章来源地址https://www.toymoban.com/news/detail-420801.html
到了这里,关于安卓音视频开发(3)—— AudioTrack两种方式播放pcm音频的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!