Android 音频基础(三)——播放(AndroidTrack)

    技术2022-07-14  70

    上一篇帖子我记录了音频采集的一些内容,既然有采集了,那么肯定是需要播放的,今天这篇帖子就简单说一下录音的播放步骤。

    录音的播放需要用到的是Android中的AudioTrack类,其实AudioTrack类和AudioRecord很相似,我们同样从AudioTrack的初始化开始说起。

    AudioTrack的初始化和AudioRecord格式几乎一直,只是参数个数不一样,我们还是先看一下AudioTrack初始化的源码,

    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode) throws IllegalArgumentException { this(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE); }

    这里接收了六个参数,分别为streamType(流类型),sampleRateInHz(采样率),channelConfig(声道),audioFormat(采样深度),bufferSizeInBytes(缓冲区大小),mode(模式)

    其中采样率,声道,采样深度,缓冲区大小都和AudioRecord对应,去除了输入音频方式,但是增加了音频类型和音频模式。

     

    这个是我初始化配置的参数,一个一个分析一下

    mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_OUT_STEREO, audioFormat, playBufsize, AudioTrack.MODE_STREAM);

    streamType

    第一个参数是steamType我这边传入的值是AudioManager.STREAM_MUSIC,我们先跳入到AudioManager文件中看下,可选的流类型有哪些

    当前Android定义了很多的种音频流的类型,抛开已弃用的和现在不再支持的,仅剩下七种类型可以选择使用,从名称和注释我们也可以大概看出来具体有哪些作用,这里就简单说明一下,方便大家理解

    STREAM_VOICE_CALL:电话语音

    STREAM_SYSTEM:系统声音

    STREAM_RING:铃声

    STREAM_MUSIC:音乐

    STREAM_ALARM:警告

    STREAM_NOTIFICATION:通知

    STREAM_DTMF:按键

    至于Android为什么要设置那么多的音频类型,我这里不展开说明了,后面再AudioFlinger里再详细说。

    sampleRateInHz

    采样率,这个和录音时的采样率保存一致就好

    channelConfig

    声道,这里有点小小的区别,录音时是收音状态AudioFormat.CHANNEL_IN_STEREO,播放时就要放音状AudioFormat.CHANNEL_OUT_STEREO

    audioFormat

    采样深度和采样率一样,和录音时保持一致

    trackBufssize

    缓冲区大小和录音时获取缓冲区大小是一样的,唯一的区别是Audiorecord时生成缓冲区大小是用AudioRecord.getMinBufferSize()而AudioTrack获取是用的AudioTrack.getMinBufferSize(),同样都是传入采样率,声道(播放时的声道设置)和采样率

    mode

    这个参数是AudioTrack较AudioRecord增加的一个参数,我们进入到AudioTrack,看到在AudioTrack中定义了两种mode方式,分别是MODE_STATIC和MODE_STREAM

    而两种方式也稍有差别

    MODE_STATIC:应用将当前音频数据一次性发给AudioTrack

    MODE_STREAM:应用将当前音频数据持续write给AudioTrack,可能会遇到阻塞,但基本适用于所有场景

     

    解释完各个参数,我们就可以开始进行播放录音操作了,播放录音也很简单,几乎和录制音频没有差别,避免占用主线程,同样的开启一共子线程进行操作,一边写入一边播放

    private void setTrack() { Log.e(TAG, "setTrack"); File file = new File(savePath); if (!file.exists()) { return; } mAudioTrack.play(); try { FileInputStream fileInputStream = new FileInputStream(file); byte[] tempBuffer = new byte[playBufsize]; while (fileInputStream.available() > 0 && isTrack) { int readCount = fileInputStream.read(tempBuffer); mAudioTrack.write(tempBuffer, 0, readCount); Log.e(TAG, "setTrack1"); } Looper.prepare(); Toast.makeText(RecordAndTrackActivity.this, "播放结束", Toast.LENGTH_SHORT).show(); Log.e(TAG, "setTrack2"); Looper.loop(); mAudioTrack.stop(); mAudioTrack.release(); mAudioTrack = null; isTrack = false; } catch (Exception e) { Log.e(TAG, e.toString()); } }

    到此,简单的录制和播放音频就告一段落了,但是这些都是最最基本的,因为我也是初学者,很多东西都没有涉及到,慢慢涉及吧,坚持出一个系列。

     

     

     

     

    Processed: 0.010, SQL: 9