Jetpack SceneCore 的空間音訊功能可讓您在 Android XR 應用程式中,打造身歷其境的音訊體驗。
空間音訊會模擬使用者在 3D 環境中感知聲音的方式,營造出聲音從四面八方傳來的感覺,包括使用者上方和下方。系統會在 3D 空間的特定位置模擬一或多個「虛擬揚聲器」,藉此達到效果。
如果現有應用程式並非專為 Android XR 設計或修改,Android XR 會自動將音訊空間化。使用者在空間中移動時,所有應用程式音訊都會從應用程式 UI 顯示的面板發出。舉例來說,如果時鐘應用程式的計時器響起,音訊會從應用程式面板的位置發出。Android XR 會自動調整音效,呈現逼真的位置感。舉例來說,應用程式面板與使用者之間的距離會影響音量,讓使用者更有身歷其境的感覺。
如要進一步瞭解現有應用程式如何算繪空間音訊,請參閱本頁面的「在應用程式中加入立體聲和環場音效」。
如果您要針對 XR 最佳化應用程式,Jetpack SceneCore 提供進階空間音訊自訂工具。您可以在 3D 環境中精確定位聲音、使用全向性音訊呈現逼真的音場,以及善用內建的環繞音效整合功能。
Android XR 支援的空間音效類型
Android XR 支援位置、立體聲、環場音效和 Ambisonic 音訊。
位置音訊
位置音訊可設定為從 3D 空間中的特定點播放。 舉例來說,您可以在虛擬環境的角落放置一隻狗的 3D 模型,並讓牠發出吠叫聲。您可以讓多個實體從各自的位置發出聲音。如要算繪位置音訊,檔案必須是單聲道或立體聲。
空間化立體聲和環場音效
所有 Android 媒體格式都支援位置、立體聲和環場音效。除了上述格式,Android XR 裝置也可能支援 Dolby Atmos、Dolby Digital 和 Dolby Digital+ 音訊格式。
立體聲音訊是指具有兩個聲道的音訊格式,環場音效是指具有兩個以上聲道的音訊格式,例如 5.1 環場音效或 7.1 環場音效設定。每個聲道的聲音資料都會與一個音箱相關聯。舉例來說,播放立體聲音樂時,左揚聲器聲道發出的樂器音軌可能與右揚聲器不同。
電影和電視節目通常會使用環場音效,透過多個音箱聲道來提升真實感和沉浸感。舉例來說,對話通常會從中央揚聲器聲道播放,而直升機飛行的聲音可能會依序使用不同聲道,營造直升機在 3D 空間中飛行的感覺。
全方位音訊
全景聲 (或全景聲) 就像音訊的 Skybox,可為使用者提供沉浸式音景。使用 Ambisonics 技術播放背景環境音效,或在其他情境中複製環繞聽者的全球形音場。Android XR 支援AmbiX 環繞聲音訊格式,包括第一、第二和第三階環繞聲。建議使用 Opus (.ogg) 和 PCM/Wave (.wav) 檔案類型。
使用 Jetpack SceneCore 空間音訊
使用 Jetpack SceneCore 實作空間音訊時,需要檢查空間功能,並選擇用於載入空間音訊的 API。
檢查空間功能
使用空間音訊功能前,請確認 Session 支援空間音訊。在下列各節的所有程式碼片段中,系統都會先檢查功能,再嘗試播放空間化音訊。
載入空間音訊
您可以使用下列任一 API,載入 Jetpack SceneCore 中使用的空間音訊。
SoundPool:適合用於大小不到 1 MB 的短音效,會預先載入,且可重複使用。這是載入位置音訊的絕佳方式。ExoPlayer:適合載入立體聲和環繞音效內容,例如音樂和影片。還能讓媒體在背景播放。MediaPlayer:提供載入 Ambisonic 音訊的最簡單方式。AudioTrack:可充分控管音訊資料的載入方式。可直接寫入音訊緩衝區,或寫入您合成或解碼的音訊檔案。
檢查是否支援媒體格式
Android 平台支援部分媒體格式。不過,特定 Android XR 裝置可能支援其他格式,例如 Dolby Atmos。如要查詢媒體格式支援情形,請使用 ExoPlayer 的 AudioCapabilities:
val audioCapabilities = AudioCapabilities.getCapabilities(context, androidx.media3.common.AudioAttributes.DEFAULT, null) if (audioCapabilities.supportsEncoding(C.ENCODING_AC3)) { // Device supports playback of the Dolby Digital media format. } if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) { // Device supports playback of the Dolby Digital Plus media format. } if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3_JOC)) { // Device supports playback of the Dolby Digital Plus with Dolby Atmos media format. }
檢查這些功能可能涉及封鎖呼叫,不應在主執行緒上呼叫。
在應用程式中加入位置音訊
位置音效來源是由 PointSourceParams 和相關聯的 Entity 定義。Entity 的位置和方向會決定 PointSourceParams 在 3D 空間中的算繪位置。
位置音訊範例
以下範例會將音效音訊檔案載入音效集區,並在 Entity 的位置播放。
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO) ) { // The session has spatial audio capabilities val maxVolume = 1F val lowPriority = 0 val infiniteLoop = -1 val normalSpeed = 1F val soundPool = SoundPool.Builder() .setAudioAttributes( AudioAttributes.Builder() .setContentType(CONTENT_TYPE_SONIFICATION) .setUsage(USAGE_ASSISTANCE_SONIFICATION) .build() ) .build() val pointSource = PointSourceParams(entity) val soundEffect = appContext.assets.openFd("sounds/tiger_16db.mp3") val pointSoundId = soundPool.load(soundEffect, lowPriority) soundPool.setOnLoadCompleteListener { soundPool, sampleId, status -> // wait for the sound file to be loaded into the soundPool if (status == 0) { SpatialSoundPool.play( session = session, soundPool = soundPool, soundID = pointSoundId, params = pointSource, volume = maxVolume, priority = lowPriority, loop = infiniteLoop, rate = normalSpeed ) } } } else { // The session does not have spatial audio capabilities }
程式碼相關重點
- 首先,請使用
spatialCapabilities檢查目前是否提供空間音訊功能。 - 將 contentType 設為
CONTENT_TYPE_SONIFICATION,並將 usage 設為USAGE_ASSISTANCE_SONIFICATION,系統就會將這個音訊檔案視為音效。 - 上述範例會將音訊檔案載入集區,然後立即使用,方便您將程式碼放在一起。理想情況下,您應該在載入應用程式時,非同步載入所有音效,這樣需要時,音訊檔案就能在集區中派上用場。
在應用程式中加入立體聲和環繞音效
建議使用 Exoplayer,在應用程式中加入立體聲和環場音效。如要進一步瞭解如何搭配 Exoplayer 使用空間音訊,請參閱空間音訊指南。
立體聲和環場音效揚聲器位置
透過環繞喇叭定位,虛擬環繞喇叭會根據中央喇叭的位置和方向,以標準 ITU 設定環繞使用者。
根據預設,中央聲道喇叭會放在應用程式的 mainPanelEntity。包括 Android XR 自動空間化的行動應用程式。
如要使用立體聲,揚聲器擺放位置與環繞音效類似,但只有左右聲道分別位於面板的左右兩側。
如果你有多個面板,並想選擇要發出音訊的面板,或是想讓立體聲或環繞音訊相對於另一個 進行算繪,可以使用 PointSourceAttributes 定義中央聲道的所在位置。Entity其餘管道會如先前所述放置。在這些情況下,您也必須使用 MediaPlayer。
使用者在空間中移動時,立體聲和環繞音效虛擬音箱會隨之移動和調整,確保音箱始終處於最佳位置。
如果已設定 MediaPlayer 或 ExoPlayer 在背景繼續播放立體聲或環繞音效,應用程式進入背景時,虛擬揚聲器位置會改變。由於沒有面板或其他空間點可錨定聲音,空間音訊會隨著使用者移動 (也就是「頭部鎖定」)。
環場音效範例
以下範例會使用 MediaPlayer 載入 5.1 音訊檔案,並將檔案的中央聲道設為 Entity。
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) { // The session has spatial audio capabilities val pointSourceAttributes = PointSourceParams(session.scene.mainPanelEntity) val mediaPlayer = MediaPlayer() val fivePointOneAudio = appContext.assets.openFd("sounds/aac_51.ogg") mediaPlayer.reset() mediaPlayer.setDataSource(fivePointOneAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setPointSourceParams( session, mediaPlayer, pointSourceAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
程式碼相關重點
- 如同位置音訊範例,第一步是使用
spatialCapabilities檢查空間音訊功能是否可用。 - 將
contentType設為AudioAttributes.CONTENT_TYPE_MUSIC,並將使用情形設為AudioAttributes.USAGE_MEDIA,系統就會將這個音訊檔案視為環場音效。
在應用程式中新增 Ambisonic 音場
如要播放全景聲音場,最簡單的方法就是使用 MediaPlayer 載入檔案。由於全景聲適用於整個音場,因此您不需要指定 Entity 來提供位置。而是建立 SoundFieldAttributes 的執行個體,並指定適當的環繞音場階數和聲道數。
Ambionics 示例
以下範例使用 MediaPlayer 播放 Ambisonics 音場。
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) { // The session has spatial audio capabilities val soundFieldAttributes = SoundFieldAttributes(SpatializerConstants.AmbisonicsOrder.FIRST_ORDER) val mediaPlayer = MediaPlayer() val soundFieldAudio = appContext.assets.openFd("sounds/foa_basketball_16bit.wav") mediaPlayer.reset() mediaPlayer.setDataSource(soundFieldAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setSoundFieldAttributes( session, mediaPlayer, soundFieldAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
程式碼相關重點
- 與先前的程式碼片段相同,第一步是使用
hasCapability()檢查空間音訊功能是否可用。 contentType和使用方式僅供參考。AMBISONICS_ORDER_FIRST_ORDER會向 SceneCore 發出信號,表示音場檔案定義了四個聲道。