Android系統Audio架構介紹
音頻基礎知識
聲音有哪些重要屬性呢?
響度(Loudness)
響度就是人類可以感知到的各種聲音的大小,也就是音量。響度與聲波的振幅有直接關係。
音調(Pitch)
音調與聲音的頻率有關係,當聲音的頻率越大時,人耳所感知到的音調就越高,否則就越低。
音色(Quality)
同一種樂器,使用不同的材質來製作,所表現出來的音色效果是不一樣的,這是由物體本身的結構特性所決定的。
如何將各種媒體源數字化呢?
音頻採樣
將聲波波形訊號通過ADC轉換成電腦支援的二進位的過程叫做音頻採樣(Audio Sampling)。採樣(Sampling)的核心是把連續的類比訊號轉換成離散的數字訊號。
樣本(Sample)
這是我們進行採樣的初始資料,比如一段連續的聲音波形。
採樣器(Sampler)
採樣器是將樣本轉換成終態訊號的關鍵。它可以是一個子系統,也可以指一個操作過程,甚至是一個演算法,取決於不同的訊號處理情境。理想的採樣器要求儘可能不產生訊號失真。
量化(Quantization)
採樣後的值還需要通過量化,也就是將連續值近似為某個範圍內有限多個離散值的處理過程。因為未經處理資料是類比的連續訊號,而數字訊號則是離散的,它的表達範圍是有限的,所以量化是必不可少的一個步驟。
編碼(Coding)
電腦的世界裡,所有數值都是用二進位表示的,因而我們還需要把量化值進行二進位編碼。這一步通常與量化同時進行。
奈奎斯特採樣理論
“當對被採樣的類比訊號進行還原時,其最高頻率只有採樣頻率的一半”。
換句話說,如果我們要完整重構原始的類比訊號,則採樣頻率就必須是它的兩倍以上。比如人的聲音範圍是2~ 20kHZ,那麼選擇的採樣頻率就應該在40kHZ左右,數值太小則聲音將產生失真現象,而數值太大也無法明顯提升人耳所能感知的音質。
錄製過程
音頻採集裝置(比如Microphone)捕獲聲音資訊。類比訊號通過模數轉換器(ADC)處理成電腦能接受的位元據。根據需求進行必要的渲染處理,比如音效調整、過濾等等。處理後的音頻資料理論上已經可以儲存到電腦裝置中了,比如硬碟、USB裝置等等。不過由於這時的音頻資料體積相對龐大,不利於儲存和傳輸,通常還會對其進行壓縮處理。比如我們常見的mp3音樂,實際上就是對未經處理資料採用相應的壓縮演算法後得到的。壓縮過程根據採樣率、位深等因素的不同,最終得到的音頻檔案可能會有一定程度的失真,另外,音視頻的編解碼既可以由純軟體完成,也同樣可以藉助於專門的硬體晶片來完成。回放過程
從存放裝置中取出相關檔案,並根據錄製過程採用的編碼方式進行相應的解碼。音頻系統為這一播放執行個體選定最終匹配的音頻回放裝置。解碼後的資料經過音頻系統設計的路徑傳輸。音頻資料訊號通過數模轉換器(DAC)變換成類比訊號。類比訊號經過回放裝置,還原出原始聲音。Audio架構
APP
廠商根據特定需求自己寫的一個音樂播放器軟體等等。
Framework
Android也提供了另兩個相似功能的類,即AudioTrack和AudioRecorder,MediaPlayerService內部的實現就是通過它們來完成的,只不過MediaPlayer/MediaRecorder提供了更強大的控制功能,相比前者也更便於使用。除此以外,Android系統還為我們控制音頻系統提供了AudioManager、AudioService及AudioSystem類。這些都是framework為便利上層應用開發所設計的。
Libraries
framework只是嚮應用程式提供訪問Android庫的橋樑,具體功能實現放在庫中完成。比如上面的AudioTrack、AudioRecorder、MediaPlayer和MediaRecorder等等在庫中都能找到相對應的類。
1、frameworks/av/media/libmedia【libmedia.so】
2、frameworks/av/services/audioflinger【libaudioflinger.so】
3、frameworks/av/media/libmediaplayerservice【libmediaplayerservice.so】
4. HAL
從設計上來看,硬體抽象層是AudioFlinger直接存取的對象。這說明了兩個問題,一方面AudioFlinger並不直接調用底層的驅動程式;另一方面,AudioFlinger上層模組只需要與它進行互動就可以實現音頻相關的功能了。因而我們可以認為AudioFlinger是Android音頻系統中真正的“隔離板”,無論下面如何變化,上層的實現都可以保持相容。
音頻方面的硬體抽象層主要分為兩部分,即AudioFlinger和AudioPolicyService。實際上後者並不是一個真實的裝置,只是採用虛擬設備的方式來讓廠商可以方便地定製出自己的策略。抽象層的任務是將AudioFlinger/AudioPolicyService真正地與硬體裝置關聯起來,但又必須提供靈活的結構來應對變化——特別是對於Android這個更新相當頻繁的系統。比如以前Android系統中的Audio系統依賴於ALSA-lib,但後期就變為了tinyalsa,這樣的轉變不應該對上層造成破壞。因而Audio HAL提供了統一的介面來定義它與AudioFlinger/AudioPolicyService之間的通訊方式,這就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,這些Struct資料類型內部大多隻是函數指標的定義,是一些“殼”。當AudioFlinger/AudioPolicyService初始化時,它們會去尋找系統中最匹配的實現(這些實現駐留在以audio.primary.*,audio.a2dp.*為名的各種庫中)來填充這些“殼”。根據產品的不同,音訊裝置存在很大差異,在Android的音頻架構中,這些問題都是由HAL層的audio.primary等等庫來解決的,而不需要大規模地修改上層實現。換句話說,廠商在定製時的重點就是如何提供這部分庫的高效實現了。
AudioRcorder和AudioTrack是Audio系統對外提供API類,AudioRcorder主要用於完成音頻資料的採集,而AudioTrack則是負責音頻資料的輸出。AudioFlinger管理著系統中的輸入輸出音頻流,並承擔著音頻資料的混合,通過讀寫Audio硬體實現音頻資料的輸入輸出功能;AudioPolicyService是Audio系統的策略控制中心,掌管系統中聲音裝置的選擇和切換、音量控制等。