Funkcje dźwięku przestrzennego w Jetpack SceneCore umożliwiają tworzenie wciągających wrażeń dźwiękowych w aplikacjach na Androida XR.
Dźwięk przestrzenny symuluje sposób, w jaki użytkownicy odbierają dźwięk w środowisku 3D. Daje to wrażenie, że dźwięk dochodzi ze wszystkich kierunków, w tym z góry i z dołu. System robi to, symulując co najmniej 1 „wirtualny głośnik” w określonych lokalizacjach w przestrzeni 3D.
Istniejące aplikacje, które nie zostały zaprojektowane ani zmodyfikowane pod kątem Androida XR, mają automatycznie przestrzennie odtwarzany dźwięk na Androidzie XR. Gdy użytkownik porusza się po swojej przestrzeni, cały dźwięk z aplikacji będzie emitowany z panelu, na którym renderowany jest interfejs aplikacji. Jeśli na przykład włączy się minutnik w aplikacji zegara, dźwięk będzie brzmiał tak, jakby pochodził z pozycji panelu aplikacji. Android XR automatycznie dostosuje dźwięk, aby zapewnić realistyczne pozycjonowanie. Na przykład postrzegana odległość między panelem aplikacji a użytkownikiem będzie subtelnie wpływać na głośność dźwięku, co zwiększy poczucie realizmu.
Więcej informacji o tym, jak istniejące aplikacje renderują dźwięk przestrzenny, znajdziesz w sekcji Dodawanie do aplikacji dźwięku stereo i przestrzennego na tej stronie.
Jeśli optymalizujesz aplikację pod kątem XR, Jetpack SceneCore udostępnia narzędzia do zaawansowanego dostosowywania dźwięku przestrzennego. Możesz precyzyjnie pozycjonować dźwięki w środowisku 3D, używać dźwięku ambisonicznego, aby uzyskać realistyczne pola dźwiękowe, i korzystać z wbudowanej integracji dźwięku przestrzennego.
Rodzaje dźwięku przestrzennego dostępne na Androidzie XR
Android XR obsługuje dźwięk pozycyjny, stereo, przestrzenny i ambisoniczny.
Dźwięk pozycyjny
Dźwięk pozycyjny można ustawić tak, aby był odtwarzany z określonego punktu w przestrzeni 3D. Możesz na przykład mieć model 3D psa szczekającego w rogu wirtualnego środowiska. Możesz mieć wiele elementów emitujących dźwięk z różnych pozycji. Aby można było odtworzyć dźwięk pozycyjny, pliki muszą być w formacie mono lub stereo.
Dźwięk stereo i przestrzenny
Wszystkie formaty multimediów na Androidzie są obsługiwane w przypadku dźwięku pozycyjnego, stereo i przestrzennego. Oprócz tych formatów urządzenia z Androidem XR mogą obsługiwać formaty audio Dolby Atmos, Dolby Digital i Dolby Digital+.
Dźwięk stereo to formaty audio z 2 kanałami, a dźwięk przestrzenny to formaty audio z więcej niż 2 kanałami, np. konfiguracje dźwięku przestrzennego 5.1 lub 7.1. Dane dźwiękowe każdego kanału są powiązane z jednym głośnikiem. Na przykład podczas odtwarzania muzyki w trybie stereo lewy kanał głośnika może emitować inne ścieżki instrumentów niż prawy.
Dźwięk przestrzenny jest często używany w filmach i programach telewizyjnych, aby zwiększyć realizm i wrażenie zanurzenia dzięki wykorzystaniu wielu kanałów głośnikowych. Na przykład dialogi są często odtwarzane z kanału głośnika centralnego, a dźwięk lecącego helikoptera może być odtwarzany z różnych kanałów po kolei, aby sprawić wrażenie, że helikopter lata w przestrzeni 3D.
Dźwięk ambisoniczny
Dźwięk ambisoniczny (lub ambisonika) jest jak skybox dla dźwięku, zapewniając użytkownikom realistyczne wrażenia dźwiękowe. Używaj ambisonii w przypadku dźwięków otoczenia w tle lub w innych sytuacjach, gdy chcesz odtworzyć pełne sferyczne pole dźwiękowe, które otacza słuchacza. Android XR obsługuje format dźwięku ambisonicznego AmbiX w ambisonice pierwszego, drugiego i trzeciego rzędu. Zalecamy typy plików Opus (.ogg) i PCM/Wave (.wav).
Używanie dźwięku przestrzennego z Jetpack SceneCore
Implementacja dźwięku przestrzennego za pomocą Jetpack SceneCore obejmuje sprawdzenie możliwości przestrzennych i wybranie interfejsu API do wczytywania dźwięku przestrzennego.
Sprawdzanie funkcji przestrzennych
Zanim użyjesz funkcji dźwięku przestrzennego, sprawdź, czy Session obsługuje dźwięk przestrzenny. We wszystkich fragmentach kodu w poniższych sekcjach możliwości są sprawdzane przed próbą odtworzenia dźwięku przestrzennego.
Wczytaj dźwięk przestrzenny
Aby wczytać dźwięk przestrzenny do użycia w Jetpack SceneCore, możesz użyć dowolnego z tych interfejsów API.
SoundPool: idealne do krótkich efektów dźwiękowych o rozmiarze mniejszym niż 1 MB. Są ładowane z wyprzedzeniem i mogą być używane wielokrotnie. To świetny sposób na wczytywanie dźwięku na potrzeby dźwięku pozycyjnego.ExoPlayer: idealny do przesyłania treści z dźwiękiem stereo i przestrzennym, takich jak muzyka i filmy. Umożliwia też odtwarzanie multimediów w tle.MediaPlayer: najprostszy sposób na wczytanie dźwięku ambisonicznego.AudioTrack: zapewnia największą kontrolę nad sposobem wczytywania danych audio. Umożliwia bezpośrednie zapisywanie buforów audio lub syntezowanie bądź dekodowanie własnych plików audio.
Sprawdzanie obsługi formatu multimediów
Niektóre formaty multimediów są obsługiwane przez platformę Androida. Jednak konkretne urządzenie z Androidem XR może obsługiwać dodatkowe formaty, takie jak Dolby Atmos. Aby sprawdzić obsługę formatu multimediów, użyj AudioCapabilities ExoPlayera:
val audioCapabilities = AudioCapabilities.getCapabilities( context, androidx.media3.common.AudioAttributes.DEFAULT, null, emptyList() ) 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. }
Sprawdzanie tych funkcji może potencjalnie wiązać się z blokowaniem wywołań i nie powinno być wywoływane w głównym wątku.
Dodawanie dźwięku pozycyjnego do aplikacji
Źródła dźwięku pozycyjnego są definiowane przez PointSourceParams i powiązany element Entity. Pozycja i orientacja Entity określają, gdzie PointSourceParams jest renderowany w przestrzeni 3D. Wywołaj setPointSourceParams na SpatialMediaPlayer, aby ustawić PointSourceParams i powiązany z nim entity w instancji MediaPlayer.
Przykład dźwięku pozycyjnego
W poniższym przykładzie plik audio z efektem dźwiękowym jest wczytywany do puli dźwięków i odtwarzany w pozycji 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() 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, entity = entity, soundPool = soundPool, soundID = pointSoundId, params = pointSource, volume = maxVolume, priority = lowPriority, loop = infiniteLoop, rate = normalSpeed ) } } } else { // The session does not have spatial audio capabilities }
Najważniejsze informacje o kodzie
- Najpierw sprawdź, czy funkcje dźwięku przestrzennego są dostępne, używając
spatialCapabilities. - Ustawienie contentType na
CONTENT_TYPE_SONIFICATIONi usage naUSAGE_ASSISTANCE_SONIFICATIONpozwala systemowi traktować ten plik audio jako efekt dźwiękowy. - W poprzednim przykładzie plik audio jest wczytywany do puli bezpośrednio przed użyciem, aby kod był prostszy. Najlepiej jest wczytywać wszystkie efekty dźwiękowe asynchronicznie podczas wczytywania aplikacji, aby wszystkie pliki audio były dostępne w puli, gdy będą potrzebne.
Dodawanie dźwięku stereo i przestrzennego do aplikacji
Zalecanym sposobem dodawania dźwięku stereo i przestrzennego do aplikacji jest użycie Exoplayer. Więcej informacji o korzystaniu z dźwięku przestrzennego na urządzeniu Exoplayer znajdziesz w przewodniku po dźwięku przestrzennym.
Pozycjonowanie głośników stereo i dźwięku przestrzennego
W przypadku pozycjonowania głośników dźwięku przestrzennego wirtualne głośniki dźwięku przestrzennego są ustawione i zorientowane względem głośnika centralnego, wokół użytkownika, w standardowej konfiguracji ITU.
Domyślnie głośnik kanału centralnego jest umieszczony na mainPanelEntity aplikacji. Obejmuje to aplikacje mobilne, których dźwięk jest automatycznie przekształcany na przestrzenny przez Androida XR.
W przypadku dźwięku stereo rozmieszczenie głośników jest podobne jak w przypadku dźwięku przestrzennego, z tą różnicą, że kanały lewy i prawy są umieszczone odpowiednio po lewej i prawej stronie panelu.
Jeśli masz kilka paneli i chcesz wybrać, który z nich ma emitować dźwięk, lub jeśli chcesz, aby dźwięk stereo lub dźwięk przestrzenny był renderowany względem innego elementu Entity, możesz użyć PointSourceAttributes, aby określić lokalizację kanału centralnego. Pozostałe kanały zostaną umieszczone w sposób opisany powyżej. W takich sytuacjach musisz też użyć MediaPlayer.
Gdy użytkownik porusza się po pomieszczeniu, wirtualne głośniki stereo i głośniki dźwięku przestrzennego będą się przemieszczać i dostosowywać, aby zawsze znajdować się w optymalnej pozycji.
Jeśli skonfigurowano MediaPlayer lub ExoPlayer, aby kontynuować odtwarzanie dźwięku stereo lub przestrzennego w tle, po przełączeniu aplikacji w tło zmieni się pozycjonowanie wirtualnego głośnika. Ponieważ nie ma panelu ani innego punktu w przestrzeni, do którego można by zakotwiczyć dźwięk, dźwięk przestrzenny porusza się wraz z użytkownikiem (innymi słowy, jest „zablokowany na głowie”).
Przykład dźwięku przestrzennego
W tym przykładzie wczytujemy plik audio 5.1 za pomocą MediaPlayer i ustawiamy kanał centralny pliku jako 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() 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, entity = session.scene.mainPanelEntity, ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
Najważniejsze informacje o kodzie
- Podobnie jak w przykładzie z dźwiękiem pozycyjnym, pierwszym krokiem jest sprawdzenie, czy funkcje dźwięku przestrzennego są dostępne, za pomocą
spatialCapabilities. - Ustawienie
contentTypenaAudioAttributes.CONTENT_TYPE_MUSICi wykorzystania naAudioAttributes.USAGE_MEDIApozwala systemowi traktować ten plik audio jako dźwięk przestrzenny.
Dodawanie do aplikacji ambisonicznych pól dźwiękowych
Najprostszym sposobem odtwarzania ambisonicznych pól dźwiękowych jest wczytanie pliku za pomocą MediaPlayer. Dźwięk ambisoniczny dotyczy całej przestrzeni dźwiękowej, więc nie musisz określać elementu Entity, aby podać pozycję. Zamiast tego tworzysz instancję SoundFieldAttributes z odpowiednim rzędem ambisonicznym określającym liczbę kanałów.
Przykład Ambionics
W przykładzie poniżej odtwarzane jest ambisoniczne pole dźwiękowe za pomocą MediaPlayer.
// 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 }
Najważniejsze informacje o kodzie
- Podobnie jak w przypadku poprzednich fragmentów kodu, pierwszym krokiem jest sprawdzenie, czy funkcje dźwięku przestrzennego są dostępne, za pomocą
spatialCapabilities. contentTypei ich wykorzystanie mają charakter wyłącznie informacyjny.SpatializerConstants.AmbisonicsOrder.FIRST_ORDERinformuje SceneCore, że plik pola dźwiękowego definiuje 4 kanały.