From 9ca18763ba15ebd84e024066078b16273762a827 Mon Sep 17 00:00:00 2001 From: Awin Huang Date: Fri, 30 Sep 2022 22:13:03 +0800 Subject: [PATCH] vault backup: 2022-09-30 22:13:03 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Affected files: 03. 專注Study/Android/AudioTrack.md --- 03. 專注Study/Android/AudioTrack.md | 40 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/03. 專注Study/Android/AudioTrack.md b/03. 專注Study/Android/AudioTrack.md index 075a377..e65d9e7 100644 --- a/03. 專注Study/Android/AudioTrack.md +++ b/03. 專注Study/Android/AudioTrack.md @@ -1,7 +1,7 @@ -AudioTrack 和 MediaPlayer 都可以播放聲音,主要差別是 AudioTrack 沒有 decode 的能力,只能播放 PCM。 +`AudioTrack` 和 `MediaPlayer` 都可以播放聲音,主要差別是 `AudioTrack` 沒有 decode 的能力,只能播放 PCM。`MediaPlayer` 除了可以 demux、decode 以外,也可以播放video。 ## 底層原理 -每一個 audio stream 對應著一個 AudioTrack 類的一個實例,每個 AudioTrack 會在建立時會註冊到 AudioFlinger 中,由 AudioFlinger 把所有的 AudioTrack 進行混合(Mixer),然後輸送到 AudioHardware中 進行播放,目前 Android 同時最多可以創建32個音頻流,也就是說,Mixer 最多會同時處理32個 AudioTrack 的資料。 +每一個 audio stream 對應著一個 `AudioTrack` 類的一個實例,每個 `AudioTrack` 會在建立時會註冊到 `AudioFlinger` 中,由 `AudioFlinger` 把所有的 `AudioTrack` 進行混合(Mixer),然後輸送到 AudioHardware 中 進行播放,目前 Android 同時最多可以創建32個音頻流,也就是說,Mixer 最多會同時處理32個 `AudioTrack` 的資料。 ## 建立 AudioTrack 物件 ```kotlin @@ -20,26 +20,38 @@ audioTrack = AudioTrack( audioTrack?.play() ``` -其中需要注意的是最後一個參數,AudioTrack 有兩種模式,分別是 AudioTrack.MODE_STREAM 與 AudioTrack.MODE_STATIC。 +其中需要注意的是最後一個參數,`AudioTrack` 有兩種模式,分別是 `AudioTrack.MODE_STREAM` 與 `AudioTrack.MODE_STATIC`。 ## AudioTrack.MODE_STREAM -這個模式會邊讀邊播,必須不停的使用 `AudioTrack.write()` 來將資料寫入,若是來不及寫入會造成斷音,可以先呼叫 AudioTrack.play(),然後開始填資料。 +這個模式會邊讀邊播,必須不停的使用 `AudioTrack.write()` 來將資料寫入,若是來不及寫入會造成斷音,先呼叫 `AudioTrack.play()`,然後開始填資料,透過 `AudioTrack.write()`。 ## AudioTrack.MODE_STATIC -這個模式中,audioBufferSize 就是你要播放的聲音長度,一樣要透過 `AudioTrack.write()` 來寫入資料,寫完之後呼叫 AudioTrack.play() 開始播放。 +這個模式中,audioBufferSize 就是你要播放的聲音長度,一樣要透過 `AudioTrack.write()` 來寫入資料,寫完之後呼叫 `AudioTrack.play()` 開始播放。 ## 狀態判斷 ### `getState()` -用 `getState()` 來取得目前的狀態。 -- STATE_INITIALIZED 表示AudioTrack 已經是可以使用了。 -- STATE_UNINITIALIZED 表示AudioTrack 創建時沒有成功地初始化。 -- STATE_NO_STATIC_DATA 表示當前是使用MODE_STATIC ,但是還沒往緩衝區中寫入數據。當接收數據之後會變為STATE_INITIALIZED 狀態。 +用 `getState() : Int` 來取得目前的狀態。 +- `STATE_INITIALIZED` 表示 `AudioTrack` 已經是可以使用了。 +- `STATE_UNINITIALIZED` 表示 `AudioTrack` 創建時沒有成功地初始化。 +- `STATE_NO_STATIC_DATA` 表示當前是使用 `MODE_STATIC` ,但是還沒往緩衝區中寫入數據。當接收數據之後會變為 `STATE_INITIALIZED` 狀態。 ### `getPlayState()` -用 `getPlayState()` 來取得目前的播放狀態。 -- PLAYSTATE_STOPPED 停止 -- PLAYSTATE_PAUSED 暫停 -- PLAYSTATE_PLAYING 正在播放 +用 `getPlayState() : Int` 來取得目前的播放狀態。 +- `PLAYSTATE_STOPPED` 停止 +- `PLAYSTATE_PAUSED` 暫停 +- `PLAYSTATE_PLAYING` 正在播放 ## 暫停 -`pause()` 可以暫停播放,但是暫存區不會被清空 \ No newline at end of file +`pause()` 可以暫停播放,但是暫存區不會被清空 + +## 停止 +如果是 `AudioTrack.MODE_STREAM` mode,需要先呼叫 `pause()` 再呼叫 `flush()` 才能馬上停止,否則會等暫存區清空才停止。 +`AudioTrack.MODE_STATIC` mode 直接使用 `stop()` 即可。 + +## 釋放 +使用 `release()` 來結束資源。 + +## 參考 +- [音视频开发之旅(三)AudioTrack播放PCM音频](https://zhuanlan.zhihu.com/p/265804902) +- [深入剖析Android音頻之AudioTrack](https://blog.csdn.net/yangwen123/article/details/39989751) +- [Android音频开发之AudioTrack](https://www.jianshu.com/p/c67fd0c2b379) \ No newline at end of file