Android系統Audio框架介紹

音頻基礎知識

聲音有哪些重要屬性呢?

  1. 響度(Loudness)

響度就是人類可以感知到的各種聲音的大小,也就是音量。響度與聲波的振幅有直接關係。

  1. 音調(Pitch)

音調與聲音的頻率有關係,當聲音的頻率越大時,人耳所感知到的音調就越高,否則就越低。

  1. 音色(Quality)

同一種樂器,使用不同的材質來製作,所表現出來的音色效果是不一樣的,這是由物體本身的結構特性所決定的。

如何將各種媒體源數字化呢?

音頻採樣

將聲波波形信號通過ADC轉換成計算機支持的二進制的過程叫做音頻採樣(Audio Sampling)。採樣(Sampling)的核心是把連續的模擬信號轉換成離散的數字信號。

  1. 樣本(Sample)

這是我們進行採樣的初始資料,比如一段連續的聲音波形。

  1. 採樣器(Sampler)

採樣器是將樣本轉換成終態信號的關鍵。它可以是一個子系統,也可以指一個操作過程,甚至是一個算法,取決於不同的信號處理場景。理想的採樣器要求儘可能不產生信號失真。

  1. 量化(Quantization)

採樣後的值還需要通過量化,也就是將連續值近似爲某個範圍內有限多個離散值的處理過程。因爲原始數據是模擬的連續信號,而數字信號則是離散的,它的表達範圍是有限的,所以量化是必不可少的一個步驟。

  1. 編碼(Coding)

計算機的世界裏,所有數值都是用二進制表示的,因而我們還需要把量化值進行二進制編碼。這一步通常與量化同時進行。

 

奈奎斯特採樣理論

“當對被採樣的模擬信號進行還原時,其最高頻率只有採樣頻率的一半”。

換句話說,如果我們要完整重構原始的模擬信號,則採樣頻率就必須是它的兩倍以上。比如人的聲音範圍是2~ 20kHZ,那麼選擇的採樣頻率就應該在40kHZ左右,數值太小則聲音將產生失真現象,而數值太大也無法明顯提升人耳所能感知的音質。

錄製過程

  1. 音頻採集設備(比如Microphone)捕獲聲音信息。
  2. 模擬信號通過模數轉換器(ADC)處理成計算機能接受的二進制數據。
  3. 根據需求進行必要的渲染處理,比如音效調整、過濾等等。
  4. 處理後的音頻數據理論上已經可以存儲到計算機設備中了,比如硬盤、USB設備等等。不過由於這時的音頻數據體積相對龐大,不利於保存和傳輸,通常還會對其進行壓縮處理。比如我們常見的mp3音樂,實際上就是對原始數據採用相應的壓縮算法後得到的。壓縮過程根據採樣率、位深等因素的不同,最終得到的音頻文件可能會有一定程度的失真,另外,音視頻的編解碼既可以由純軟件完成,也同樣可以藉助於專門的硬件芯片來完成。

回放過程

  1. 從存儲設備中取出相關文件,並根據錄製過程採用的編碼方式進行相應的解碼。
  2. 音頻系統爲這一播放實例選定最終匹配的音頻回放設備。
  3. 解碼後的數據經過音頻系統設計的路徑傳輸。
  4. 音頻數據信號通過數模轉換器(DAC)變換成模擬信號。
  5. 模擬信號經過回放設備,還原出原始聲音。

Audio框架

  1. APP

廠商根據特定需求自己寫的一個音樂播放器軟件等等。

  1. Framework

Android也提供了另兩個相似功能的類,即AudioTrack和AudioRecorder,MediaPlayerService內部的實現就是通過它們來完成的,只不過MediaPlayer/MediaRecorder提供了更強大的控制功能,相比前者也更易於使用。除此以外,Android系統還爲我們控制音頻系統提供了AudioManager、AudioService及AudioSystem類。這些都是framework爲便利上層應用開發所設計的。

  1. Libraries

framework只是嚮應用程序提供訪問Android庫的橋樑,具體功能實現放在庫中完成。比如上面的AudioTrackAudioRecorderMediaPlayerMediaRecorder等等在庫中都能找到相對應的類。

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系統的策略控制中心,掌管系統中聲音設備的選擇和切換、音量控制等。

 

Audio 系統代碼:

(1)Audio 的Java 部分

frameworks/base/media/java/android/media

與Audio 相關的Java包是android.media,主要包含AudioManager和Audio 系統的幾個類。

(2)Audio 的JNI 部分

frameworks/base/core/jni

生成庫libandroid_runtime.so,Audio 的JNI是其中的一個部分。

(3)Audio 的框架部分

frameworks/base/include/media/

frameworks/base/media/libmedia/

這部分內容被編譯成庫libmedia.so,實現Audio系統的核心框架,同時提供了IAudioFlinger 類接口。在這個類中,可以獲得IAudioTrack 和IAudioRecorder 兩個接口,分別用於聲音的播放和錄製。AudioTrack 和AudioRecorder 分別調用IAudioTrack 和IAudioRecorder 來實現。IAudioFlinger.h、IAudioTrack.h 和IAudioRecorder.h 這三個接口通過下層來實現。AudioSystem.h、AudioTrack.h 和AudioRecorder.h 是對上層提供的接口,它們既供本地程序調用,也可以通過JNI 向Java 層提供接口。從功能上看,AudioSystem 負責的是Audio 系統的綜合管理功能,而AudioTrack 和AudioRecorder 分別負責音頻數據的輸出和輸入,即播放和錄製。另外一個接口是IAudioFlingerClient,它作爲向IAudioFlinger中註冊的監聽器,相當於使用回調函數獲取IAudioFlinger運行時信息。

(4)Audio Flinger

frameworks/base/libs/audioflinger

這部分內容被編譯成庫libaudioflinger.so,它是Audio系統的本地服務部分。

(5)Audio 的硬件抽象層接口

hardware/libhardware_legacy/include/hardware/

1、Audio使用JNI和Java對上層提供接口,JNI部分通過調用libmedia庫提供的接口來實現。

2、 Audio 本地框架類是libmedia.so的一個部分,這些Audio框架類對上層提供接口,由下層的本地代碼去實現。

3、AudioFlinger繼承libmeida中的接口,提供實現庫libaudiofilnger.so。這部分內容沒有自己的對外頭文件,上層調用的只是libmedia本部分的接口,但實際調用的內容是libaudioflinger.so。

4、Audio的硬件抽象層提供到硬件的接口,供AudioFlinger調用。Audio的硬件抽象層實際上是各個平臺開發過程中需要主要關注和獨立完成的部分。

在Android的Audio系統中,無論上層還是下層,都使用一個管理類和輸出輸入兩個類來表示整個Audio系統,輸出輸入兩個類負責數據通道。在各個層次之間具有對應關係:

在libhardware_legacy中定義的音頻相關的硬件抽象層數據結構legacy_audio_device、legacy_stream_out、legacy_stream_in如下:

音頻設備描述符:

  1. struct legacy_audio_device {  
  2.     struct audio_hw_device device;  
  3.     struct AudioHardwareInterface *hwif;  
  4. };  

音頻輸出描述符:

  1. struct legacy_stream_out {  
  2.     struct audio_stream_out stream;  
  3.     AudioStreamOut *legacy_out;  
  4. };  

音頻輸入描述符:

  1. struct legacy_stream_in {  
  2.     struct audio_stream_in stream;  
  3.     AudioStreamIn *legacy_in;  
  4. };  

通過上表比較可以看出,audio_hw_device和AudioHardwareInterface、audio_stream_out和AudioStreamOut、audio_stream_in和AudioStreamIn定義的接口基本一致,這是爲了兼容Android先前版本。

AudioHardwareInterface.cpp負責實現基礎類和管理,而AudioHardwareGeneric.cpp、AudioHardwareStub.cpp、AudioDumpInterface.cpp和A2dpAudioInterface.cpp各自代表一種Auido硬件抽象層的實現。

  1. AudioHardwareGeneric.cpp:實現基於特定驅動的通用Audio硬件抽象層,這是一個真正能夠使用的Audio硬件抽象層,但是它需要Android的一種特殊的聲音驅動程序的支持。
  2. AudioHardwareStub.cpp:實現Audio硬件抽象層的一個樁,這個實現不操作實際的硬件和文件,它所進行的是空操作。
  3.  AudioDumpInterface.cpp:實現輸出到文件的Audio硬件抽象層,支持Audio的輸出功能,不支持輸入功能。
  4. A2dpAudioInterface.cpp:實現藍牙音頻的Audio硬件抽象層。


轉自:http://blog.csdn.net/yangwen123/article/details/39502689



發佈了5 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章