基于Android的音樂播放器的設(shè)計(jì)與實(shí)現(xiàn)

本文基于Android音頻API提供的四個(gè)層面的音頻API夜矗,說說Android系統(tǒng)的音頻架構(gòu)泛范。

下面先上這張經(jīng)典的Android系統(tǒng)架構(gòu)圖

從圖上看Andorid整個(gè)系統(tǒng)層面從下到上分以下四層:

  1. Linux Kernel
  2. 硬件適配層
  3. Framework層(可分為Java層與C++層)
  4. APP層

我們上面介紹的四個(gè)層面的音頻API實(shí)現(xiàn)均在Framework層,其他各層音頻相關(guān)有哪些功能紊撕?當(dāng)我們調(diào)用某一API時(shí)最終是怎么驅(qū)動(dòng)硬件工作的呢罢荡?下面我們先看看系統(tǒng)各層音頻相關(guān)模塊及功能。

1. 各層音頻模塊

1.1 Java層

Java層提供了 android.media API 與音頻硬件進(jìn)行交互对扶。在內(nèi)部柠傍,此代碼會(huì)調(diào)用相應(yīng)的 JNI 類,以訪問與音頻硬件交互的原生代碼辩稽。

  • 源代碼目錄:frameworks/base/media/java/android/media/

  • AudioManager:音頻管理器,包括音量管理从媚、AudioFocus管理逞泄、音頻設(shè)備管理、模式管理拜效;

  • 錄音:AudioRecord喷众、MediaRecorder;

  • 播放:AudioTrack紧憾、MedaiPlayer到千、SoundPool、ToneGenerator;

  • 編解碼:MediaCodec赴穗,音視頻數(shù)據(jù) 編解碼接口憔四。

1.2 JNI層

與 android.media 關(guān)聯(lián)的 JNI 代碼可調(diào)用較低級(jí)別的原生代碼,以訪問音頻硬件般眉。JNI 位于 frameworks/base/core/jni/ 和 frameworks/base/media/jni 中了赵。

在這里可以調(diào)用我們上篇文章介紹的AAudio和OpenSLES接口。

1.3 Native framework 原生框架層

不管是Java層還是JNI層都只是對(duì)外提供的接口甸赃,真正的實(shí)現(xiàn)在原生框架層柿汛。原生框架可提供相當(dāng)于 android.media 軟件包的原生軟件包,從而調(diào)用 Binder IPC 代理以訪問媒體服務(wù)器的特定于音頻的服務(wù)埠对。原生框架代碼位于 frameworks/av/media/libmediaframeworks/av/media/libaudioclient中(不同版本络断,位置有所改變)裁替。

1.4 Binder IPC

Binder IPC 代理用于促進(jìn)跨越進(jìn)程邊界的通信。代理位于 frameworks/av/media/libmediaframeworks/av/media/libaudioclient 中貌笨,并以字母“I”開頭弱判。

1.5 Audio Server

Audio系統(tǒng)在Android中負(fù)責(zé)音頻方面的數(shù)據(jù)流傳輸和控制功能,也負(fù)責(zé)音頻設(shè)備的管理躁绸。這個(gè)部分作為Android的Audio系統(tǒng)的輸入/輸出層次裕循,一般負(fù)責(zé)播放PCM聲音輸出和從外部獲取PCM聲音,以及管理聲音設(shè)備和設(shè)置(注意:解碼功能不在這里實(shí)現(xiàn)净刮,在android系統(tǒng)里音頻視頻的解碼是opencore或stagefright完成的剥哑,在解碼之后才調(diào)用音頻系統(tǒng)的接口,創(chuàng)建音頻流并播放)淹父。Audio服務(wù)在Android N(7.0)之前存在于mediaserver中株婴,Android N開始以audioserver形式存在,這些音頻服務(wù)是與HAL 實(shí)現(xiàn)進(jìn)行交互的實(shí)際代碼暑认。媒體服務(wù)器位于 frameworks/av/services/audioflingerframeworks/av/services/audiopolicy中困介。

Audio服務(wù)包含AudioFlinger 和AudioPolicyService:

  • AudioFlinger:主要負(fù)責(zé)音頻流設(shè)備的管理以及音頻流數(shù)據(jù)的處理傳輸,?量計(jì)算蘸际,重采樣座哩、混?、?效等粮彤。

  • AudioPolicyService:主要負(fù)責(zé)?頻策略相關(guān)根穷,?量調(diào)節(jié)?效,設(shè)備選擇导坟,?頻通路選擇等屿良。

1.6 HAL層

HAL 定義了由音頻服務(wù)調(diào)用且手機(jī)必須實(shí)現(xiàn)以確保音頻硬件功能正常運(yùn)行的標(biāo)準(zhǔn)接口。音頻 HAL 接口位于 hardware/libhardware/include/hardware 中惫周。詳情可參閱 audio.h睡汹。

1.7 內(nèi)核驅(qū)動(dòng)層

音頻驅(qū)動(dòng)程序可與硬件和 HAL 實(shí)現(xiàn)進(jìn)行交互阶冈。我們可以使用高級(jí) Linux 音頻架構(gòu) (ALSA)、開放聲音系統(tǒng) (OSS) 或自定義驅(qū)動(dòng)程序(HAL 與驅(qū)動(dòng)程序無關(guān))。

注意:如果使用的是 ALSA浮庐,建議將 external/tinyalsa 用于驅(qū)動(dòng)程序的用戶部分硼砰,因?yàn)樗哂屑嫒莸脑S可(標(biāo)準(zhǔn)的用戶模式庫已獲得 GPL 許可)乎婿。

2. 音頻系統(tǒng)架構(gòu)的演進(jìn)

一個(gè)好的系統(tǒng)架構(gòu)今阳,需要盡可能地降低上層與具體硬件的耦合,這既是操作系統(tǒng)的設(shè)計(jì)目的逊躁,對(duì)于音頻系統(tǒng)也是如此似踱。音頻系統(tǒng)的雛形框架可以簡單的用下圖來表示:

在這個(gè)圖中,除去Linux本身的Audio驅(qū)動(dòng)外,整個(gè)Android音頻實(shí)現(xiàn)都被看成了User核芽。因而我們可以認(rèn)為Audio Driver就是上層與硬件間的“隔離板”囚戚。但是如果單純采用上圖所示的框架來設(shè)計(jì)音頻系統(tǒng),對(duì)上層應(yīng)用使用音頻功能是不小的負(fù)擔(dān)轧简,顯然Android開發(fā)團(tuán)隊(duì)還會(huì)根據(jù)自身的實(shí)際情況來進(jìn)一步細(xì)化“User”部分驰坊。具體該怎么細(xì)化呢?如果是讓我們?nèi)ゼ?xì)化我們?cè)撛趺醋瞿兀?/p>

首先作為一個(gè)操作系統(tǒng)要對(duì)外提供可用的API哮独,供應(yīng)用開發(fā)者調(diào)用拳芙。APP開發(fā)者開發(fā)的應(yīng)用我們稱APP,我們提供的API姑且叫Framework皮璧。如果Framework直接和驅(qū)動(dòng)交互有什么問題呢舟扎?

  1. 首先是耦合問題,接口和實(shí)現(xiàn)耦合悴务,硬件層有任何變動(dòng)都需要接口層適配睹限,我們?cè)黾右粚佑布m配層;
  2. 資源統(tǒng)一管理的問題讯檐,如果多個(gè)APP調(diào)用相同API使用硬件資源羡疗,改怎么分配?增加統(tǒng)一資源管理器别洪,其實(shí)就是對(duì)應(yīng)Android系統(tǒng)的Audio Lib層叨恨。

細(xì)化后我們發(fā)現(xiàn),整個(gè)結(jié)構(gòu)對(duì)應(yīng)的就就是Android的幾個(gè)層次結(jié)構(gòu)挖垛,包括應(yīng)用層特碳、framework層、庫層以及HAL層晕换,如下圖所示:


我們可以結(jié)合目前已有的知識(shí),我們分析Lib層和HAL層架構(gòu)主要設(shè)計(jì)思路站宗。

2.1 Lib層

framework層的大多數(shù)類闸准,其實(shí)只是應(yīng)用程序使用Android庫文件的“中介”,它只是個(gè)殼子梢灭。因?yàn)锳ndroid應(yīng)用采用java語言編寫夷家,它們需要最直接的java接口的支持,如果我們的Android系統(tǒng)支持另一種語言的運(yùn)行時(shí)敏释,那么可以提供另一種語言的接口支持(比如Go)库快,這就是framework層存在的意義之一。但是作為“中介”钥顽,它們并不會(huì)真正去實(shí)現(xiàn)具體的功能义屏,或者只實(shí)現(xiàn)其中的一部分功能,而把主要重心放在核心庫中來完成。比如上面的AudioTrack闽铐、AudioRecorder蝶怔、MediaPlayer和MediaRecorder等等在庫中都能找到相對(duì)應(yīng)的類,這些多數(shù)是C++語言編寫的兄墅。

我們?cè)購牧硪粋€(gè)線索來思考這個(gè)問題:我們提供的API供應(yīng)用層調(diào)用踢星,那么這個(gè)API最終運(yùn)行在應(yīng)用的進(jìn)程中。如果多個(gè)應(yīng)用同時(shí)使用這個(gè)功能就會(huì)沖突隙咸;再一個(gè)允許任何一個(gè)進(jìn)程操作硬件也是個(gè)危險(xiǎn)的行為沐悦。那么真相就浮出了水面:我們需要一個(gè)有權(quán)限管理和硬件交互的進(jìn)程,需要調(diào)用某個(gè)硬件服務(wù)必須和我這個(gè)服務(wù)打交道五督。這就是Android系統(tǒng)的很常用的C/S結(jié)構(gòu)以及Binder存在的主要原因藏否。Android系統(tǒng)中的Server就是一個(gè)個(gè)系統(tǒng)服務(wù),比如ServiceManager概荷、LocationManagerService秕岛、ActivityManagerService等等,以及管理圖像合成的SurfaceFlinger误证,和今天我們今天介紹的音頻服務(wù)AudioFlinger和AudioPolicyService继薛。它們的代碼放置在frameworks/av/services/audioflinger,生成的最主要的庫叫做libaudioflinger愈捅。

這里也提到了分析源碼除以模塊為線索外的另一種線索以進(jìn)程為線索遏考。庫并不代表一個(gè)進(jìn)程,但是進(jìn)程則依賴于庫來運(yùn)行蓝谨。雖然有的類是在同一個(gè)庫中實(shí)現(xiàn)的灌具,但并不代表它們會(huì)在同一個(gè)進(jìn)程中被調(diào)用。比如AudioFlinger和AudioPolicyService都駐留于名為mediaserver的系統(tǒng)進(jìn)程中;而AudioTrack/AudioRecorder和MediaPlayer/MediaRecorder只是應(yīng)用進(jìn)程的一部分譬巫,它們通過binder服務(wù)來與其它audioflinger等系統(tǒng)進(jìn)程通信咖楣。

2.2 HAL層

硬件抽象層顧名思義為適配不同硬件而獨(dú)立封裝的一層,音頻硬件抽象層的任務(wù)是將AudioFlinger/AudioPolicyService真正地與硬件設(shè)備關(guān)聯(lián)起來芦昔,但又必須提供靈活的結(jié)構(gòu)來應(yīng)對(duì)變化诱贿。

從設(shè)計(jì)上來看,硬件抽象層是AudioFlinger直接訪問的對(duì)象咕缎。這里體現(xiàn)了兩方面的考慮:

  • 一方面AudioFlinger并不直接調(diào)用底層的驅(qū)動(dòng)程序;
  • 另一方面珠十,AudioFlinger上層(包括和它同一層的MediaPlayerService)的模塊只需要與它進(jìn)行交互就可以實(shí)現(xiàn)音頻相關(guān)的功能了。

AudioFlinger和HAL是整個(gè)架構(gòu)解耦的核心層凭豪,通過HAL層的audio.primary等庫抹平音頻設(shè)備間的差異焙蹭,無論硬件如何變化,不需要大規(guī)模地修改上層實(shí)現(xiàn)嫂伞,保證系統(tǒng)對(duì)外暴露的上層API不需要修改孔厉,達(dá)成高內(nèi)聚低耦合拯钻。而對(duì)廠商而言,在定制時(shí)的重點(diǎn)就是如何在這部分庫中進(jìn)行高效實(shí)現(xiàn)了烟馅。

舉個(gè)例子说庭,以前Android系統(tǒng)中的Audio系統(tǒng)依賴于ALSA-lib,但后期就變?yōu)榱藅inyalsa郑趁,這樣的轉(zhuǎn)變不應(yīng)該對(duì)上層造成破壞刊驴。因而Audio HAL提供了統(tǒng)一的接口來定義它與AudioFlinger/AudioPolicyService之間的通信方式,這就是audio_hw_device寡润、audio_stream_in及audio_stream_out等等存在的目的捆憎,這些Struct數(shù)據(jù)類型內(nèi)部大多只是函數(shù)指針的定義,是一個(gè)個(gè)句柄梭纹。當(dāng)AudioFlinger/AudioPolicyService初始化時(shí)躲惰,它們會(huì)去尋找系統(tǒng)中最匹配的實(shí)現(xiàn)(這些實(shí)現(xiàn)駐留在以audio.primary.,audio.a2dp.為名的各種庫中)來填充這些“殼”,可以理解成是一種“多態(tài)”的實(shí)現(xiàn)变抽。

3. Linux平臺(tái)下的兩種主要的音頻驅(qū)動(dòng)架構(gòu)介紹

上面我們的示例提到了ALSA础拨,這個(gè)其實(shí)是Linux平臺(tái)的一種音頻驅(qū)動(dòng)架構(gòu)。下面介紹兩種常見的Linux音頻驅(qū)動(dòng)架構(gòu)绍载。

3.1 OSS (Open Sound System)

早期Linux版本采用的是OSS框架诡宗,它也是Unix及類Unix系統(tǒng)中廣泛使用的一種音頻體系。OSS既可以指OSS接口本身击儡,也可以用來表示接口的實(shí)現(xiàn)塔沃。OSS的作者是Hannu Savolainen,就職于4Front Technologies公司阳谍。由于涉及到知識(shí)產(chǎn)權(quán)問題蛀柴,OSS后期的支持與改善不是很好,這也是Linux內(nèi)核最終放棄OSS的一個(gè)原因矫夯。

另外鸽疾,OSS在某些方面也遭到了人們的質(zhì)疑,比如:

  • 對(duì)新音頻特性的支持不足;

  • 缺乏對(duì)最新內(nèi)核特性的支持等等训貌。

當(dāng)然肮韧,OSS做為Unix下統(tǒng)一音頻處理操作的早期實(shí)現(xiàn),本身算是比較成功的旺订。它符合“一切都是文件”的設(shè)計(jì)理念,而且做為一種體系框架超燃,其更多地只是規(guī)定了應(yīng)用程序與操作系統(tǒng)音頻驅(qū)動(dòng)間的交互区拳,因而各個(gè)系統(tǒng)可以根據(jù)實(shí)際的需求進(jìn)行定制開發(fā)∫馀遥總的來說樱调,OSS使用了如下表所示的設(shè)備節(jié)點(diǎn):

設(shè)備節(jié)點(diǎn) 說明
/dev/dsp 向此文件寫數(shù)據(jù)à輸出到外放Speaker向此文件讀數(shù)據(jù)à從Microphone進(jìn)行錄音
/dev/mixer 混音器约素,用于對(duì)音頻設(shè)備進(jìn)行相關(guān)設(shè)置,比如音量調(diào)節(jié)
/dev/midi00 第一個(gè)MIDI端口笆凌,還有midi01,midi02等等
/dev/sequencer 用于訪問合成器(synthesizer),常用于游戲等效果的產(chǎn)生

更多詳情圣猎,可以參考OSS的官方說明

3.2 ALSA(Advanced Linux Sound Architecture)

ALSA是Linux社區(qū)為了取代OSS而提出的一種框架,是一個(gè)源代碼完全開放的系統(tǒng)(遵循GNU GPL和GNU LGPL)乞而。ALSA在Kernel 2.5版本中被正式引入后送悔,OSS就逐步被排除在內(nèi)核之外。當(dāng)然爪模,OSS本身還是在不斷維護(hù)的欠啤,只是不再為Kernel所采用而已。

ALSA相對(duì)于OSS提供了更多屋灌,也更為復(fù)雜的API接口洁段,因而開發(fā)難度相對(duì)來講加大了一些。為此共郭,ALSA專門提供了一個(gè)供開發(fā)者使用的工具庫祠丝,以幫助他們更好地使用ALSA的API。根據(jù)官方文檔的介紹除嘹,ALSA有如下特性:

  • 高效支持大多數(shù)類型的audio interface(不論是消費(fèi)型或者是專業(yè)型的多聲道聲卡)
  • 高度模塊化的聲音驅(qū)動(dòng)
  • SMP及線程安全(thread-safe)設(shè)計(jì)
  • 在用戶空間提供了alsa-lib來簡化應(yīng)用程序的編寫
  • 與OSS API保持兼容写半,這樣子可以保證老的OSS程序在系統(tǒng)中正確運(yùn)行

ALSA主要由下表所示的幾個(gè)部分組成:

Element Description
alsa-driver 內(nèi)核驅(qū)動(dòng)包
alsa-lib 用戶空間的函數(shù)庫
alsa-utils 包含了很多實(shí)用的小程序,比如alsactl:用于保存設(shè)備設(shè)置amixer:是一個(gè)命令行程序憾赁,用于聲量和其它聲音控制alsamixer:amixer的ncurses版acconnect和aseqview:制作MIDI連接污朽,以及檢查已連接的端口列表aplay和arecord:兩個(gè)命令行程序,分別用于播放和錄制多種格式的音頻
alsa-tools 包含一系列工具程序
alsa-firmware 音頻固件支持包
alsa-plugins 插件包龙考,比如jack,pulse,maemo
alsa-oss 用于兼容OSS的模擬包
pyalsa 用于編譯Python版本的alsa lib

Alsa主要的文件節(jié)點(diǎn)如下:

  1. Information Interface (/proc/asound)
  2. Control Interface (/dev/snd/controlCX)
  3. Mixer Interface (/dev/snd/mixerCXDX)
  4. PCM Interface (/dev/snd/pcmCXDX)
  5. Raw MIDI Interface (/dev/snd/midiCXDX)
  6. Sequencer Interface (/dev/snd/seq)
  7. Timer Interface (/dev/snd/timer)

Android的TinyALSA是基于Linux ALSA基礎(chǔ)改造而來蟆肆。一看“Tiny”這個(gè)詞,我們應(yīng)該能猜到這是一個(gè)ALSA的縮減版本晦款。實(shí)際上在Android系統(tǒng)的其它地方也可以看到類似的做法——既想用開源項(xiàng)目炎功,又嫌工程太大太繁瑣,怎么辦缓溅?那就只能瘦身了蛇损,于是很多Tiny-XXX就出現(xiàn)了。

在早期版本中坛怪,Android系統(tǒng)的音頻架構(gòu)主要是基于ALSA的淤齐,其上層實(shí)現(xiàn)可以看做是ALSA的一種“應(yīng)用”。后來可能是由于ALSA所存在的一些不足袜匿,Android后期版本開始不再依賴于ALSA提供的用戶空間層的實(shí)現(xiàn)更啄。HAL層最終依賴alsa-lib庫與驅(qū)動(dòng)層交互。

4. 一種新的錄音方式實(shí)現(xiàn)

除了之前提到的系統(tǒng)API居灯,我們還有其他的錄音方式嗎祭务?答案是肯定的内狗。上面我們提到HAL層依賴alsa-lib庫與驅(qū)動(dòng)層交互,我們直接使用alsa-lib义锥,繞開HAL層和Framework層不也可以做到嗎(當(dāng)然前提是要有系統(tǒng)權(quán)限)柳沙?

為什么會(huì)有這種述求呢?在做家居和車載產(chǎn)品時(shí)拌倍,會(huì)有四麥赂鲤、六麥、甚至八麥的場景贰拿。錄制大于2麥的設(shè)備時(shí)需要在HAL層以及Framework層做適配蛤袒,基于AOSP的修改會(huì)顯得特別重,特別是一些像回聲抑制膨更,聲源定位等信號(hào)處理算法妙真,如果集成在操作系統(tǒng),會(huì)有更新升級(jí)麻煩的問題荚守,我們可以基于alsa-lib在應(yīng)用層拿到多路數(shù)據(jù)調(diào)用信號(hào)處理算法珍德,這樣算法模塊升級(jí)只需要升級(jí)APP即可,不需要升級(jí)整個(gè)系統(tǒng)矗漾。

我們先來看看Android系統(tǒng)自帶的tinyX系列工具锈候。

4.1 tinymix混響器

在root用戶下調(diào)用tinymix可以查看硬件驅(qū)動(dòng)支持的混響配置

root@android:/ # tinymix
Number of controls: 7
ctl type    num name                                     value
0   ENUM    1   Playback Path                            OFF
1   ENUM    1   Capture MIC Path                         MIC OFF
2   ENUM    1   Voice Call Path                          OFF
3   ENUM    1   Voip Path                                OFF
4   INT 2   Speaker Playback Volume                  0 0
5   INT 2   Headphone Playback Volume                0 0
6   ENUM    1   Modem Input Enable                       ON
root@android:/ #
復(fù)制代碼

那么它里面的內(nèi)容是什么意思呢?

  • 首先我們要知道敞贡,一個(gè)mixer通常有多個(gè)controler泵琳,像這個(gè),里面有7個(gè)誊役,然后就分別列出每一個(gè)controller的信息获列;
  • 首先看第一個(gè):它的編號(hào)為0,類型是ENUM型蛔垢,它目前的值是OFF击孩,它是用來控制音頻輸出通道;
  • 同理鹏漆,第二個(gè)也控制音頻輸入通道巩梢;
  • 第三個(gè),通話音頻通道艺玲;
  • 第四個(gè)IP電話音頻通道括蝠;
  • 第五個(gè)揚(yáng)聲器音量,和上層音量值無關(guān)饭聚;
  • 第六個(gè)耳機(jī)音量忌警,和上層音量值無關(guān);

一般Playback Path對(duì)應(yīng)的枚舉值有:

  1. OFF:關(guān)閉
  2. RCV
  3. SPK:揚(yáng)聲器
  4. HP:耳機(jī)帶麥
  5. HP_NO_MIC:耳機(jī)無麥
  6. BT:藍(lán)牙

那么我如果像改變某一項(xiàng)的時(shí)候若治,要怎么設(shè)置呢慨蓝?方法是tinymix ctl value;如果tinymix只跟上控制器的編號(hào)端幼,就會(huì)把控制器的當(dāng)前狀態(tài)顯示出來:

# tinymix 7
Audio linein in: On
# tinymix 7 0
root@dolphin-fvd-p1:/ # **tinymix 7**
Audio linein in: Off
復(fù)制代碼

4.2 tinycap采集器

使用下面命令即可實(shí)現(xiàn)錄制并保存到sd卡:

 tinycap 
Usage: tinycap file.wav [-D card] [-d device] [-c channels] [-r rate] [-b bits] [-p period_size] [-n n_periods] 
 tinycap /sdcard/rec.wav -D 0 -d 0 –c 4 –r 16000 –b 16 –p 1024 –n 3
復(fù)制代碼

4.3 tinyplay播放

tinyplay
Usage: tinyplay file.wav [-D card] [-d device] [-p period_size] [-n n_periods]
tinyplay /sdcard/test44.wav -D 0 -d 0 -p 1024 -n 3
復(fù)制代碼

4.4 程序中集成

現(xiàn)在我們已經(jīng)通過命令的方式實(shí)現(xiàn)了繞開framework的音頻采集礼烈,我們?cè)谧约旱腶pp中怎么使用呢?如果還是通過命令的方式只能錄制到文件婆跑,無法實(shí)現(xiàn)流式錄制此熬。

解決辦法是我們的app依賴tinyalsa庫

        struct pcm_config config;
        config.channels = 4;
    config.rate = 16000;
    config.period_size = 1024;
    config.period_count = 4;
    config.start_threshold = 0;
    config.stop_threshold = 0;
    config.silence_threshold = 0;

    if (bitDepth == 32)
        config.format = PCM_FORMAT_S32_LE;
    else if (bitDepth == 16)
        config.format = PCM_FORMAT_S16_LE;
    pcm = pcm_open(0, device, PCM_IN, &config);
    if (!pcm || !pcm_is_ready(pcm)) {
        return -1;
    }
    int bufferSize = pcm_get_buffer_size(pcm);

    char *buffer = (char*)malloc(bufferSize);
    int i = pcm_read(pcm, buffer, bufferSize);
    if(i ==0){
        //success
    }
復(fù)制代碼

5. 總結(jié)

本文介紹了Andorid系統(tǒng)的整套音頻架構(gòu),以及架構(gòu)各層級(jí)的功能及作用滑进。并介紹了一種繞開framework層的新的音頻采集方式犀忱。其實(shí)Andorid的音頻架構(gòu)實(shí)現(xiàn)是更復(fù)雜的一個(gè)過程,本文只是簡略的對(duì)各個(gè)模塊做了一些介紹扶关,以助于更深入理解上一篇提到的各個(gè)API的實(shí)現(xiàn)阴汇。其實(shí)API提供出來的音頻接口,都是屬于接口層节槐,不論是Java接口還是C++接口搀庶,都隸屬于應(yīng)用進(jìn)程。以采集為例铜异,不論我們調(diào)用哪個(gè)API哥倔,我們都會(huì)發(fā)現(xiàn)啟動(dòng)后應(yīng)用進(jìn)程會(huì)多出一個(gè)AudioRecord的線程:

我們啟動(dòng)的錄制線程調(diào)用API只是從AudioRecord線程寫入到Buffer的數(shù)據(jù)的讀取。

更多Android技術(shù)分享可以關(guān)注@我,也可以加入QQ群號(hào):1078469822揍庄,學(xué)習(xí)交流Android開發(fā)技能咆蒿。

作者:輕口味
鏈接:https://juejin.cn/post/7011154855590887437
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)蚂子,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處沃测。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缆镣,隨后出現(xiàn)的幾起案子芽突,更是在濱河造成了極大的恐慌,老刑警劉巖董瞻,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寞蚌,死亡現(xiàn)場離奇詭異,居然都是意外死亡钠糊,警方通過查閱死者的電腦和手機(jī)挟秤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抄伍,“玉大人艘刚,你說我怎么就攤上這事〗卣洌” “怎么了攀甚?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵箩朴,是天一觀的道長。 經(jīng)常有香客問我秋度,道長炸庞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任荚斯,我火速辦了婚禮埠居,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘事期。我一直安慰自己滥壕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布兽泣。 她就那樣靜靜地躺著绎橘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撞叨。 梳的紋絲不亂的頭發(fā)上金踪,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音牵敷,去河邊找鬼胡岔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛枷餐,可吹牛的內(nèi)容都是我干的靶瘸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毛肋,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼怨咪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起润匙,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤诗眨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后孕讳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匠楚,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年厂财,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芋簿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡璃饱,死狀恐怖与斤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤撩穿,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布磷支,位于F島的核電站,受9級(jí)特大地震影響食寡,放射性物質(zhì)發(fā)生泄漏齐唆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一冻河、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茉帅,春花似錦叨叙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至樱蛤,卻和暖如春钮呀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昨凡。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工爽醋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人便脊。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓蚂四,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哪痰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遂赠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android Audio Architecture Android Audio Framework Archit...
    leifuuu閱讀 7,014評(píng)論 0 11
  • 提醒一下,純個(gè)人筆記晌杰,你完全可能看暈 一跷睦、音頻數(shù)字化基礎(chǔ)知識(shí) 見書,列出知識(shí)點(diǎn)如下: 聲音聲波肋演,聲音頻率抑诸、響度, ...
    YY17閱讀 31,289評(píng)論 6 48
  • 安卓系統(tǒng)是一種基于Linux的自由及開放源代碼的操作系統(tǒng)惋啃。主要使用于移動(dòng)設(shè)備哼鬓,如智能手機(jī)和平板電腦,由Google...
    特立獨(dú)行的佩奇閱讀 684評(píng)論 0 0
  • 導(dǎo)語本篇文章簡要介紹Android Audio的架構(gòu)边灭,從總體上把握Audio模塊在Android平臺(tái)上的實(shí)現(xiàn)异希。 應(yīng)...
    ZafirTab閱讀 538評(píng)論 1 5
  • 在Unity上面做音游称簿,當(dāng)在移動(dòng)端實(shí)機(jī)運(yùn)行起來扣癣,會(huì)發(fā)現(xiàn),音頻的發(fā)出會(huì)有一定的延遲憨降,無論是長音效還是短音效父虑,Unit...
    nekocon閱讀 7,960評(píng)論 1 6