Audroid|Audroid AudioTrack音频播放

1、简介 Android 中用于播放音频的API有三种,分别是:MediaPlayer,SoundPool,AudioTrack。MediaPlayer适合长时间在后台播放媒体音乐,包括本地音乐或在线流媒体资源。SoundPool适合播放比较短的音频片段,比如游戏音效、铃声片段等,它可以同时播放多个音频。AudioTrack更接近底层,它提供了强大的音频控制能力,支持低延迟播放,适合流媒体播放等。AudioTrack播放的音频必须是解码后的PCM数据。
2、MediaPlayer的创建

public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)

  • streamType 这个参数代表当前应用使用哪种音频管理策略。当系统有多个进程需要播放音频时,这个策略会决定最终展示的效果。该参数值在AudioManager类中,主要包括:
    STREAM_VOCIE_CALL:电话声音
    STREAM_SYSTEM:系统声音
    STREAM_RING:铃声
    STREAM_MUSCI:音乐声
    STREAM_ALARM:警告声
    STREAM_NOTIFICATION:通知声
  • 【Audroid|Audroid AudioTrack音频播放】sampleRateInHz 该参数表示采样率。44100Hz是科学家给出的最佳采样频率,并且在Android中也是多所有Android设备兼容最好的采样频率。
  • channelConfig 通道数,也就是声道数。常量定义在AudioFormat类中,CHANNEL_OUT_MONO表示单声道,CHANNEL_OUT_STEREO表示双声道。
  • audioFormat 指音频采样精度,或者说是音频位宽。常量定义在AudioFormat类中,可选AudioFormat.ENCODING_PCM_16BIT或AudioFormat.ENCODING_PCM_8BIT等。16位将占用更多的空间,但采集的音频也更加接近原声。AudioFormat.ENCODING_PCM_16BIT目前兼容性更好。
  • bufferSizeInBytes 这个参数是AudioRecoder内部音频缓冲区的大小。该缓冲区的大小不能小于一个“音频帧”的大小。音频帧的计算方法为:int size = 采样率 x 位宽 x 采样时间 x 声道数。
    采样时间是指采集一帧数据所用的时间,它的取值一般在2.5ms~120ms 之间,根据手机厂商等因素决定。每一帧采样的时间越短,产生的延时就越小,但是碎片化的数据也就越多。
    AudioRecoder类中提供了一个静态方法int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)来获取缓冲区大小。音频缓冲区大小必须是“音频帧”大小的2~N倍。这里强烈建议使用该方法去计算缓冲区大小,而不是手动去计算。
  • mode AudioTrack提供两种播放方式,一种是static,另外一种是stream。static方式需要一次性的将所有的音频数据全部写入音频缓冲区,这样简单高效,适用于铃声、系统提示音等比较短的音频片段。stream方式是按一定的时间间隔将音频数据不断的写入到缓存区,比如音频通话,视频直播的声音播放,理论上适用于所有的音频播放场景。
3、音频播放 AudioTrack创建完成后,就可以在一个新的线程中,调用以下方法将数据写入到缓存区进行播放
AudioTrack.write(byte[] audioData, int offsetInBytes, int sizeInBytes)
AudioTrack.write方法需要在子线程中调用。
4、代码示例
private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC; private static final int DEFAULT_PLAY_MODE = AudioTrack.MODE_STREAM; private static final int DEFAULT_CHANNEL = AudioFormat.CHANNEL_OUT_MONO; /** * 缓存的音频大小 */ private int mBufferSize; private boolean isPlaying = false; private AudioTrack audioTrack; /** * @param sampleRate sample rate、采样率 * @param encodingAudio data format、音频格式 */ AudioPlayer(int sampleRate, int encoding) { this.mSampleRate = sampleRate; this.mBufferSize = AudioTrack.getMinBufferSize(sampleRate, DEFAULT_CHANNEL, encoding); if (mBufferSize == AudioTrack.ERROR_BAD_VALUE) { Log.e(TAG, "获取BufferSize失败"); return; }this.audioTrack = new AudioTrack(DEFAULT_STREAM_TYPE, sampleRate, DEFAULT_CHANNEL, encoding, mBufferSize, DEFAULT_PLAY_MODE); isPlaying = false; }/** * 播放音频 * * @param audioData */ public void startPlay(final byte[] audioData) { if (isPlaying) { return; } if (audioData.length < mBufferSize) { Log.e(TAG, "startPlay: 录音太短"); return; }new Thread(new Runnable() { @Override public void run() { if (audioTrack.write(audioData, 0, audioData.length) != audioData.length) { Log.e(TAG, "startPlay: 播放出错"); } audioTrack.play(); } }).start(); }/** * 停止播放 */ public void stopPlay() { if (!isPlaying) { return; } if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { audioTrack.stop(); } audioTrack.release(); isPlaying = false; }

这里只是介绍了使用AudioTrack进行音频的播放,示例代码只是部分代码。在这里记录一下自己学习的过程。

    推荐阅读