車載音頻
Android Automotive OS (AAOS) 是在核心 Android 音頻堆棧的基礎(chǔ)之上打造而成,以支持用作車輛信息娛樂系統(tǒng)的用例。AAOS 負(fù)責(zé)實現(xiàn)信息娛樂聲音(即媒體、導(dǎo)航和通訊聲音),但不直接負(fù)責(zé)具有嚴(yán)格可用性和計時要求的鈴聲和警告。雖然 AAOS 提供了信號和機(jī)制來幫助車輛管理音頻,但最終還是由車輛來決定應(yīng)為駕駛員和乘客播放什么聲音,從而確保對保障安全至關(guān)重要的聲音和監(jiān)管聲音能被確切聽到,而不會中斷。
當(dāng) Android 管理車輛的媒體體驗時,應(yīng)通過應(yīng)用來代表外部媒體來源(例如電臺調(diào)諧器),這類應(yīng)用可以處理該來源的音頻焦點和媒體鍵事件。
對于與汽車相關(guān)的音頻支持,Android 11 進(jìn)行了以下更改:
- 根據(jù)關(guān)聯(lián)的用戶 ID 自動選擇音頻區(qū)
- 新的系統(tǒng)用法可支持特定于汽車的聲音
- HAL 音頻焦點支持
- 非瞬態(tài)聲音流的音頻焦點延遲
- 用于控制導(dǎo)航和通話之間交互的用戶設(shè)置
Android 聲音和聲音流
汽車音頻系統(tǒng)可以處理以下聲音和聲音流:
圖 1. 以聲音流為中心的架構(gòu)圖
Android 管理來自 Android 應(yīng)用的聲音,同時控制這些應(yīng)用,并根據(jù)其聲音類型將聲音路由到 HAL 中的輸出設(shè)備:
- 邏輯聲音流:在核心音頻命名法中稱為“聲源”,使用音頻屬性進(jìn)行標(biāo)記。
- 物理聲音流:在核心音頻命名法中稱為“設(shè)備”,在混音后沒有上下文信息。
為了確??煽啃?,外部聲音(來自獨立聲源,例如安全帶警告鈴聲)在 Android 外部(HAL 下方,甚至是在單獨的硬件中)進(jìn)行管理。系統(tǒng)實現(xiàn)者必須提供一個混音器,用于接受來自 Android 的一個或多個聲音輸入流,然后以合適的方式將這些聲音流與車輛所需的外部聲源組合起來。
HAL 實現(xiàn)和外部混音器負(fù)責(zé)確保對保障安全至關(guān)重要的外部聲音能夠被用戶聽到,而且負(fù)責(zé)在 Android 提供的聲音流中進(jìn)行混音,并將混音結(jié)果路由到合適的音響設(shè)備。
Android 聲音
應(yīng)用可以有一個或多個通過標(biāo)準(zhǔn) Android API(如用于控制焦點的 AudioManager 或用于在線播放的 MediaPlayer)交互的播放器,以便發(fā)出一個或多個音頻數(shù)據(jù)邏輯聲音流。這些數(shù)據(jù)可能是單聲道聲音,也可能是 7.1 環(huán)繞聲,但都會作為單個聲源進(jìn)行路由和處理。應(yīng)用聲音流與 AudioAttributes(可向系統(tǒng)提供有關(guān)應(yīng)如何表達(dá)音頻的提示)相關(guān)聯(lián)。
邏輯聲音流通過 AudioService 發(fā)送,并路由到一個(并且只有一個)可用的物理輸出聲音流,其中每個聲音流都是混音器在 AudioFlinger 內(nèi)的輸出。音頻屬性在混合到物理聲音流后將不再可用。
接下來,每個物理聲音流都會傳輸?shù)揭纛l HAL,以在硬件上呈現(xiàn)。在汽車應(yīng)用中,呈現(xiàn)硬件可能是本地編解碼器(類似于移動設(shè)備),也可能是車輛物理網(wǎng)絡(luò)中的遠(yuǎn)程處理器。無論是哪種情況,音頻 HAL 實現(xiàn)都需要提供實際樣本數(shù)據(jù)并使其能被用戶聽見。
外部聲音流
如果聲音流因認(rèn)證或計時原因而不應(yīng)經(jīng)由 Android,則可以直接發(fā)送到外部混音器。從 Android 11 開始,HAL 現(xiàn)在能夠針對這些外部聲音請求焦點,以通知 Android,使其能夠采取適當(dāng)措施(例如暫停媒體或阻止其他人獲得焦點)。
如果外部聲音流是應(yīng)與 Android 正在生成的聲音環(huán)境交互的媒體源(例如,當(dāng)外部調(diào)諧器處于開啟狀態(tài)時,停止 MP3 播放),則那些外部聲音流應(yīng)由 Android 應(yīng)用表示。此類應(yīng)用將代表媒體來源(而非 HAL)請求音頻焦點,并根據(jù)需要通過啟動/停止外部聲音源來響應(yīng)焦點通知,以符合 Android 音頻焦點政策規(guī)定。應(yīng)用還負(fù)責(zé)處理媒體鍵事件,例如播放/暫停。如需控制此類外部設(shè)備,建議使用的一種機(jī)制是 HwAudioSource。
輸出設(shè)備
在音頻 HAL 級別,設(shè)備類型 AUDIO_DEVICE_OUT_BUS 提供用于車載音頻系統(tǒng)的通用輸出設(shè)備??偩€設(shè)備支持可尋址端口(其中每個端口都是一個物理聲音流的端點),并且應(yīng)該是車輛內(nèi)唯一受支持的輸出設(shè)備類型。
系統(tǒng)實現(xiàn)可以針對所有 Android 聲音使用一個總線端口,在這種情況下,Android 會將所有聲音混合在一起,并將混音結(jié)果作為一個聲音流進(jìn)行傳輸。此外,HAL 可以分別為每個 CarAudioContext 提供一個總線端口,以允許并發(fā)傳輸任何聲音類型。這樣一來,HAL 實現(xiàn)就可以根據(jù)需要混合和閃避不同的聲音。
音頻上下文到輸出設(shè)備的分配是通過 car_audio_configuration.xml 完成的。
麥克風(fēng)輸入
在捕獲音頻時,音頻 HAL 會收到 openInputStream 調(diào)用,其中包含指示應(yīng)如何處理麥克風(fēng)輸入的 AudioSource 參數(shù)。
VOICE_RECOGNITION 源(尤其是 Google 助理)需要一個符合以下條件的立體聲麥克風(fēng)流:具有回聲消除效果(如果有),但不應(yīng)用任何其他處理。波束成形應(yīng)由 Google 助理來完成。
多聲道麥克風(fēng)輸入
若要從具有兩個以上聲道(立體聲)的設(shè)備捕獲音頻,請使用聲道索引掩碼,而不是定位索引掩碼(例如 CHANNEL_IN_LEFT)。例如:
final AudioFormat audioFormat = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(44100)
.setChannelIndexMask(0xf /* 4 channels, 0..3 */)
.build();
final AudioRecord audioRecord = new AudioRecord.Builder()
.setAudioFormat(audioFormat)
.build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);
如果 setChannelMask 和 setChannelIndexMask 均已設(shè)置,則 AudioRecord 僅使用由 setChannelMask 設(shè)置的值(最多兩個聲道)。
并發(fā)捕獲
從 Android 10 開始,Android 框架支持并發(fā)捕獲輸入,但具有保護(hù)用戶隱私的限制。作為這些限制的一部分,AUDIO_SOURCE_FM_TUNER 等虛擬來源會被忽略,因此可以與常規(guī)輸入(例如麥克風(fēng))同時捕獲。HwAudioSources 也不會被納入并發(fā)捕獲限制。
旨在與 AUDIO_DEVICE_IN_BUS 設(shè)備或輔助 AUDIO_DEVICE_IN_FM_TUNER 設(shè)備結(jié)合使用的應(yīng)用必須依賴于以下功能:明確識別這些設(shè)備,以及使用 AudioRecord.setPreferredDevice() 繞過 Android 默認(rèn)聲源選擇邏輯。
音頻用法
AAOS 主要使用 AudioAttributes.AttributeUsages 進(jìn)行路由、音量調(diào)整和焦點管理。用法用于表示播放聲音流的“原因”。因此,所有聲音流和音頻焦點請求都應(yīng)為其音頻播放指定用法。如果在構(gòu)建 AudioAttributes 對象時未明確設(shè)置,則用法將默認(rèn)為 USAGE_UNKOWN。雖然目前會對此用法采取與 USAGE_MEDIA 一樣的處理,但不應(yīng)依賴此行為進(jìn)行媒體播放。
系統(tǒng)用法
Android 11 中引入了系統(tǒng)用法。這些用法的行為與之前確立的用法類似,不同之處在于它們需要使用系統(tǒng) API 以及 android.permission.MODIFY_AUDIO_ROUTING。新的系統(tǒng)用法如下:
- USAGE_EMERGENCY
- USAGE_SAFETY
- USAGE_VEHICLE_STATUS
- USAGE_ANNOUNCEMENT
若要通過系統(tǒng)用法構(gòu)造 AudioAttributes,請使用 AudioAttributes.Builder#setSystemUsage,而不是 setUsage。如果要通過非系統(tǒng)用法調(diào)用此方法,就會導(dǎo)致系統(tǒng)拋出 IllegalArgumentException。此外,如果同時在構(gòu)建器上設(shè)置了系統(tǒng)用法和非系統(tǒng)用法,則在構(gòu)建時將會拋出 IllegalArgumentException。
如需查看與 AudioAttributes 實例關(guān)聯(lián)的用法,請調(diào)用 AudioAttributes#getSystemUsage。這將返回關(guān)聯(lián)的用法或系統(tǒng)用法。
音頻上下文
為了簡化 AAOS 音頻的配置,類似用法均已歸入 CarAudioContext。這些音頻上下文會在整個 CarAudioService 中使用,以定義路由、音量組和音頻焦點管理。
Android 11 中的音頻上下文包括:
CarAudioContext | 關(guān)聯(lián)的 AttributeUsages |
---|---|
MUSIC | UNKNOWN, GAME, MEDIA |
NAVIGATION | ASSISTANCE_NAVIGATION_GUIDANCE |
VOICE_COMMAND | ASSISTANT, ASSISTANCE_ACCESSIBILITY |
CALL_RING | NOTIFICATION_RINGTONE |
CALL | VOICE_COMMUNICATION, VOICE_COMMUNICATION_SIGNALING |
ALARM | ALARM |
NOTIFICATION | NOTIFICATION, NOTIFICATION_* |
SYSTEM_SOUND | ASSISTANCE_SONIFICATION |
EMERGENCY | EMERGENCY |
SAFETY | SAFETY |
VEHICLE_STATUS | VEHICLE_STATUS |
ANNOUNCEMENT | ANNOUNCEMENT |
音頻上下文和用法之間的映射關(guān)系。突出顯示的行用于新的系統(tǒng)用法。
多區(qū)音頻
在汽車領(lǐng)域,圍繞多個用戶同時與平臺互動并且每個用戶都希望使用單獨媒體的需求,出現(xiàn)了一系列新的用例。例如,后座上的乘客在后座顯示屏上觀看 YouTube 視頻時,司機(jī)可以在駕駛艙中播放音樂。多區(qū)音頻通過允許不同的音頻源在車輛的不同音頻區(qū)同時進(jìn)行播放來實現(xiàn)此目的。
從 Android 10 開始提供的多區(qū)音頻讓原始設(shè)備制造商 (OEM) 能夠?qū)⒁纛l配置到單獨的音頻區(qū)。每個音頻區(qū)由車輛內(nèi)的一組設(shè)備組成,并且有各自的音量組、上下文路由配置以及焦點管理。通過這種方式,可以將主駕駛艙配置為一個音頻區(qū),而將后座顯示屏的耳機(jī)插孔配置為第二個音頻區(qū)。
這些音頻區(qū)被定義為 car_audio_configuration.xml 的一部分。然后,CarAudioService 讀取該配置,并幫助 AudioService 根據(jù)關(guān)聯(lián)的音頻區(qū)路由音頻流。每個音頻區(qū)仍會根據(jù)上下文和應(yīng)用 UID 定義路由規(guī)則。創(chuàng)建播放器時,CarAudioService 會確定播放器與哪個音頻區(qū)相關(guān)聯(lián),然后根據(jù)用法確定 AudioFlinger 應(yīng)將音頻路由到哪個設(shè)備。
每個音頻區(qū)的焦點也是單獨維護(hù)的。這使得不同音頻區(qū)中的應(yīng)用可以單獨生成音頻,而不會彼此干擾,同時讓應(yīng)用保持關(guān)注其所在音頻區(qū)內(nèi)焦點的變化。CarAudioService 內(nèi)中的 CarZonesAudioFocus 負(fù)責(zé)管理每個音頻區(qū)的焦點。
音頻 HAL
車載音頻實現(xiàn)依賴標(biāo)準(zhǔn) Android 音頻 HAL,其中包括以下內(nèi)容:
- IDevice.hal:負(fù)責(zé)創(chuàng)建輸入聲音流和輸出聲音流、處理主音量和靜音操作,以及使用:
createAudioPatch:在設(shè)備之間創(chuàng)建外部-外部音頻通路。
IDevice.setAudioPortConfig():為各個物理聲音流提供音量。 - IStream.hal:連同輸入變體和輸出變體一起管理進(jìn)出硬件的樣本音頻流。
車載設(shè)備類型
以下設(shè)備類型與車載平臺相關(guān):
設(shè)備類型 | 說明 |
---|---|
AUDIO_DEVICE_OUT_BUS | Android 的主要輸出(Android 的所有音頻均通過這種方式提供給車輛)。用作消除各個上下文的信息流歧義的地址。 |
AUDIO_DEVICE_OUT_TELEPHONY_TX 用于傳輸路由到手機(jī)無線裝置的音頻。 | |
AUDIO_DEVICE_IN_BUS | 用于尚未進(jìn)行分類的輸入。 |
AUDIO_DEVICE_IN_FM_TUNER | 僅用于廣播無線裝置輸入。 |
AUDIO_DEVICE_IN_TV_TUNER | 用于電視設(shè)備(如果存在)。 |
AUDIO_DEVICE_IN_LINE | 用于 AUX 輸入耳機(jī)插孔。 |
AUDIO_DEVICE_IN_BLUETOOTH_A2DP | 通過藍(lán)牙接收到的音樂。 |
AUDIO_DEVICE_IN_TELEPHONY_RX | 用于從移動網(wǎng)絡(luò)電臺接收到的與通話相關(guān)聯(lián)的音頻。 |
配置音頻設(shè)備
Android 可見的音頻設(shè)備必須在 /audio_policy_configuration.xml 中進(jìn)行定義,其中包括以下組件:文章來源:http://www.zghlxwxcb.cn/news/detail-400191.html
- 模塊名稱:支持“primary”(用于汽車用例)、“A2DP”、“remote_submix”和“USB”。模塊名稱和相應(yīng)音頻驅(qū)動程序應(yīng)編譯到 audio.primary.$(variant).so 中。
- devicePorts:包含可從此模塊訪問的所有輸入和輸出設(shè)備(包括永久連接的設(shè)備和可移除設(shè)備)的設(shè)備描述符列表。
- 對于每種輸出設(shè)備,您可以定義增益控制(包含以 millibel 為單位的 min/max/default/step 值,其中 1 millibel = 1/100 dB = 1/1000 bel)。
- 即使有多個設(shè)備的設(shè)備類型為 AUDIO_DEVICE_OUT_BUS,也可以使用 devicePort 實例上的地址屬性查找設(shè)備。
- mixPorts:包含由音頻 HAL 提供的所有輸出聲音流和輸入聲音流的列表。每個 mixPort 實例都可被視為傳輸?shù)?Android AudioService 的物理聲音流。
- routes:定義輸入和輸出設(shè)備之間或聲音流和設(shè)備之間可能存在的連接的列表。
以下示例定義了輸出設(shè)備 bus0_phone_out,其中所有 Android 音頻流都通過 mixer_bus0_phone_out 完成混音。該路由會將 mixer_bus0_phone_out 的輸出聲音流傳遞到設(shè)備 bus0_phone_out。文章來源地址http://www.zghlxwxcb.cn/news/detail-400191.html
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<modules>
<module name="primary" halVersion="3.0">
<attachedDevices>
<item>bus0_phone_out</item>
<defaultOutputDevice>bus0_phone_out</defaultOutputDevice>
<mixPorts>
<mixPort name="mixport_bus0_phone_out"
role="source"
flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="bus0_phone_out"
role="sink"
type="AUDIO_DEVICE_OUT_BUS"
address="BUS00_PHONE">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
minValueMB="-8400"
maxValueMB="4000"
defaultValueMB="0"
stepValueMB="100"/>
</gains>
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="bus0_phone_out"
sources="mixport_bus0_phone_out"/>
</routes>
</module>
</modules>
</audioPolicyConfiguration>
到了這里,關(guān)于Android automotive車載開發(fā)(1)-----Automotive audio的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!