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:通知声

  • 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 encoding   Audio 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进行音频的播放,示例代码只是部分代码。在这里记录一下自己学习的过程。

你可能感兴趣的:(Audroid AudioTrack音频播放)