標籤:播放 允許 sample 資源 ref dos cal reads androi
本篇項目地址,名字是錄音和播放PCM,求star
https://github.com/979451341/Audio-and-video-learning-materials
1.AudioTrack官方說明
AudioTrack允許PCM音頻緩衝器流到音頻接收器進行回放。這是通過“推”的資料對象的訊號使用 write(byte[], int, int) and write(short[], int, int) 方法。
一個訊號可以在兩種模式下運行:靜態或流。
在流模式中,應用程式寫一個連續的資料流的訊號,採用write()方法。這些都是封閉和返回時,資料已經從java層轉移到本地層排隊等候播放。在播放音頻資料區塊時,流模式最為有用:
由於播放聲音的期間太大而不適合於記憶,因為音頻資料的特性(採樣率高)
在處理適合於記憶體的短聲音時,應該選擇靜態模式,並且需要以最小的延遲進行播放。因此,靜態模式更適合於經常播放的UI和遊戲聲音,並且可能開銷最小。
在創作中,一個聲道對象初始化其相關音頻緩衝區。這個緩衝區的大小,規定在施工過程中,確定多長時間的訊號可以跑出來的資料之前玩。
使用靜態模式的訊號,這是聲音的大小,可以發揮它的最大尺寸。
對於流模式,資料將被寫入音頻接收器,其大小小於或等於總緩衝區大小。訊號不是終點,從而允許子類,但不推薦使用。
2.AudioTrack何如建立和配置
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
sampleRateInHz:採集率,有8000、20100等,一般來說越高音質越好,但檔案體積就越大
streamType:音頻流的類型,STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING, STREAM_MUSIC, STREAM_ALARM, and STREAM_NOTIFICATION,這個參數和Android中的AudioManager有關係,涉及到手機上的音頻管理原則。
channelConfig:聲道,單聲道CHANNEL_OUT_MONO 和雙聲道 CHANNEL_OUT_STEREO
audioFormat:採樣點大小,只有ENCODING_PCM_16BIT 和 ENCODING_PCM_8BIT兩種選擇,意思是一個採集點16bit或8bit
bufferSizeInBytes:AudioTrack一次所能接收最小的聲音資源大小,通過getMinBufferSize函數擷取,
mode:有MODE_STATIC和MODE_STREAM兩種分類。
STREAM的意思是由使用者在應用程式通過write方式把資料一次一次得寫到audiotrack中,效率低。
而STATIC的意思是一開始建立的時候,就把音頻資料放到一個固定的buffer,然後直接傳給audiotrack,只有讀取一次,這種方法對於鈴聲等記憶體佔用較小,延時要求較高的聲音來說很適用。
3.AudioTrack使用
其實這個和AudioRecord一樣的道理,因為是播放,所以播放檔案存在,直接讀取檔案,通過流的形式一次一次的讀取資料,同時播放
首先建立AudioTrack
bufferSize = AudioTrack.getMinBufferSize(8000,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
// 執行個體AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
接著
track.play()
然後迴圈讀取資料,讀完了就stop(),自己中斷的話就停止迴圈
track.play(); //writeToFileHead(); while (isStart) { if (null != track&&dis.available() > 0) { int i = 0; while (dis.available() > 0 && i < buffer.length){ buffer[i] = dis.readShort(); i++; } track.write(buffer,0,buffer.length); } } track.stop();
需要注意的是資源的及時釋放
if (track != null) { if (track.getState() == AudioRecord.STATE_INITIALIZED) { track.stop(); } if (track != null) { track.release(); } } if (dis != null) { dis.close(); }
4.AudioRecord和AudioTrack的對比
兩者的功能剛好相反,一個產生pcm一個讀取pcm,而運作的過程非常相似,都對流情有獨鐘,都是一次吃不了這麼多,慢慢的吃,
mRecorder.startRecording(); //writeToFileHead(); while (isStart) { if (null != mRecorder) { bytesRecord = mRecorder.read(tempBuffer, 0, bufferSize); if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION || bytesRecord == AudioRecord.ERROR_BAD_VALUE) { continue; } if (bytesRecord != 0 && bytesRecord != -1) { //在此可以對錄製音訊資料進行二次處理 比如變聲,壓縮,降噪,增益等操作 //我們這裡直接將pcm音頻原資料寫入檔案 這裡可以直接發送至伺服器 對方採用AudioTrack進行播放原資料 dos.write(tempBuffer, 0, bytesRecord); } else { break; } } }
就連資源釋放都相似
if (mRecorder != null) { if (mRecorder.getState() == AudioRecord.STATE_INITIALIZED) { mRecorder.stop(); } if (mRecorder != null) { mRecorder.release(); } } if (dos != null) { dos.flush(); dos.close(); }
完整的代碼請看文章首部項目地址
Android 音視頻深入 二 AudioTrack播放pcm(附源碼下載)