空間音訊提供身歷其境的聽覺饗宴,讓影音內容變得更加逼真。音訊會經過「空間化」處理,產生宛如有多個喇叭的音效體驗 (類似環場音效設定),但透過耳機播放。
以電影為例,汽車的聲音可能會在使用者後面 然後沿著這個距離前進在視訊通話中,系統可以將聲音分離並放置在使用者周圍,方便辨識講者。
如果內容使用支援的音訊格式,您可以從 Android 13 (API 級別 33) 開始,在應用程式中加入空間音訊。
功能查詢
使用 Spatializer
類別執行下列操作:
查詢裝置的空間化功能和行為。從擷取開始
呼叫窗格中的 Spatializer
例項
AudioManager
:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
取得 Spatializer
後,請檢查哪四個條件
true,裝置才能輸出空間音訊:
條件 | 查看 |
---|---|
裝置是否支援空間化? |
getImmersiveAudioLevel() 不是 SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
是否支援空間化? 適用情況取決於與目前音訊輸出轉送的相容性。 |
isAvailable() 已true |
是否已啟用空間化功能? | isEnabled() 為 true |
包含特定參數的音軌是否可以進行空間化? | canBeSpatialized() 已true |
可能無法滿足這些條件,例如無法使用空間化功能 ,或在音訊輸出裝置中完全停用。
頭部追蹤
使用支援的耳機後,平台就能調整音訊
根據使用者的頭部位置自動調整空間化如何檢查頭部追蹤器是否
適用於目前的音訊輸出轉送,呼叫
isHeadTrackerAvailable()
。
相容內容
Spatializer.canBeSpatialized()
指出能否使用指定屬性的音訊進行空間化
目前的輸出裝置轉送方式這個方法會使用 AudioAttributes
和 AudioFormat
,兩者皆會在下方詳細說明。
AudioAttributes
AudioAttributes
物件
說明瞭 Pod 的用途
音訊串流 (例如遊戲音訊)
或標準媒體),
以及播放行為和內容類型。
呼叫 canBeSpatialized()
時,請使用與 Player
相同的 AudioAttributes
例項。舉例來說
您使用的是 Jetpack Media3 程式庫,且並未自訂
AudioAttributes
,請使用 AudioAttributes.DEFAULT
。
停用空間音訊
如要指出內容已完成空間化處理,請呼叫 setIsContentSpatialized(true)
,以免音訊遭到重複處理。或者,您也可以調整
透過呼叫
setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
。
AudioFormat
AudioFormat
物件會說明
音軌格式與頻道設定的詳細資料。
將 AudioFormat
例項化以傳入 canBeSpatialized()
時,
設定編碼
與解碼器預期的輸出格式相同您也應設定與內容管道設定相符的管道遮罩。詳情請參閱
預設空間化行為一節,瞭解
指定要使用的特定值
監聽 Spatializer
的變更
如要監聽 Spatializer
狀態的變更,您可以使用 Spatializer.addOnSpatializerStateChangedListener()
新增事件監聽器。同樣地,如要監聽頭部追蹤器可用性變化,
呼叫 Spatializer.addOnHeadTrackerAvailableListener()
。
如果你想在播放期間調整選擇的曲目,這項功能就能派上用場
透過事件監聽器的回呼例如,當使用者連線或中斷連線時
裝置上的耳機,onSpatializerAvailableChanged
回呼指出新式參數是否可使用空間化效果
音訊輸出轉送此時,您可以考慮更新播放器的
追蹤選取邏輯以配合裝置的新功能。如要進一步瞭解 ExoPlayer 的曲目選取行為,請參閱「ExoPlayer 和空間音訊」一節。
ExoPlayer 和空間音訊
ExoPlayer 最新版本還能輕鬆採用空間音訊功能。如果您使用獨立的 ExoPlayer 程式庫 (套件名稱 com.google.android.exoplayer2
),2.17 版會將平台設為輸出空間化音訊,而 2.18 版則會引入音訊頻道數限制。如果使用 Media3 程式庫中的 ExoPlayer 模組 (套件名稱),
androidx.media3
),版本 1.0.0-beta01
更新後,就會加入相同的更新
將 ExoPlayer 依附元件更新為最新版本後,應用程式 都必須包含能空間化的內容
音訊頻道數量限制
符合所有四個空間音訊條件時,ExoPlayer 會挑選結果
多聲道音軌如果沒有,ExoPlayer 會選擇立體聲音軌。
如果 Spatializer
屬性變更,ExoPlayer 會觸發新的音軌選取作業,選取與目前屬性相符的音訊音軌。請注意,這個新的曲目選取可能會導致短暫的重新緩衝期。
如要停用音訊頻道數限制,請在播放器上設定音軌選取參數,如下所示:
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
同樣地,您可以更新現有軌跡選取器的參數 聲道數的限制條件如下:
Kotlin
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
停用音訊聲道數限制 (如果內容含有多個音訊) ExoPlayer 一開始先選擇頻道數量最多的 都能從裝置播放。舉例來說,如果內容包含多聲道音軌和立體聲音軌,且裝置支援播放這兩種音軌,ExoPlayer 會選取多聲道音軌。如要進一步瞭解如何自訂這項行為,請參閱「音軌選取」一文。
選取音軌
ExoPlayer 的音訊頻道數量限制時 停用行為,ExoPlayer 不會自動選取音軌 與裝置空間器的屬性相符。您可以改為在播放前或播放期間設定音軌選取參數,自訂 ExoPlayer 的音軌選取邏輯。根據預設,ExoPlayer 會選取音訊 在 MIME 類型方面,與初始軌跡相同的音軌 (編碼)、頻道數量和取樣率。
變更曲目選取參數
如要變更 ExoPlayer 的軌道選取參數,請使用
Player.setTrackSelectionParameters()
。
同樣地,您也可以使用 Player.getTrackSelectionParameters()
取得 ExoPlayer 目前的參數。舉例來說,如要在播放期間選取立體聲音軌,請按照下列步驟操作:
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
請注意,如果在播放期間變更音軌選擇參數,可能會導致 中斷播放。進一步瞭解如何調整玩家音軌 選取參數 音軌選取 一節所述的所有內容。
預設空間化行為
Android 中的預設空間化行為包含下列行為,這些行為可由原始設備製造商 (OEM) 自訂:
只有多聲道內容會經過空間化處理,而非立體聲內容。如果您未使用 ExoPlayer,則視多聲道音訊內容的格式而定,您可能需要將音訊解碼器可輸出的最大聲道數設為較大的數字。這可以確保 音訊解碼器會輸出多頻道 PCM 供平台使用。
Kotlin
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
Java
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
如需實際操作範例,請參閱 ExoPlayer 的
MediaCodecAudioRenderer.java
。自行關閉空間化功能 (無論原始設備製造商為何) 請參閱「停用空間音訊」一文。AudioAttributes
:音訊可用於空間化 如果usage
設為USAGE_MEDIA
或USAGE_GAME
。AudioFormat
:使用至少包含AudioFormat.CHANNEL_OUT_QUAD
聲道 (前左、前右、後左和後右) 的頻道遮罩,讓音訊符合空間化處理的條件。在以下範例中,我們使用AudioFormat.CHANNEL_OUT_5POINT1
來處理 5.1 音軌。如果是立體聲音軌,請使用AudioFormat.CHANNEL_OUT_STEREO
。如果您使用的是 Media3,可以使用
Util.getAudioTrackChannelConfig(int channelCount)
將頻道數轉換為頻道遮罩。此外,如果您已將解碼器設定為輸出多聲道 PCM,請將編碼設為
AudioFormat.ENCODING_PCM_16BIT
。Kotlin
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
Java
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
測試空間音訊
確認測試裝置已啟用空間音訊功能:
- 如果是使用有線耳機,請依序前往「系統設定」>「音效和震動」>「空間音訊」。
- 如要設定無線耳機,請前往「系統設定」>已連結的裝置 >齒輪圖示 的無線裝置 >空間音訊:
如要查看目前路線空間音訊功能的可用性,請執行
adb shell dumpsys audio
指令。畫面應顯示如下
參數:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)