Dodawanie dźwięku przestrzennego do aplikacji XR

Funkcje dźwięku przestrzennego w Jetpack SceneCore umożliwiają tworzenie immersyjnych doświadczeń 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. Tworzy on wrażenie dźwięku dochodzącego ze wszystkich kierunków, w tym z góry i z dołu. System robi to, symulując co najmniej 1 „wirtualnego głośnika” w określonych miejscach w przestrzeni 3D.

Dotychczasowe aplikacje, które nie zostały zaprojektowane ani zmodyfikowane pod kątem Androida XR, mają dźwięk automatycznie przestrzenny na Androidzie XR. Gdy użytkownik porusza się po pokoju, dźwięk z aplikacji będzie emitowany z panelu, na którym renderowany jest interfejs aplikacji. Jeśli na przykład minutnik w aplikacji zegar włączy się, dźwięk będzie wydawał się dobiegać z pozycji panelu aplikacji. Android XR automatycznie zmienia dźwięk, aby zapewnić realizm przestrzenny. Na przykład odległość między użytkownikiem a panelem aplikacji będzie subtelnie wpływać na głośność dźwięku, aby zwiększyć realizm.

Więcej informacji o tym, jak istniejące aplikacje renderują dźwięk przestrzenny, znajdziesz na tej stronie w sekcji Dodawanie dźwięku stereo i dźwięku przestrzennego do aplikacji.

Jeśli optymalizujesz aplikację pod kątem XR, Jetpack SceneCore udostępnia narzędzia do zaawansowanej personalizacji dźwięku przestrzennego. Możesz precyzyjnie umieszczać dźwięki w środowisku 3D, używać dźwięku ambisonicznego do realistycznych pól dźwiękowych i korzystać z wbudowanej integracji dźwięku przestrzennego.

Typy dźwięku przestrzennego dostępne w Androidzie XR

Android XR obsługuje dźwięk przestrzenny, stereofoniczny, przestrzenny i ambisoniowy.

Dźwięk przestrzenny

Dźwięk pozycyjny może być odtwarzany z określonego punktu w przestrzeni 3D. Możesz na przykład umieścić model 3D psa szczekającego w rogu swojego wirtualnego środowiska. Możesz mieć wiele obiektów emitujących dźwięk z poszczególnych pozycji. Aby renderować dźwięk przestrzenny, pliki muszą być mono lub stereo.

Stereo przestrzenne i dźwięk przestrzenny

Obsługiwane są wszystkie formaty multimediów na Androidzie w przypadku dźwięku przestrzennego, stereo i dźwięku przestrzennego.

Dźwięk stereo to formaty dźwięku z 2 kanałami, a dźwięk przestrzenny to formaty dźwięku z więcej niż 2 kanałami, takie jak konfiguracje dźwięku przestrzennego 5.1 lub dźwięku przestrzennego 7.1. Dane dźwiękowe każdego kanału są powiązane z jednym mówcą. Podczas odtwarzania muzyki w 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żenia dzięki zastosowaniu wielu kanałów głośników. Na przykład dialog często odtwarzany jest z kanału głośnika środkowego, podczas gdy dźwięk helikoptera może używać różnych kanałów kolejno, aby stworzyć wrażenie, że helikopter krąży wokół przestrzeni 3D.

Dźwięk ambisonicznym

Dźwięk ambisonic (lub ambisonics) to coś w rodzaju skyboxa dla dźwięku, który zapewnia użytkownikom wciągający dźwięk. Używaj ambisonicznego dźwięku do tworzenia dźwięków tła lub w innych sytuacjach, w których chcesz odtworzyć pełne dźwiękowe pole wokół słuchacza. Android XR obsługuje format dźwięku ambisonics AmbiX w pierwszym, drugim i trzecim porządku. Zalecamy typy plików Opus (.ogg) i PCM/Wave (.wav).

Korzystanie z dźwięku przestrzennego w Jetpacku SceneCore

Wdrożenie dźwięku przestrzennego za pomocą Jetpacka SceneCore wymaga sprawdzenia możliwości przestrzennych i wybrania interfejsu API do wczytywania dźwięku przestrzennego.

Sprawdzanie możliwości przestrzennych

Zanim zaczniesz korzystać z funkcji dźwięku przestrzennego, sprawdź, czy Session obsługuje dźwięk przestrzenny. We wszystkich fragmentach kodu w następnych sekcjach przed odtworzeniem dźwięku przestrzennego sprawdzane są możliwości.

Wczytywanie dźwięku przestrzennego

Aby załadować dźwięk przestrzenny do użycia w Jetpacku SceneCore, możesz użyć dowolnego z tych interfejsów API.

  • SoundPool: idealne rozwiązanie do krótkich efektów dźwiękowych o rozmiarze poniżej 1 MB. Są one wczytywane z wyprzedzeniem i można ich używać wielokrotnie. To świetny sposób na wczytywanie dźwięku dla dźwięku pozycyjnego.
  • ExoPlayer: idealny do wczytywania treści stereo i dźwięku przestrzennego, takich jak muzyka i filmy. Umożliwia też odtwarzanie multimediów w tle.
  • MediaPlayer: najprostszy sposób wczytywania dźwięku ambisonicznego.
  • AudioTrack: zapewnia największą kontrolę nad sposobem wczytywania danych audio. Umożliwia bezpośrednie zapisywanie buforów dźwięku lub zsyntetyzowanych lub odkodowanych własnych plików audio.

Dodawanie dźwięku zależnego od położenia do aplikacji

Pozycyjne źródła dźwięku są definiowane przez PointSourceParams i powiązane z nim Entity. Pozycja i orientacja Entityokreśla, gdzie PointSourceParams zostanie wyrenderowany w przestrzeni 3D.

Przykład dźwięku pozycjonowanego

W tym przykładzie wczytujemy plik audio z efektem dźwiękowym do puli dźwięków i odtwarzamy go w miejscu, w którym znajduje się Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities
    .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_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
}

Najważniejsze informacje o kodzie

  • Najpierw sprawdź, czy funkcje dźwięku przestrzennego są obecnie dostępne, korzystając z spatialCapabilities.
  • Ustawienie wartości contentType na CONTENT_TYPE_SONIFICATION i ustawienie wartości usage na USAGE_ASSISTANCE_SONIFICATION powoduje, że system będzie traktować ten plik audio jako efekt dźwiękowy.
  • W powyższym przykładzie plik audio jest wczytywany do puli bezpośrednio przed jego użyciem, aby utrzymać kod w jednym miejscu ze względów uproszczenia. Najlepiej jest wczytywać wszystkie efekty dźwiękowe asynchronicznie podczas wczytywania aplikacji, aby wszystkie pliki audio były dostępne w pulach, gdy ich potrzebujesz.

Dodawanie dźwięku stereo i przestrzennego do aplikacji

Zalecane jest dodawanie dźwięku stereo i dźwięku przestrzennego do aplikacji za pomocą Exoplayer. Więcej informacji o korzystaniu z dźwięku przestrzennego w przypadku Exoplayer znajdziesz w przewodniku po dźwięku przestrzennym.

Rozmieszczenie głośników stereo i głośników dźwięku przestrzennego

W przypadku dźwięku przestrzennego głośniki wirtualnego dźwięku przestrzennego są ustawione i zorientowane względem głośnika środkowego, wokół użytkownika w standardowej konfiguracji ITU.

Domyślnie głośnik kanału środkowego jest umieszczony na mainPanelEntity aplikacji. Dotyczy to aplikacji mobilnych, których dźwięk jest automatycznie przestrzenny dzięki Androidowi XR.

W przypadku dźwięku stereo rozmieszczenie głośników jest podobne do 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 chcesz, aby dźwięk stereo lub dźwięk przestrzenny był renderowany w odniesieniu do innego Entity, możesz użyć atrybutów [PointSourceAttributes][Atrybuty źródła punktu] do określenia położenia kanału środkowego. Pozostałe kanały zostaną umieszczone zgodnie z wcześniejszym opisem. W takich sytuacjach musisz też użyć MediaPlayer.

Gdy użytkownik porusza się po pomieszczeniu, wirtualne głośniki stereo i surround będą się przemieszczać i dostosowywać, aby zawsze znajdowały się w optymalnej pozycji.

Jeśli skonfigurujesz MediaPlayer lub ExoPlayer tak, aby nadal odtwarzać dźwięk stereo lub dźwięk przestrzenny w tle, po umieszczeniu aplikacji w tle zmieni się pozycjonowanie głośników wirtualnych. Ponieważ nie ma panelu ani innego punktu w przestrzeni, do którego można zakotwiczyć dźwięk, dźwięk przestrzenny porusza się wraz z użytkownikiem (czyli jest „zablokowany w głowie”).

Przykład dźwięku przestrzennego

W tym przykładzie wczytujemy plik audio 5.1 za pomocą funkcji MediaPlayer i ustawiamy kanał środkowy pliku jako Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_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
}

Najważniejsze informacje o kodzie

Dodawanie pól dźwięku ambisonic do aplikacji

Najprostszym sposobem odtwarzania ambisonicznego pola dźwięku jest załadowanie pliku za pomocą MediaPlayer. Ponieważ dźwięk ambisonic dotyczy całego krajobrazu dźwiękowego, nie musisz podawać wartości Entity, aby określić pozycję. Zamiast tego tworzysz instancję SoundFieldAttributes z odpowiednim porządkiem ambisonicznym, określając liczbę kanałów.

Przykład Ambionics

W tym przykładzie pole MediaPlayer odtwarza ambisoniczną ścieżkę dźwiękową.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AMBISONICS_ORDER_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ą obecnie dostępne, za pomocą funkcji [getSpatialCapabilities()][getSpatialCapabilities()].
  • Typ treści i sposób jej wykorzystania mają charakter wyłącznie informacyjny.
  • Wartość AMBISONICS_ORDER_FIRST_ORDER sygnalizuje SceneCore, że plik pola dźwiękowego definiuje 4 kanały.