Android音頻系統之音頻架構

來源:互聯網
上載者:User

1.1 音頻架構轉載請註明,From LXS, http://blog.csdn.net/uiop78uiop78/article/details/8796492Android的音頻系統在很長一段時間內都是外界詬病的焦點。的確,早期的Android系統在音頻處理上相比於IOS有一定的差距,這也是很多專業的音樂播放軟體開發商沒有推出Android平台產品的一個重要原因。但這並不代表它的音頻架構一無是處,相反,基於Linux系統的Android平台有很多值得我們學習的地方。1.1.1 Linux下的音頻架構在電腦發展的早期,電腦的聲音處理裝置是由一個非常簡易的loudspeaker外加發聲器(Tone Generator)構成的,功能相對局限。後來人們想到了以plug-in的形式來擴充音訊裝置,“Sound blaster”就是其中很有名的一個。這種早期的音效卡以外掛程式方式串連到電腦主板上,並提供了更多複雜的音訊裝置。可想而知,獨立的硬體設計也意味著成本的增加,於是隨著技術的發展,便又出現了板載音效卡,也就是我們俗稱的“整合音效卡”。板載音效卡又分為“軟音效卡”和“硬音效卡”。如果音效卡本身沒有主處理晶片,而只有解碼晶片,需要通過CPU運算來執行處理工作,那麼就是“軟音效卡”,反之就是“硬音效卡”。通常面向低端市場的電腦都會包含一個整合的音效卡裝置以降低成本。一個典型的音效卡通常包含三個部分:·          Connectors用於音效卡與外放裝置,如擴音器、耳機的串連,又被稱為“jacks”·          Audio Circuits音效卡的主要實現體,它負責訊號的放大、混音、以及類比數字轉換等操作·          Interface串連音效卡與電腦匯流排的單元,比如PCI匯流排我們可以通過“cat/proc/asound/cards”命令來查看電腦中安裝的音效卡裝置,如下例子所示:目前市面上音效卡的種類眾多,既有複雜的高效能的,也有低端的簡易的,那麼對於一個作業系統來說,它如何管理這些音訊裝置,並向上層應用提供統一的介面呢?Android嚴格來講只是一個Linux系統,它依賴於核心提供的各種驅動支援,包括音頻驅動。因此我們有必要先花點時間來學習下Linux平台下的兩種主要的音頻驅動架構: ·        OSS (Open Sound System)早期Linux版本採用的是OSS架構,它也是Unix及類Unix系統中廣泛使用的一種音頻體系。OSS既可以指OSS介面本身,也可以用來表示介面的實現。OSS的作者是Hannu Savolainen,就職於4Front Technologies公司。由於涉及到智慧財產權問題,OSS後期的支援與改善不是很好,這也是Linux核心最終放棄OSS的一個原因。另外,OSS在某些方面也遭到了人們的質疑,比如:對新音頻特性的支援不足;缺乏對最新核心特性的支援等等。當然,OSS做為Unix下統一音頻處理操作的早期實現,本身算是比較成功的。它符合“一切都是檔案”的設計理念,而且做為一種體系架構,其更多地只是規定了應用程式與作業系統音頻驅動間的互動,因而各個系統可以根據實際的需求進行定製開發。總的來說,OSS使用了如下表所示的裝置節點:表格 13‑1 OSS採用的裝置節點裝置節點說明/dev/dsp向此檔案寫資料à輸出到外放Speaker向此檔案讀資料à從Microphone進行錄音/dev/mixer混音器,用於對音訊裝置進行相關設定,比如音量大小/dev/midi00第一個MIDI連接埠,還有midi01,midi02等等/dev/sequencer用於訪問合成器(synthesizer),常用於遊戲等效果的產生  ·        ALSA(Advanced Linux Sound Architecture)ALSA是Linux社區為了取代OSS而提出的一種架構,是一個原始碼完全開放的系統(遵循GNU GPL和GNU LGPL)。ALSA在Kernel 2.5版本中被正式引入後,OSS就逐步被排除在核心之外。當然,OSS本身還是在不斷維護的,只是不再為Kernel所採用而已。ALSA相對於OSS提供了更多,也更為複雜的API介面,因而開發難度相對來講加大了一些。為此,ALSA專門提供了一個供開發人員使用的工具庫,以協助他們更好地使用ALSA的API。根據官方文檔的介紹,ALSA有如下特性:Ø  高效支援大多數類型的audio interface(不論是消費型或者是專業型的多聲道音效卡)Ø  高度模組化的聲音驅動Ø  SMP及安全執行緒(thread-safe)設計Ø  在使用者空間提供了alsa-lib來簡化應用程式的編寫Ø  與OSS API保持相容,這樣子可以保證老的OSS程式在系統中正確運行 ALSA主要由下表所示的幾個部分組成:表格 13‑2 Alsa-project PackageElementDescriptionalsa-driver核心驅動包alsa-lib使用者空間的函數庫alsa-utils包含了很多實用的小程式,比如alsactl:用於儲存裝置設定amixer:是一個命令列程式,用於聲量和其它聲音控制alsamixer:amixer的ncurses版acconnect和aseqview:製作MIDI串連,以及檢查已串連的連接埠列表aplay和arecord:兩個命令列程式,分別用於播放和錄製多種格式的音頻alsa-tools包含一系列工具程式alsa-firmware音頻韌體支援包alsa-plugins外掛程式包,比如jack,pulse,maemoalsa-oss用於相容OSS的類比包pyalsa用於編譯Python版本的alsa lib Alsa主要的檔案節點如下:Information Interface (/proc/asound)Control Interface (/dev/snd/controlCX)Mixer Interface (/dev/snd/mixerCXDX)PCM Interface (/dev/snd/pcmCXDX)Raw MIDI Interface (/dev/snd/midiCXDX)Sequencer Interface (/dev/snd/seq)Timer Interface (/dev/snd/timer) 關於ALSA的更多知識,建議大家可以自行參閱相關文檔,這對於後面理解整個Audio系統是不無裨益的。1.1.2 TinyAlsa一看“Tiny”這個詞,大家應該能猜到這是一個ALSA的縮減版本。實際上在Android系統的其它地方也可以看到類似的做法——既想用開源項目,又嫌工程太大太繁瑣,怎麼辦?那就只能瘦身了,於是很多Tiny-XXX就出現了。在早期版本中,Android系統的音頻架構主要是基於ALSA的,其上層實現可以看做是ALSA的一種“應用”。後來可能是由於ALSA所存在的一些不足,Android後期版本開始不再依賴於ALSA提供的使用者空間層的實現,因而我們在它的庫檔案夾中已經找不到alsa相關的lib了,如所示:     圖 13‑7 Android4.1與早期版本在音頻庫上的區別 而取代它的是tinyalsa相關的庫檔案,如所示: 同時我們可以看到externl目錄下多了一個“tinyalsa”檔案夾,其中包含了為數不多的幾個源碼檔案,如下所示:   表格 13‑3 Tiny-alsa工程檔案Source FileDescriptionAndroid.mkmakefilemixer.cMixer Interface實現pcm.cPCM Interface實現tinycap.cCaputer工具tinymix.cMixer工具tinyplay.cPlay工具include/tinyalsa/asoundlib.h標頭檔可見TinyAlsa與原版Alsa的差異還是相當大的,它只是部分支援了其中的兩種Interface,而像Raw MIDI、Sequencer、Timer等Interface則沒有涉及到——當然這對於一般的嵌入式裝置還是足夠了。TinyAlsa作為Alsa-lib的一個替代品,自面世已來得到的公眾評價有褒有貶,不能一概而論——對於每個廠商來說,合適自己的就是最好的。而且各廠商也可以在此基礎上擴充自己的功能,真正的把ALSA利用到極致。1.1.3 Android系統上的音頻架構 一個好的系統架構,需要儘可能地降低上層與具體硬體的耦合,這既是作業系統的設計目的,對於音頻系統也是如此。音頻系統的雛形架構可以簡單的用來表示: 圖 13‑8 音頻系統的雛形架構 在這個圖中,除去Linux本身的Audio驅動外,整個Android音頻實現都被看成了User。因而我們可以認為Audio Driver就是上層與硬體間的“隔離板”。但是如果單純採用所示的架構來設計音頻系統,對上層應用使用音頻功能是不小的負擔,顯然AndroidTeam Dev還會根據自身的實際情況來進一步細化“User”部分。細化的根據自然還是Android的幾個階層,包括應用程式層、framework層、庫層以及HAL層,如所示: 圖 13‑9 音頻架構在Android系統中的進一步細化 我們可以結合目前已有的知識,想一下每一個層次都會包含哪些模組(先不考慮藍芽音頻部分)?·        APP這是整個音頻體系的最上層,因而並不是Android系統實現的重點。比如廠商根據特定需求自己寫的一個音樂播放器,遊戲中使用到聲音,或者調節音訊一類軟體等等。 ·        Framework相信大家可以馬上想到MediaPlayer和MediaRecorder,因為這是我們在開發音頻相關產品時使用最廣泛的兩個類。實際上,Android也提供了另兩個相似功能的類,即AudioTrack和AudioRecorder,MediaPlayerService內部的實現就是通過它們來完成的,只不過MediaPlayer/MediaRecorder提供了更強大的控制功能,相比前者也更便於使用。我們後面還會有詳細介紹。除此以外,Android系統還為我們控制音頻系統提供了AudioManager、AudioService及AudioSystem類。這些都是framework為便利上層應用開發所設計的。 ·        Libraries我們知道,framework層的很多類,實際上只是應用程式使用Android庫檔案的“中介”而已。因為上層應用採用java語言編寫,它們需要最直接的java介面的支援,這就是framework層存在的意義之一。而作為“中介”,它們並不會真正去實現具體的功能,或者只實現其中的一部分功能,而把主要重心放在庫中來完成。比如上面的AudioTrack、AudioRecorder、MediaPlayer和MediaRecorder等等在庫中都能找到相對應的類。這一部分代碼集中放置在工程的frameworks/av/media/libmedia中,多數是C++語言編寫的。除了上面的類庫實現外,音頻系統還需要一個“核心中控”,或者用Android中通用的實現來講,需要一個系統服務(比如ServiceManager、LocationManagerService、ActivityManagerService等等),這就是AudioFlinger和AudioPolicyService。它們的代碼放置在frameworks/av/services/audioflinger,產生的最主要的庫叫做libaudioflinger。音頻體系中另一個重要的系統服務是MediaPlayerService,它的位置在frameworks/av/media/libmediaplayerservice。因為涉及到的庫和相關類是非常多的,建議大家在理解的時候分為兩條線索。其一,以庫為線索。比如AudioPolicyService和AudioFlinger都是在libaudioflinger庫中;而AudioTrack、AudioRecorder等一系列實現則在libmedia庫中。其二,以進程為線索。庫並不代表一個進程,進程則依賴於庫來運行。雖然有的類是在同一個庫中實現的,但並不代表它們會在同一個進程中被調用。比如AudioFlinger和AudioPolicyService都駐留於名為mediaserver的系統進程中;而AudioTrack/AudioRecorder和MediaPlayer/MediaRecorder一樣實際上只是應用進程的一部分,它們通過binder服務來與其它系統進程通訊。在分析源碼的過程中,一定要緊抓這兩條線索,才不至於覺得混亂。 ·        HAL從設計上來看,硬體抽象層是AudioFlinger直接存取的對象。這說明了兩個問題,一方面AudioFlinger並不直接調用底層的驅動程式;另一方面,AudioFlinger上層(包括和它同一層的MediaPlayerService)的模組只需要與它進行互動就可以實現音頻相關的功能了。因而我們可以認為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等等庫來解決的,而不需要大規模地修改上層實現。換句話說,廠商在定製時的重點就是如何提供這部分庫的高效實現了。  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.