空間音訊提供身歷其境的聽覺饗宴,讓使用者以身歷其境的方式觀看內容,提供更逼真的內容。系統會透過耳機提供「空間化」音效,藉此產生多喇叭效果,就像設定環場音效一樣。
以電影為例,汽車的聲音可能會從使用者後方開始,接著向前移動,並將軌跡滑出至遠處。在視訊通訊中,語音可以分隔並放置在使用者周圍,方便您辨識說話者。
如果您的內容使用系統支援的音訊格式,自 Android 13 (API 級別 33) 起,您可以在應用程式中加入空間音訊。
功能查詢
使用 Spatializer
類別查詢裝置的空間化功能和行為。首先,從 AudioManager
擷取 Spatializer
的例項:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
取得 Spatializer
後,請檢查以下四個條件,確認裝置輸出空間化音訊時必須滿足哪些條件:
條件 | 查看 |
---|---|
這部裝置是否支援空間化? |
getImmersiveAudioLevel() 不是 SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
提供空間化功能嗎? 適用情況取決於與目前音訊輸出轉送的相容性。 |
isAvailable() 已true |
是否啟用空間化功能? | isEnabled() 已true |
包含特定參數的音軌是否可以進行空間化? | canBeSpatialized() 已true |
可能無法滿足這些條件,例如,如果目前的音軌無法使用空間化功能,或是完全停用音訊輸出裝置中的空間化功能,就可能不符合這些條件。
頭部追蹤
使用支援的耳機時,平台可以根據使用者的頭部位置調整音訊的空間化。如要確認車用追蹤程式是否支援目前音訊輸出轉送功能,請呼叫 isHeadTrackerAvailable()
。
相容內容
Spatializer.canBeSpatialized()
表示能否透過目前的輸出裝置轉送功能,使用具有指定屬性的音訊。這個方法需要使用 AudioAttributes
和 AudioFormat
,以下將詳細說明兩者。
AudioAttributes
AudioAttributes
物件說明音訊串流 (例如遊戲音訊或標準媒體) 的「用途」,以及播放行為和內容類型。
呼叫 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() );
請注意,如果在播放期間變更音軌選取參數,可能會導致播放中斷。如要進一步瞭解如何調整玩家的軌道選取參數,請參閱 ExoPlayer 文件的軌跡選取部分。
預設空間化行為
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
。如要自行關閉空間化功能 (無論如何自訂原始設備製造商 (OEM) 自訂功能),請參閱停用空間音訊一文。AudioAttributes
:如果usage
設為USAGE_MEDIA
或USAGE_GAME
,則音訊可用於空間化。AudioFormat
:使用頻道遮罩至少包含AudioFormat.CHANNEL_OUT_QUAD
頻道 (正面、右前方、右後方和右下方),音訊才符合空間化資格。在以下範例中,我們針對 5.1 音軌使用AudioFormat.CHANNEL_OUT_5POINT1
。如要製作立體聲音軌,請使用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)