Files
Obsidian-Main/03. 專注Study/Android/AudioTrack.md
Awin Huang 3f275aef06 vault backup: 2022-10-03 14:34:16
Affected files:
03. 專注Study/Android/AudioTrack.md
2022-10-03 14:34:17 +08:00

58 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
`AudioTrack``MediaPlayer` 都可以播放聲音,主要差別是 `AudioTrack` 沒有 decode 的能力,只能播放 PCM。`MediaPlayer` 除了可以 demux、decode 以外也可以播放video。
## 底層原理
每一個 audio stream 對應著一個 `AudioTrack` 類的一個實例,每個 `AudioTrack` 會在建立時會註冊到 `AudioFlinger` 中,由 `AudioFlinger` 把所有的 `AudioTrack` 進行混合Mixer然後輸送到 AudioHardware 中 進行播放,目前 Android 同時最多可以創建32個音頻流也就是說Mixer 最多會同時處理32個 `AudioTrack` 的資料。
## 建立 AudioTrack 物件
```kotlin
const val SAMPLE_RATE = 44100
const val CHANNEL_OUT_FORMAT = AudioFormat.CHANNEL_OUT_STEREO
const val AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT
var audioBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_OUT_FORMAT, AUDIO_FORMAT)
audioTrack = AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
CHANNEL_OUT_FORMAT,
AUDIO_FORMAT,
audioBufferSize,
AudioTrack.MODE_STREAM)
audioTrack?.play()
```
其中需要注意的是最後一個參數,`AudioTrack` 有兩種模式,分別是 `AudioTrack.MODE_STREAM``AudioTrack.MODE_STATIC`
## AudioTrack.MODE_STREAM
這個模式會邊讀邊播,必須不停的使用 `AudioTrack.write()` 來將資料寫入,若是來不及寫入會造成斷音,先呼叫 `AudioTrack.play()`,然後開始填資料,透過 `AudioTrack.write()`
## AudioTrack.MODE_STATIC
這個模式中audioBufferSize 就是你要播放的聲音長度,一樣要透過 `AudioTrack.write()` 來寫入資料,寫完之後呼叫 `AudioTrack.play()` 開始播放。
## 狀態判斷
### `getState()`
`getState() : Int` 來取得目前的狀態。
- `STATE_INITIALIZED` 表示 `AudioTrack` 已經是可以使用了。
- `STATE_UNINITIALIZED` 表示 `AudioTrack` 創建時沒有成功地初始化。
- `STATE_NO_STATIC_DATA` 表示當前是使用 `MODE_STATIC` ,但是還沒往緩衝區中寫入數據。當接收數據之後會變為 `STATE_INITIALIZED` 狀態。
### `getPlayState()`
`getPlayState() : Int` 來取得目前的播放狀態。
- `PLAYSTATE_STOPPED` 停止
- `PLAYSTATE_PAUSED` 暫停
- `PLAYSTATE_PLAYING` 正在播放
## 暫停
`pause()` 可以暫停播放,但是暫存區不會被清空
## 停止
如果是 `AudioTrack.MODE_STREAM` mode需要先呼叫 `pause()` 再呼叫 `flush()` 才能馬上停止,否則會等暫存區清空才停止。
`AudioTrack.MODE_STATIC` mode 直接使用 `stop()` 即可。
## 釋放
使用 `release()` 來結束資源。
## 參考
- [AudioTrack](https://developer.android.com/reference/android/media/AudioTrack)
- [音视频开发之旅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)