本章介紹Android的音頻系統內容,主要是音頻的輸入/輸出環節,不涉及編解碼的內容。 1.1 Audio系統綜述Audio系統在Android中負責音頻方面輸入/輸出層次,一般負責播放PCM聲音輸出和從外部獲取PCM聲音,以及管理聲音設備和設置。 主要分成如下幾個層次: (1)media庫提供的Audio系統本地部分接口; (2)AudioFlinger作爲Audio系統的中間層; (3)Audio的硬件抽象層提供底層支持; (4)Audio接口通過JNI和Java框架提供給上層。 Audio系統的各個層次接口主要提供了兩方面功能:放音(Track)和錄音(Recorder)。 Android的Audio系統結構如圖1-1所示。
圖 1-1 Android的audio系統結構 Android系統的代碼分佈情況如下所示: (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/ Audio本地框架是media庫的一部分,本部分內容被編譯成庫libmedia.so,提供Audio部分的接口(包括基於Binder的IPC機制)。 (4)Audio Flinger 代碼路徑:frameworks/base/services/audioflinger(注:android2.3) 這部分內容被編譯成庫libaudioflinger.so,它是Audio系統的本地服務部分。 (5)Audio的硬件抽象層接口 頭文件路徑:hardware/libhardware_legacy/include/hardware/ Audio硬件抽象層的實現在各個系統中可能是不同的,需要使用代碼去繼承相應的類並實現它們,作爲Android系統本地框架層和驅動程序接口。 1.2 Audio系統和上層接口 在Android中,Audio系統自上而下由Java的Audio類、Audio本地框架類、AudioFlinger和Audio的硬件抽象層幾個部分組成。 1.2.1 Audio系統的各個層次 Audio本地框架類是libmedia.so的一個部分,這些Audio接口對上層提供接口,由下層的本地代碼去實現。 AudioFlinger繼承libmeida中的接口,提供實現庫libaudiofilnger.so。這部分內容沒有自己的對外頭文件,上層調用的只是libmedia本部分的接口,但實際調用的內容是libaudioflinger.so。 Audio使用JNI和Java對上層提供接口,JNI部分通過調用libmedia庫提供的接口來實現。 Audio的硬件抽象層提供到硬件的接口,供AudioFlinger調用。Audio的硬件抽象層實際上是各個平臺開發過程中需要主要關注和獨立完成的部分。 在各個層次之間具有對應關係,如表1-1所示所示。表 1-1 Android Audio各個層次的對應關係
1.2.2 media庫中的Audio框架部分 Android的Audio系統的核心框架在media庫中提供,對上面主要實現AudioSystem、AudioTrack和AudioRecorder三個類。 提供了IAudioFlinger類接口,在這個類中,可以獲得IAudioTrack和IAudioRecorder兩個接口,分別用於聲音的播放和錄製。AudioTrack和AudioRecorder分別通過調用IAudioTrack和IAudioRecorder來實現。 Audio系統的頭文件在frameworks/base/include/media/目錄中,主要的頭文件如下: AudioSystem.h:media庫的Audio部分對上層的總管接口; IAudioFlinger.h:需要下層實現的總管接口; AudioTrack.h:放音部分對上接口; IAudioTrack.h:放音部分需要下層實現的接口; AudioRecorder.h:錄音部分對上接口; IAudioRecorder.h:錄音部分需要下層實現的接口。 IAudioFlinger.h、IAudioTrack.h和IAudioRecorder.h這三個接口通過下層的繼承來實現(即AudioFlinger)。AudioFlinger.h、AudioTrack.h和AudioRecorder.h是對上層提供的接口,它們既供本地程序調用(例如聲音的播放器、錄製器等),也可以通過JNI向Java層提供接口。 meida庫中Audio部分的結構如圖1-2所示。
圖1-2 media庫中Audio部分的結構
從功能上看,AudioSystem負責的是Audio系統的綜合管理功能,而AudioTrack和AudioRecorder分別負責音頻數據的輸出和輸入,即播放和錄製。 AudioSystem.h中主要定義了一些枚舉值和set/get等一系列接口;在Audio系統的幾個枚舉值中,audio_routes是由單獨的位來表示的,而不是由順序的枚舉值表示,因此這個值在使用過程中可以使用" 或"的方式。例如,表示聲音可以既從耳機(EARPIECE)輸出,也從揚聲器(SPEAKER)輸出,這樣是否能實現,由下層提供支持。在這個類中,set/get等接口控制的也是相關的內容,例如Audio聲音的大小、Audio的模式、路徑等。 AudioTrack是Audio輸出環節的類,其中最重要的接口是write(); AudioRecord是Audio輸入環節的類,其中最重要的接口爲read() AudioTrack和AudioRecord的read/write函數的參數都是內存的指針及其大小,內存中的內容一般表示的是Audio的原始數據(PCM數據)。這兩個類還涉及Auido數據格式、通道數、幀數目等參數,可以在建立時指定,也可以在建立之後使用set()函數進行設置。 在libmedia庫中提供的只是一個Audio系統框架,AudioSystem、AudioTrack和AudioRecord分別調用下層的IAudioFlinger、IAudioTrack和IAudioRecord來實現。另外的一個接口是IAudioFlingerClient,它作爲向IAudioFlinger中註冊的監聽器,相當於使用回調函數獲取 IAudioFlinger運行時信息。
1.2.3 AudioFlinger本地代碼 AudioFlinger是Audio系統的中間層,在系統中起到服務作用,它主要作爲libmedia提供的Audio部分接口的實現,其代碼路徑爲:frameworks/base/libs/audioflinger AudioFlinger的核心文件是AudioFlinger.h和AudioFlinger.cpp,提供了類AudioFlinger,這個類是一個IAudioFlinger的實現 AudioFlinger主要提供createTrack()創建音頻的輸出設備IAudioTrack,openRecord()創建音頻的輸入設備IAudioRecord。另外包含的就是一個get/set接口,用於控制。 從工作的角度看,AudioFlinger在初始化之後,首先獲得放音設備,然後爲混音器(Mixer)建立線程,接着建立放音設備線程,在線程中獲得放音設備。 在AudioFlinger的AudioResampler.h中定義了一個音頻重取樣器工具類,這個音頻重取樣工具包含3種質量:低等質量(LOW_QUALITY)將使用線性差值算法實現;中等質量(MED_QUALITY)將使用立方差值算法實現;高等質量(HIGH_ QUALITY)將使用FIR(有限階濾波器)實現。AudioResampler中的AudioResamplerOrder1是線性實現,AudioResamplerCubic.*文件提供立方實現方式,AudioResamplerSinc.*提供FIR實現。 AudioMixer.h和AudioMixer.cpp中實現的是一個Audio系統混音器,它被AudioFlinger調用,一般用於在聲音輸出之前的處理,提供多通道處理、聲音縮放、重取樣。AudioMixer調用了AudioResampler。 1.2.4 Audio系統的JNI代碼 Android的Audio部分通過JNI向Java層提供接口,在Java層可以通過JNI接口完成Audio系統的大部分操作。Audio JNI部分的代碼路徑爲:frameworks/base/core/jni。 其中,主要實現的3個文件爲:android_media_AudioSystem.cpp、android_media_Audio Track.cpp和android_media_AudioRecord.cpp,它們分別對應了Android Java框架中的3個類的支持: android.media.AudioSystem:負責Audio系統的總體控制; android.media.AudioTrack:負責Audio系統的輸出環節; android.media.AudioRecorder:負責Audio系統的輸入環節。 在Android的Java層中,可以對Audio系統進行控制和數據流操作,對於控制操作,和底層的處理基本一致;但是對於數據流操作,由於Java不支持指針,因此接口被封裝成了另外的形式。 向Java提供native_write_byte和native_write_short接口,它們一般是通過調用AudioTrack的write()函數來完成的,只是在Java的數據類型和C++的指針中做了一步轉換。
1.2.5 Audio系統的Java代碼 Android的Audio系統的相關類在android.media 包中,Java部分的代碼路徑爲: frameworks/base/media/java/android/media Audio系統主要實現了以下幾個類:android.media.AudioSystem、android.media. AudioTrack、android.media.AudioRecorder、android.media.AudioFormat。前面的3個類和本地代碼是對應的,AudioFormat提供了一些Audio相關類型的枚舉值。 注意:在Audio系統的Java代碼中,雖然可以通過AudioTrack和AudioRecorder的write()和read()接口,在 Java層對Audio的數據流進行操作。但是,更多的時候並不需要這樣做,而是在本地代碼中直接調用接口進行數據流的輸入/輸出,而Java層只進行控制類操作,不處理數據流。 |