一.音頻總體的架構:

二.Audio Policy
•
Stream
類型選擇合適的
device :
•
音頻管理策略管理音頻的輸入輸出,它
決定各種類型的聲音優先送往系統哪個輸
出設備,或使用哪個輸入設備進行采樣。
•
比如,如果有藍牙耳機或者耳機,將優
先使用他們作為輸入輸出設備。
•
創建
AudioTrack
的時候會傳入一個
Stream
類型,根據這個類型獲得
strategy,
然后根據
strategy
獲得一個
device。

•
Stream
類型選擇合適的
Strategy
類型
:
•
第一欄是流的類型,第二欄是音頻策略
•
從表中可以看出,某些流可以使用相同
的音頻策略進行輸入或者輸出。

•
Strategy
類型選擇合適的
device :
•
第一欄是
Strategy
的類型,第二欄是
device
。
•
按照一定的優先級順序,檢查哪些可用的輸入
輸出設備,然后選擇一個設備用來輸入輸出。

三.
Audio
使用
•
比如音樂播放器,錄音機
APK
進行錄音或播放。
•
播放聲音能夠用
MediaPlayer
和
AudioTrack
,
MediaRecorder
和
AudioRecord
進行錄音。
•
MediaPlayer
在
framework
層還是會創建
AudioTrack
,
把解碼后的
PCM
數流傳遞給
AudioTrack。AudioTrack
再傳遞給
AudioFlinger
進行混音,然后才傳遞給硬件播放
,
所以是
MediaPlayer
包括了
AudioTrack
。
四.
Audio播放流程
•
Android
的播放架構圖

•播放流程一般分為三個部分:
1.
AudioTrack
構造;
•Framework或者APP層通過JNI創建AudioTrack (JAVA)對象;
•調用到android_media_AudioRecord_setup(JNI),然后創建一個AudioRecord(C++);
•AudioRecord(C++)會調用getOutputForAttr,這個函數會調用到AudioPolicy,根據策略選擇輸出設備;
•AudioTrack(C++)通過binder機制調用AudioFlinger的createTrack()創建Track,同時分配共享內存。
•AudioFlinger擁有多個工作線程,每一個線程擁有多個Track。
•每一個音頻流對應着一個AudioTrack類的一個實例,每個AudioTrack會在創建時注冊到 AudioFlinger中,由AudioFlinger把所有的AudioTrack進行混合(Mixer),然后輸送到AudioHardware中進行播放。
目前Android同時最多可以創建32個音頻流,也就是說,Mixer最多會同時處理32個AudioTrack
的數據流
2.
AudioTrack
的
Start
;
•
Framework
或者
APP
層調用
AudioTrack(java)
的
play()
進行音頻播放的准備
;
•
play()
會調用
jni
的
native_start
(),
對應的函數是
android_media_AudioTrack_start();
•
android_media_AudioTrack_start
()
只是做了轉發,最后會調用
AudioTrack
(C++)
的
start();
•
AudioTrack
的
start()
進過轉發
,
最后會調用
PlaybackThread
的
start();
•
PlaybackThread
的
start()
的又會調用
addTrack_l();
•
PlaybackTread
的
addTrack_l
主要工作是添加
track
到
mActiveTracks,
並激活沉睡的
PlaybackTread
線程
。

3.
AudioTrack
的
Write
。
•
Framework
或者
APP
層調用
AudioTrack(java)
的
AudioTrack(java)
的
write()
寫入音頻數據
;
•
調用
jni
的
android_media_AudioTrack_write_byte()
,主要是獲取
java
傳下來的數據,並調用
writeToTrack()
來向共享內存寫入數據
;
•
writeToTrack
()
調用
AudioTrack(c++)
的
write()
,
AudioTrack(C++)
會使用
obtainBuffer
獲取一塊共享內存, 並寫入數據,寫完后用
releaseBuffer
釋放共享內存。
•
服務端讀取共享內存的音頻數據是在
PlaybackThread
的
threadLoop()
中進行的,調用
threadLoop_mix()
進行混音
;
•
完成混音后,調用
threadLoop_write
(),
它會調用
mOutput->stream->write()
寫入,這里會調用到
HAL
層
;
•
HAL
層的調用
tiny_alsa
的
pcm_open()
打開相應的錄音設備,再通過
pcm_write()
寫入音頻數據到
linux
系統,再到硬件。
四.Audio錄音流程
•Android的錄音架構圖

1.
AudioRecord
構造過程
:
•
Framework
或者
APP
層通過
JNI
創建
AudioRecord (JAVA)
對象
;
•
調用到
android_media_AudioRecord_setup(JNI),
然后創建一個
AudioRecord(C++);
•
AudioRecord
會通過
AudioSystem::getInputForAttr
,這個函數會調用到
AudioPolicy
,根據策略選擇輸出設備
;
•
AudioRecord
通過
binder
機制調用
AudioFlinger
的
createRecordTrack_l()
創建
RecordTrack
,同時分配共享內存
。
2.
AudioRecord
的
Start :
•
Framework
或者
APP
層調用
AudioTrack(java)
的
startRecording()
進行音頻播放的准備
;
•
startRecording()
會調用
jni
的
native_start(),
對應的函數是
android_media_AudioRecord_start();
•
android_media_AudioRecord_start()
只是做了轉發,最后會調用
AudioRecord(c++)
的
start();
•
AudioRecord
的
start
又會調用
TrackHandle(
服務端的
Track
代理
)
的
start,
最后會調用到
RecordThread
的
start();
•
RecordThread
的
start()
會激活沉睡的
RecordThread 。
3.
AudioRecord
的
Read :
•
Framework
或者
APP
層調用
AudioRecord(java)
的
AudioTrack(java)
的
read
讀取音頻數據
;
•
調用
jni
的
android_media_AudioRecord_readInByteArray
,調用
AudioTrack(c++)
的
read
讀取數據
;
•
AudioTrack(C++)
會使用
obtainBuffer
獲取一塊共享內存, 並讀取數據
;
•
服務端讀取共享內存的音頻數據是在
RecordThread
的
threadLoop()
中進行
;
•
調用
mInput->stream->read
讀取,這里會調用到
HAL
層
;
•
HAL
層的調用
tiny_alsa
的
pcm_open
打開設備,然后通過
pcm_read()
讀取相應設備數據。