Android 音訊系統:從 AudioTrack 到 AudioFlinger
1. Android 音訊框架概述
Audio 是整個 Android 平臺非常重要的一個組成部分,負責音訊資料的採集和輸出、音訊流的控制、音訊裝置的管理、音量調節等,主要包括如下部分:
- Audio Application Framework:音訊應用框架
- AudioTrack:負責回放資料的輸出,屬 Android 應用框架 API 類
- AudioRecord:負責錄音資料的採集,屬 Android 應用框架 API 類
- AudioSystem: 負責音訊事務的綜合管理,屬 Android 應用框架 API 類
- Audio Native Framework:音訊本地框架
- AudioTrack:負責回放資料的輸出,屬 Android 本地框架 API 類
- AudioRecord:負責錄音資料的採集,屬 Android 本地框架 API 類
- AudioSystem: 負責音訊事務的綜合管理,屬 Android 本地框架 API 類
- Audio Services:音訊服務
- AudioPolicyService:音訊策略的制定者,負責音訊裝置切換的策略抉擇、音量調節策略等
- AudioFlinger:音訊策略的執行者,負責輸入輸出流裝置的管理及音訊流資料的處理傳輸
- Audio HAL:音訊硬體抽象層,負責與音訊硬體裝置的互動,由 AudioFlinger 直接呼叫
與 Audio 強相關的有 MultiMedia,MultiMedia 負責音視訊的編解碼,MultiMedia 將解碼後的資料通過 AudioTrack 輸出,而 AudioRecord 採集的錄音資料交由 MultiMedia 進行編碼。
本文分析基於 Android 7.0 - Nougat。
//////////////////////////////////////////////////////////////////////////////////////
// 宣告:本文由 http://blog.csdn.net/zyuanyun 原創,轉載請註明出處,謝謝!
//////////////////////////////////////////////////////////////////////////////////////
2. AudioTrack API 概述
播放聲音可以使用 MediaPlayer 和 AudioTrack,兩者都提供 Java API 給應用開發者使用。兩者的差別在於:MediaPlayer 可以播放多種格式的音源,如 mp3、flac、wma、ogg、wav 等,而 AudioTrack 只能播放解碼後的 PCM 資料流。從上面 Android 音訊系統架構圖來看:MediaPlayer 在 Native 層會建立對應的音訊解碼器和一個 AudioTrack,解碼後的資料交由 AudioTrack 輸出。所以 MediaPlayer 的應用場景更廣,一般情況下使用它也更方便;只有一些對聲音時延要求非常苛刻的應用場景才需要用到 AudioTrack。
2.1. AudioTrack Java API
AudioTrack Java API 兩種資料傳輸模式:
Transfer Mode | Description |
---|---|
MODE_STATIC | 應用程序將回放資料一次性付給 AudioTrack,適用於資料量小、時延要求高的場景 |
MODE_STREAM | 用程序需要持續呼叫 write() 寫資料到 FIFO,寫資料時有可能遭遇阻塞(等待 AudioFlinger::PlaybackThread 消費之前的資料),基本適用所有的音訊場景 |
AudioTrack Java API 音訊流型別:
Stream Type | Description |
---|---|
STREAM_VOICE_CALL | 電話語音 |
STREAM_SYSTEM | 系統聲音 |
STREAM_RING | 鈴聲聲音,如來電鈴聲、鬧鐘鈴聲等 |
STREAM_MUSIC | 音樂聲音 |
STREAM_ALARM | 警告音 |
STREAM_NOTIFICATION | 通知音 |
STREAM_DTMF | DTMF 音(撥號盤按鍵音) |
Android 為什麼要定義這麼多的流型別?這與 Android 的音訊管理策略有關,例如:
- 音訊流的音量管理,調節一個型別的音訊流音量,不會影響到其他型別的音訊流
- 根據流型別選擇合適的輸出裝置;比如插著有線耳機期間,音樂聲(STREAM_MUSIC)只會輸出到有線耳機,而鈴聲(STREAM_RING)會同時輸出到有線耳機和外放
這些屬於 AudioPolicyService 的內容,本文不展開分析了。應用開發者應該根據應用場景選擇相應的流型別,以便系統為這道流選擇合適的輸出裝置。
一個 AudioTrack Java API 的測試例子(MODE_STREAM 模式):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
詳細說明下 getMinBufferSize() 介面,字面意思是返回最小資料緩衝區的大小,它是聲音能正常播放的最低保障,從函式引數來看,返回值取決於取樣率、取樣深度、聲道數這三個屬性。MODE_STREAM 模式下,應用程式重點參考其返回值然後確定分配多大的資料緩衝區。如果資料緩衝區分配得過小,那麼播放聲音會頻繁遭遇 underrun,underrun 是指生產者(AudioTrack)提供資料的速度跟不上消費者(AudioFlinger::PlaybackThread)消耗資料的速度,反映到現實的後果就是聲音斷續卡頓,嚴重影響聽覺體驗。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
可見最小緩衝區的大小 = 最低幀數 * 聲道數 * 取樣深度,(取樣深度以位元組為單位)
,到這裡大家應該有所明悟了吧,在視訊中,如果幀數過低,那麼畫面會有卡頓感,對於音訊,道理也是一樣的。最低幀數如何求得,我們到 native 層再解釋。
關於 MediaPlayer、AudioTrack,更多更詳細的 API 介面說明請參考 Android Developer:
2.2. AudioTrack Native API
AudioTrack Native API 四種資料傳輸模式:
Transfer Mode | Description |
---|---|
TRANSFER_CALLBACK | 在 AudioTrackThread 執行緒中通過 audioCallback 回撥函式主動從應用程序那裡索取資料,ToneGenerator 採用這種模式 |
TRANSFER_OBTAIN | 應用程序需要呼叫 obtainBuffer()/releaseBuffer() 填充資料,目前我還沒有見到實際的使用場景 |
TRANSFER_SYNC | 應用程序需要持續呼叫 write() 寫資料到 FIFO,寫資料時有可能遭遇阻塞(等待 AudioFlinger::PlaybackThread 消費之前的資料),基本適用所有的音訊場景;對應於 AudioTrack Java API 的 MODE_STREAM 模式 |
TRANSFER_SHARED | 應用程序將回放資料一次性付給 AudioTrack,適用於資料量小、時延要求高的場景;對應於 AudioTrack Java API 的 MODE_STATIC 模式 |
AudioTrack Native API 音訊流型別:
Stream Type | Description |
---|---|
AUDIO_STREAM_VOICE_CALL | 電話語音 |
AUDIO_STREAM_SYSTEM | 系統聲音 |
AUDIO_STREAM_RING | 鈴聲聲音,如來電鈴聲、鬧鐘鈴聲等 |
AUDIO_STREAM_MUSIC | 音樂聲音 |
AUDIO_STREAM_ALARM | 警告音 |
AUDIO_STREAM_NOTIFICATION | 通知音 |
AUDIO_STREAM_DTMF | DTMF 音(撥號盤按鍵音) |
AudioTrack Native API 輸出標識:
AUDIO_OUTPUT_FLAG | Description |
---|---|
AUDIO_OUTPUT_FLAG_DIRECT | 表示音訊流直接輸出到音訊裝置,不需要軟體混音,一般用於 HDMI 裝置聲音輸出 |
AUDIO_OUTPUT_FLAG_PRIMARY | 表示音訊流需要輸出到主輸出裝置,一般用於鈴聲類聲音 |
AUDIO_OUTPUT_FLAG_FAST | 表示音訊流需要快速輸出到音訊裝置,一般用於按鍵音、遊戲背景音等對時延要求高的場景 |
AUDIO_OUTPUT_FLAG_DEEP_BUFFER | 表示音訊流輸出可以接受較大的時延,一般用於音樂、視訊播放等對時延要求不高的場景 |
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | 表示音訊流沒有經過軟體解碼,需要輸出到硬體解碼器,由硬體解碼器進行解碼 |
我們根據不同的播放場景,使用不同的輸出標識,如按鍵音、遊戲背景音對輸出時延要求很高,那麼就需要置 AUDIO_OUTPUT_FLAG_FAST,具體可以參考 ToneGenerator、SoundPool 和 OpenSL ES。
一個 AudioTrack Natvie API 的測試例子(MODE_STATIC/TRANSFER_SHARED 模式),程式碼檔案位置:frameworks/base/media/tests/audiotests/shared_mem_test.cpp:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
-
相關推薦
Android 音訊系統:從 AudioTrack 到 AudioFlinger
1. Android 音訊框架概述 Audio 是整個 Android 平臺非常重要的一個組成部分,負責音訊資料的採集和輸出、音訊流的控制、音訊裝置的管理、音量調節等,主要包括如下部分: Audio Application Framework:音訊
ANDROID音訊系統散記之三:resample-2
這篇是承接上一篇提到的底層resample處理,以Samsung的tiny alsa-lib為例說明。 tiny alsa-lib 這個tiny alsa-lib位於android2.3.1-gingerbread/device/samsung/crespo/libau
ANDROID音訊系統散記之二:resample
預設的情況下,Android放音的取樣率固定為44.1khz,錄音的取樣率固定為8khz,因此底層的音訊裝置驅動只需設定好這兩個固定的取樣率。如果上層傳過來的取樣率與其不符的話,則Android Framework層會對音訊流做resample(重取樣)處理。 Resamp
Android音訊系統之AudioFlinger(一)
在上面的框架圖中,我們可以看到AudioFlinger(下面簡稱AF)是整個音訊系統的核心與難點。作為Android系統中的音訊中樞,它同時也是一個系統服務,啟到承上(為上層提供訪問介面)啟下(通過HAL來管理音訊裝置)的作用。只有理解了AudioFlinger,才能以此
ANDROID音訊系統散記之二:resample-1
Android上的resample處理 預設的情況下,Android放音的取樣率固定為44.1khz,錄音的取樣率固定為8khz,因此底層的音訊裝置驅動只需設定好這兩個固定的取樣率。如果上層傳過來的取樣率與其不符的話,則Android Framework層會對音訊流做resample(重取樣)處理。 Re
視頻直播系統:從直播源碼當中我們能看到什麽?
直播軟件開發越來越多的數據表明直播行業發展的曲線,是一種良性又快速的增長。這種增長方式得益於各大主流網絡直播平臺的領頭作用,又得益於視頻直播開發的良性循環。從視頻直播開發當中,能清晰的看到,直播源碼在其中占著絕大的“領地”。而我們由大及小,單單從直播源碼當中,就能看到這個行業發展的路程。視頻直播開發,用長遠的
Android音訊系統適配《C++功能層》
繼上一篇Android音訊系統適配《java邏輯層》之後,我們需要知道整個功能介面的實現路由,其實相對而言要簡單很多。上一篇有提到AudioManager.java所呼叫的介面的最終實現是在AudioSystem.java。本篇我們就從AudioSystem.java開始。
android音訊系統簡介
音訊基礎知識 聲音有哪些重要屬性呢? 響度(Loudness) 響度就是人類可以感知到的各種聲音的大小,也就是音量。響度與聲波的振幅有直接關係。 音調(Pitch) 音調與聲音的頻率有關係,當聲音的頻率越大時,人耳所感知到的音調就越高,否則就越低。 音色(Qualit
android 音訊系統/音效卡驅動 codec
0. 專用術語 1. 物理結構 2. 系統架構 本文基於Freescale IMX平臺Codec ALC5625為例。 0. 專用術語 ASLA - Advanced Sound Linux Architecture OSS - 以前的Linux音訊體系結構,被ASL
Android音訊系統框架簡述
情景1:音效卡驅動比較複雜,提供一個lib層對驅動進行封裝,APP調驅動.。框圖如下: 情景2:廠家對音效卡的配置更瞭解,設定的引數在HAL層,HAL呼叫lib,傳入不同引數,提供給APP.框圖如下: 情景3: 如果多個APP播放聲音,把聲音合成播放,則多了AudioFlinger層。
Linux ALSA 音訊系統:邏輯裝置篇
6. 音效卡和 PCM 裝置的建立過程 前面幾章分析了 Codec、Platform、Machine 驅動的組成部分及其註冊過程,這三者都是物理裝置相關的,大家應該對音訊物理鏈路有了一定的認知。接著分析音訊驅動的中間層,由於這些並不是真正的物理裝置,故我們稱之
Android外掛化:從入門到放棄
本文根據包建強在2016GMTC全球移動開發大會上的演講整理而成。 首先自我介紹一下,我叫包建強,是這個分場的主持人。我去年寫了一本書,叫《App研發錄》,相信有很多從事技術的朋友看過或買過。 引言 先簡單介紹一下Android外掛化。很早之前已經有公司在研究這
Android音訊系統之音訊框架
Android的音訊系統在很長一段時間內都是外界詬病的焦點。的確,早期的android系統在音訊處理上相比於iOS有一定的差距,這也是很多專業的音樂播放軟體開發商沒有推出Android平臺產品的一個重要原因。但這並不代表它的音訊框架一無是處,相反,基於Linux系統的
Android 音訊系統
http://blog.csdn.net/qianjin0703/article/details/6387662 0. 專用術語 1. 物理結構 2. 系統架構 本文基於Freescale IMX平臺Codec ALC5625為例。 0. 專用術語 ASLA - Advanced Sound Linux
Android音訊系統
Muti-media時多種形式的媒體內容(文字、音訊、視訊、圖片、動畫)的組合。多媒體可以是“MediaPlayer和MediaRecorder”的實現,Android的一大特性時高度封裝,提高了軟體的開發效率。這也使得整個多媒體系統顯得異常龐大,各種類定義、C
Android核心開發:從原始碼樹中刪除出廠的app應用
公開課1060:組策略(下) 12345678910 本文是《Android核心開發》系列的第十一篇文章,本文重點介紹如何從Android原始碼中刪除出廠的app應用。 上一篇文章中提到過,系統出廠的app應用,其實就是被安裝到/system分割槽的app
Android音訊系統之音訊基礎
轉載請註明:LXS, http://blog.csdn.net/uiop78uiop78/article/details/8787779 對於一部嵌入式裝置來說,除了若干基礎功能外(比如手機通話、簡訊),最重要的可能就是多媒體了——那麼一個最簡單的問題,什麼是多媒體呢?
Android程序系統:程序的建立、啟動與排程流程
Android程序框架:程序的建立、啟動與排程流程 文章目錄 一 程序的建立與啟動流程 二 程序的優先順序 三 程序的排程流程 Android系統的啟動流程如下圖(點選檢視大圖)所示: Loader層 當手機處於關機狀態時,長按電源鍵開機,引
Linux ALSA 音訊系統:物理鏈路篇
1. Overview 硬體平臺及軟體版本: Kernel - 3.4.5 SoC - Samsung exynos CODEC - WM8994 Machine - goni_wm8994 Userspace - tinyalsa Linux ALS
通用Android應用架構:從建專案開始
1.專案結構 現在的MVP模式越來越流行。就預設採用了。 如果專案比較小的話: app——Application Activity Fragment Presenter等的頂級父類 config——API,常量表等 model——資料層 entit