【轉】Android的Audio系統(一)

Android的Audio系統(一)

 本章介紹Android的音頻系統內容,主要是音頻的輸入/輸出環節,不涉及編解碼的內容

1.1  Audio系統綜述

Audio系統在Android中負責音頻方面輸入/輸出層次,一般負責播放PCM聲音輸出和從外部獲取PCM聲音,以及管理聲音設備和設置。

主要分成如下幾個層次:

1media庫提供的Audio系統本地部分接口;

2AudioFlinger作爲Audio系統的中間層;

3Audio的硬件抽象層提供底層支持;

4Audio接口通過JNIJava框架提供給上層。

Audio系統的各個層次接口主要提供了兩方面功能:放音(Track)和錄音(Recorder)。

AndroidAudio系統結構如圖1-1所示。

 



1-1 Androidaudio系統結構

Android系統的代碼分佈情況如下所示:

1AudioJava部分

代碼路徑:frameworks/base/media/java/android/media

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

2AudioJNI部分

代碼路徑:frameworks/base/core/jni

生成庫libandroid_runtime.soAudioJNI是其中的一個部分。

3Audio的框架部分

頭文件路徑:frameworks/base/include/media/

源代碼路徑:frameworks/base/media/libmedia/

Audio本地框架是media庫的一部分,本部分內容被編譯成庫libmedia.so,提供Audio部分的接口(包括基於BinderIPC機制)。

4Audio Flinger

代碼路徑:frameworks/base/services/audioflinger(注:android2.3

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

5Audio的硬件抽象層接口

頭文件路徑:hardware/libhardware_legacy/include/hardware/

Audio硬件抽象層的實現在各個系統中可能是不同的,需要使用代碼去繼承相應的類並實現它們,作爲Android系統本地框架層和驅動程序接口。

 1.2  Audio系統和上層接口

Android中,Audio系統自上而下由JavaAudio類、Audio本地框架類、AudioFlingerAudio的硬件抽象層幾個部分組成。

 1.2.1  Audio系統的各個層次

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

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

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

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

在各個層次之間具有對應關係,如表1-1所示所示。

                                                    表 1-1 Android Audio各個層次的對應關係

 

Audio管理環節

Audio輸出

Audio輸入

Java

android.media.AudioSystem

android.media.AudioTrack

android.media.AudioRecorder

本地框架層

AudioSystem

AudioTrack

AudioRecorder

AudioFlinger

IAudioFlinger

IAudioTrack

IAudioRecorder

硬件抽象層

AudioHardwareInterface

AudioStreamOut

AudioStreamIn

 

 1.2.2  media庫中的Audio框架部分

AndroidAudio系統的核心框架在media庫中提供,對上面主要實現AudioSystemAudioTrackAudioRecorder三個類。

提供了IAudioFlinger類接口,在這個類中,可以獲得IAudioTrackIAudioRecorder兩個接口,分別用於聲音的播放和錄製。AudioTrackAudioRecorder分別通過調用IAudioTrackIAudioRecorder來實現。

Audio系統的頭文件在frameworks/base/include/media/目錄中,主要的頭文件如下:

AudioSystem.hmedia庫的Audio部分對上層的總管接口;

IAudioFlinger.h:需要下層實現的總管接口;

AudioTrack.h:放音部分對上接口;

IAudioTrack.h:放音部分需要下層實現的接口;

AudioRecorder.h:錄音部分對上接口;

IAudioRecorder.h:錄音部分需要下層實現的接口。

IAudioFlinger.hIAudioTrack.hIAudioRecorder.h這三個接口通過下層的繼承來實現(即AudioFlinger)。AudioFlinger.hAudioTrack.hAudioRecorder.h是對上層提供的接口,它們既供本地程序調用(例如聲音的播放器、錄製器等),也可以通過JNIJava層提供接口。

meida庫中Audio部分的結構如圖1-2所示。

 

 圖1-2 media庫中Audio部分的結構

 

從功能上看,AudioSystem負責的是Audio系統的綜合管理功能,而AudioTrackAudioRecorder分別負責音頻數據的輸出和輸入,即播放和錄製。

AudioSystem.h中主要定義了一些枚舉值和set/get等一系列接口;在Audio系統的幾個枚舉值中,audio_routes是由單獨的位來表示的,而不是由順序的枚舉值表示,因此這個值在使用過程中可以使用"的方式。例如,表示聲音可以既從耳機(EARPIECE)輸出,也從揚聲器(SPEAKER)輸出,這樣是否能實現,由下層提供支持。在這個類中,set/get等接口控制的也是相關的內容,例如Audio聲音的大小、Audio的模式、路徑等。

AudioTrackAudio輸出環節的類,其中最重要的接口是write()

AudioRecordAudio輸入環節的類,其中最重要的接口爲read()

AudioTrackAudioRecordread/write函數的參數都是內存的指針及其大小,內存中的內容一般表示的是Audio的原始數據(PCM數據)。這兩個類還涉及Auido數據格式、通道數、幀數目等參數,可以在建立時指定,也可以在建立之後使用set()函數進行設置。

libmedia庫中提供的只是一個Audio系統框架,AudioSystemAudioTrackAudioRecord分別調用下層的IAudioFlingerIAudioTrackIAudioRecord來實現。另外的一個接口是IAudioFlingerClient,它作爲向IAudioFlinger中註冊的監聽器,相當於使用回調函數獲取 IAudioFlinger運行時信息。

 

1.2.3  AudioFlinger本地代碼

AudioFlingerAudio系統的中間層,在系統中起到服務作用,它主要作爲libmedia提供的Audio部分接口的實現,其代碼路徑爲:frameworks/base/libs/audioflinger

AudioFlinger的核心文件是AudioFlinger.hAudioFlinger.cpp,提供了類AudioFlinger,這個類是一個IAudioFlinger的實現

AudioFlinger主要提供createTrack()創建音頻的輸出設備IAudioTrackopenRecord()創建音頻的輸入設備IAudioRecord。另外包含的就是一個get/set接口,用於控制。

從工作的角度看,AudioFlinger在初始化之後,首先獲得放音設備,然後爲混音器(Mixer)建立線程,接着建立放音設備線程,在線程中獲得放音設備。

AudioFlingerAudioResampler.h中定義了一個音頻重取樣器工具類,這個音頻重取樣工具包含3種質量:低等質量(LOW_QUALITY)將使用線性差值算法實現;中等質量(MED_QUALITY)將使用立方差值算法實現;高等質量(HIGH_ QUALITY)將使用FIR(有限階濾波器)實現。AudioResampler中的AudioResamplerOrder1是線性實現,AudioResamplerCubic.*文件提供立方實現方式,AudioResamplerSinc.*提供FIR實現。

AudioMixer.hAudioMixer.cpp中實現的是一個Audio系統混音器,它被AudioFlinger調用,一般用於在聲音輸出之前的處理,提供多通道處理、聲音縮放、重取樣。AudioMixer調用了AudioResampler

1.2.4  Audio系統的JNI代碼

AndroidAudio部分通過JNIJava層提供接口,在Java層可以通過JNI接口完成Audio系統的大部分操作。Audio JNI部分的代碼路徑爲:frameworks/base/core/jni

其中,主要實現的3個文件爲:android_media_AudioSystem.cppandroid_media_Audio Track.cppandroid_media_AudioRecord.cpp,它們分別對應了Android Java框架中的3個類的支持:

android.media.AudioSystem:負責Audio系統的總體控制;

android.media.AudioTrack:負責Audio系統的輸出環節;

android.media.AudioRecorder:負責Audio系統的輸入環節。

AndroidJava層中,可以對Audio系統進行控制和數據流操作,對於控制操作,和底層的處理基本一致;但是對於數據流操作,由於Java不支持指針,因此接口被封裝成了另外的形式。

Java提供native_write_bytenative_write_short接口,它們一般是通過調用AudioTrackwrite()函數來完成的,只是在Java的數據類型和C++的指針中做了一步轉換。

 

1.2.5  Audio系統的Java代碼

AndroidAudio系統的相關類在android.media 包中,Java部分的代碼路徑爲:

frameworks/base/media/java/android/media

Audio系統主要實現了以下幾個類:android.media.AudioSystemandroid.media. AudioTrackandroid.media.AudioRecorderandroid.media.AudioFormat。前面的3個類和本地代碼是對應的,AudioFormat提供了一些Audio相關類型的枚舉值。

注意:在Audio系統的Java代碼中,雖然可以通過AudioTrackAudioRecorderwrite()read()接口,在 Java層對Audio的數據流進行操作。但是,更多的時候並不需要這樣做,而是在本地代碼中直接調用接口進行數據流的輸入/輸出,而Java層只進行控制類操作,不處理數據流。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章