使用AudioTrack组件,对
Pcm原始格式的音频文件进行播放
一、音频播放
1.1 MediaPlayer
通常,在Android开发中,对于播放音频,会考虑使用MediaPlayer进行播放,比如mp3、aac文件的播放
MediaPlayer的使用流程一般是
-
构建实例
MediaPlayer mediaPlayer = new MediaPlayer() -
设置播放路径
MediaPlayer mediaPlayer.setDataSource(path) -
准备
MediaPlayer prepare() -
开始播放
MediaPlayer.start() -
停止播放
MediaPlayer.stop()
当然,MediaPlayer的功能还是比较强大的,除了上述的基本功能,还有暂停、跳转等功能,还可以设置一些状态回调
正因如此,在一般的开发中,使用MediaPlayer播放音频是很方便的,不过,如果要播放Pcm格式的音频文件,那么MediaPlayer就行不通了
那该怎么办,其实Android提供了Pcm格式音频文件的播放组件,那就是AudioTrack,相比于MediaPlayer,AudioTrack是专门播放Pcm格式音频文件的组件
1.2 AudioTrack
上一章,通过使用AudioRecord录制了一段Pcm格式的音频文件,正愁没播放器播放,也就不知道录制的Pcm是否正常,那么就可以通过AudioTrack来验证录制的Pcm是否正常
AudioTrack的使用流程和AudioRecord很像
- 开启子线程
- 构建实例
- 开始播放
- 循环读取文件数据,并写入
AudioTrack - 停止播放,释放资源
下面会详细介绍AudioTrack的播放流程
二、AudioTrack播放流程
2.1 开启子线程
和AudioRecord的录制流程一样,AudioTrack的播放流程也都是需要在子线程中执行
private static class PlayThread extends Thread {
public PlayThread(){}
}
2.2 配置必要参数
private static class PlayThread extends Thread {
/**
* pcm播放组件
*/
private AudioTrack audioTrack;
/**
* 文件输入
*/
private FileInputStream fis;
private final String path;
/**
* 音频流格式(一般使用music)
*/
private final int streamType;
/**
* 采样率
*/
private final int sampleRateInHz;
/**
* 声道设置
*/
private final int channelConfig;
/**
* 编码格式
*/
private final int audioFormat;
/**
* 播放模式(一般使用流模式)
*/
private final int mod;
/**
* 音频缓存大小
*/
private int bufferSizeInBytes;
/**
* 是否停止播放
*/
private boolean isStopPlay = false;
/**
* 构造方法(传入必要的参数)
*/
public PlayThread(String path,
int streamType,
int sampleRateInHz,
int channelConfig,
int audioFormat,
int mod
) {
this.path = path;
this.streamType = streamType;
this.sampleRateInHz = sampleRateInHz;
this.channelConfig = channelConfig;
this.audioFormat = audioFormat;
this.mod = mod;
}
}
构建AudioTrack需要如下参数
-
streamType音频流的类型,在Android音频管理中,有很多音频流类型,一般使用
AudioManager.STREAM_MUSIC即可 -
sampleRateInHz采样率,一般使用
44100 -
channelConfig声道设置,单声道
CHANNEL_OUT_MONO,双声道CHANNEL_OUT_STEREO,注意,区别于AudioRecord的channelConfig,一个是in,一个是out,分别表示输入和输出 -
audioFormat和
AudioRecord一样,同样可以选择ENCODING_PCM_8BIT和ENCODING_PCM_16BIT -
mod该参数表示
AudioTrack的使用类型,通常使用AudioTrack.MODE_STREAM类型 -
bufferSizeInBytes该参数和
AudioRecord的一样,都是表示buffer的缓存大小,在写入AudioTrack时使用
2.3 初始化
重写Thread的run方法
# run()
@Override
public void run() {
super.run();
initIo();
initAudioTrack();
play();
}
run方法里面调用了三个方法,分别是
-
initIo()初始化读取的文件IO流
-
initAudioTrack()初始化
AudioTrack组件 -
play()真正开始播放
# initIo()
/**
* 初始化IO
*/
private void initIo() {
if (TextUtils.isEmpty(path)) {
return;
}
try {
fis = new FileInputStream(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
fis = null;
}
}
# initAudioTrack()
/**
* 初始化pcm播放组件
*/
private void initAudioTrack() {
bufferSizeInBytes = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
audioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mod);
}
2.4 播放
进入到play()方法后,就开始真正的播放
# play()
/**
* 开始播放
*/
private void play() {
if (audioTrack == null || fis == null) {
return;
}
byte[] data = new byte[bufferSizeInBytes];
audioTrack.play();
for (; ; ) {
if (isStopPlay) {
release();
break;
}
int readSize = -1;
try {
readSize = fis.read(data);
} catch (IOException e) {
e.printStackTrace();
}
if (readSize <= 0) {
isStopPlay = true;
continue;
}
audioTrack.write(data, 0, readSize);
}
}
类似于AudioRecord,AudioTrack中也使用for(;;)构建了一个死循环,里面也是通过isStopPlay标志位来控制调用release()方法和退出循环
和AudioRecord相反的是,是从AudioRecord中读取数据,写入文件,而AudioTrack是从文件中读取数据后,写入到AudioTrack中
在手动结束,或者文件读取结束后,释放资源
# release()
/**
* 释放资源
*/
private void release() {
if (audioTrack != null) {
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
在执行过程中,就能够听到该程序播放Pcm的声音
三、GitHub
相关的类均可在GitHub中找到