前一篇講瞭如何錄製wav音頻文件,本篇就來講講如何播放wav文件,這裡就是使用AudioTrack來播放音頻,確切的說是播放pcm格式數據,使用AudioTrack播放也沒什麼難度,主要就是將數據寫入到AudioTrack中就可以了,先貼代碼 播放的方法,是傳入文件路徑,AudioRecordMan ...
前一篇講瞭如何錄製wav音頻文件,本篇就來講講如何播放wav文件,這裡就是使用AudioTrack來播放音頻,確切的說是播放pcm格式數據,使用AudioTrack播放也沒什麼難度,主要就是將數據寫入到AudioTrack中就可以了,先貼代碼
package cn.sskbskdrin.record.audio; import android.media.AudioManager; import android.media.AudioTrack; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; /** * @author sskbskdrin * @date 2019/April/3 */ public class AudioTrackManager { private AudioTrack audioTrack; private boolean playing = false; public AudioParams playWav(String filepath, AudioRecordManager.RecordCallback callback) { RandomAccessFile file = null; AudioParams params = null; try { file = new RandomAccessFile(filepath, "r"); params = readWavHeader(file); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (params == null) { return null; } int simpleRate = params.simpleRate; int channelConfig = params.getOutChannelConfig(); int audioFormat = params.getEncodingFormat(); int minBufSize = AudioTrack.getMinBufferSize(simpleRate, channelConfig, audioFormat); audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, simpleRate, channelConfig, audioFormat, minBufSize, AudioTrack.MODE_STREAM); final RandomAccessFile finalFile = file; new Thread(() -> { playing = true; audioTrack.play(); byte[] buffer = new byte[minBufSize]; try { finalFile.seek(44); while (playing) { int read = finalFile.read(buffer); if (read > 0) { audioTrack.write(buffer, 0, read); } else { finalFile.close(); playing = false; audioTrack.stop(); audioTrack.release(); } if (callback != null) { callback.onRecord(buffer, read); } } } catch (IOException e) { e.printStackTrace(); } }).start(); return params; } public static AudioParams readWavHeader(RandomAccessFile file) throws IOException { file.seek(22); byte channelCount = file.readByte(); file.seek(24); int sampleRate = file.readByte() & 0xff; sampleRate |= (file.readByte() & 0xff) << 8; sampleRate |= (file.readByte() & 0xff) << 16; sampleRate |= (file.readByte() & 0xff) << 24; file.seek(34); byte bits = file.readByte(); return new AudioParams(sampleRate, channelCount, bits); } }
播放的方法,是傳入文件路徑,AudioRecordManager.RecordCallback可以為空。先是通過readWavHeader()方法讀取wav文件的文件頭信息,返回AudioParams,這個類是我前一篇文章有列出來,可以得到一些需要的數據。
關於讀數據頭部信息,可以參考這裡,讀取重要數據。
AudioTrack.getMinBufferSize(simpleRate, channelConfig, audioFormat)可以獲取最小緩存大小。
AudioTrack的構造方法中,第一個參數為播放流的類型,有下麵幾種
AudioManager.STREAM_MUSIC //音樂
AudioManager.STREAM_VOICE_CALL //電話
AudioManager.STREAM_RING //鈴聲
AudioManager.STREAM_ALARM //鬧鐘
AudioManager.STREAM_NOTIFICATION //通知
最後了個參數是流寫入的方式,有兩種
AudioTrack.MODE_STREAM // 流寫入
AudioTrack.MODE_STATIC //靜態寫入
AudioTrack.MODE_STREAM看名字大概就能知道是流的方式寫入,邊寫邊播。
AudioTrack.MODE_STATIC就是一次寫完,然後播放,這種方式更適合比較短的聲音播放,比如通知聲音
開始播放時,先調用AudioTrack.play(),然後從wav文件的數據塊開始讀,即第44個位元組開始,讀完調用audioTrack.write寫入pcm數據。當讀不到數據時,停止AudioTrack,釋放資源即可。
通過RandomAccessFile方式讀取文件,可以記錄讀取的位置,並通過seek方法跳轉到指定位置,可實現播放、暫停、繼續播放的功能。