音视频开发进阶指南(第四章)-AudioTrack播放PCM

书中示例源码地址
ffmpeg编译参考链接

使用AudioTrack播放PCM

为什么只播放PCM不播放Mp3呢?因为AudioTrack是基础API,没有解码功能,而MediaPlayer是有解码功能的。所以要播放Mp3,还需要自行添加解码功能,把Mp3解码为PCM再播放。
只要做好两件事情:

  1. AudioTrack的初始化参数的含义
  2. AudioTrack的播放流程:play->write->stop

1. 初始化AudioTrack

 //获取最小缓冲区大小
 int minBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,    //采样率
         AudioFormat.CHANNEL_OUT_STEREO, //双声道
         AudioFormat.ENCODING_PCM_16BIT  //采样格式
 );
 //初始化AudioTrack对象
 AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,   //媒体类型
         SAMPLE_RATE,  //采样率
         AudioFormat.CHANNEL_IN_STEREO, //双声道
         AudioFormat.ENCODING_PCM_16BIT, //采样格式
         minBufferSize,  //缓冲区大小
         AudioTrack.MODE_STREAM  //流式加载
 );

参数详解:

  • 参数一:streamType
    Android手机上提供了多重音频管理策略(例如按一下手机侧面音量键,会出现多个音量管理,这其实就是不同音频策略的音频控制展示),当系统有多个进程需要播放音频的时候,管理策略会决定最终的呈现效果,该参数的可选值将以常量的形式定义在类AudioManager中,主要包括以下内容:
public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_
public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
public static final int STREAM_RING = AudioSystem.STREAM_RING;
public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
  • 参数二:sampleRateInHz
    采样率,即播放的音频每秒钟会有多少次采样,可选用的采样频率列表为:8000、16000、22050、24000、32000、44100、48000等,要根据播放的PCM的采样率来决定初始化AudioTrack时的具体值,否则可能导致声音变快或者变慢
  • 参数三:channelConfig
    声道数(通道数)配置,可选值以常量形式配置在类AudioFormat中,常用的是CHANNEL_IN_MONO(输入单声道),CHANNEL_IN_STEREO(输入双声道)。(因为现在大多数手机的麦克风都是伪立体声采集,为了性能考虑,建议使用单声道进行音频采集,而转变为立体声的过程可以在声音的特效处理阶段来完成)。
  • 参数四:audioFormat
    该参数是用来配置数据位宽,表示了采样精度,可选值以常量的形式定义在类AudioFormat中,分别为ENCODING_PCM_16BIT和ENCODING_PCM_8BIT,注意,前者是可以兼容安卓所有手机的。
  • 参数五:bufferSizeInBytes
    它配置的是AudioTrack内部缓冲区的大小,AudioTrack类提供了一个静态方法getMinBufferSize来帮忙开发者确定缓冲区的大小,在实际开发中,强烈建议使用该方法,而不是自己手动计算。
  • 参数六:mode
    AudioTrack提供了两种播放模式,可选的值以常量的形式定义在类AudioTrack中,分别为:
  1. MODE_STREAM 按照一定的时间间隔不间断地定入音频数据,理论上它可以应用于任何音频播放的场景
  2. MODE_STATIC 需要一次性将所有的数据都写入播放缓冲区中,简单高效,通常用于播放铃声、系统提醒的音频片段。

2. 启动播放

//先启动播放
audioTrack.play();

3. write音频数据

//分配缓冲区
byte[] buffer = new byte[minBufferSize * 3];
is = getAssets().open(pcmFilePath);
dis = new DataInputStream(is);
int readCount = 0;
while (dis.available() > 0) {
    //读取PCM
    readCount = dis.read(buffer);
    Log.d(MainActivity.class.getSimpleName(), "readCount=" + readCount);
    if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
        continue;
    }
    if (readCount != 0 && readCount != -1) {
        //写入AudioTrack
        audioTrack.write(buffer, 0, readCount);
    }
}
...
audioTrack.stop();

完整的代码Demo地址

你可能感兴趣的:(音视频开发进阶指南(第四章)-AudioTrack播放PCM)