Dźwięk przestrzenny to niezwykłe doznania dźwiękowe, które przenoszą użytkowników w sam środek akcji i zapewniają większy realizm. „Uprzestrzennienie” dźwięku pozwala uzyskać efekt wielu głośników (podobny do konfiguracji dźwięku przestrzennego), ale zamiast głośników wykorzystuje słuchawki.
Na przykład w filmie dźwięk samochodu może zaczynać się za użytkownikiem, przesuwać do przodu i zanikać w oddali. Podczas czatu wideo głosy mogą być rozdzielone i umieszczone wokół użytkownika, co ułatwia identyfikację rozmówców.
Jeśli Twoje treści są w obsługiwanym formacie audio, możesz dodać dźwięk przestrzenny do aplikacji od Androida w wersji 13 (poziom API 33).
Zapytanie o możliwości
Użyj klasy Spatializer
, aby zapytać o możliwości i zachowanie lokalizacji przestrzennej urządzenia. Najpierw pobierz instancję funkcji Spatializer
z poziomu bazy danych AudioManager
:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
Po uzyskaniu Spatializer
sprawdź, czy urządzenie spełnia 4 kryteria, które muszą być spełnione, aby mogło odtwarzać dźwięk przestrzenny:
Kryteria | Sprawdź |
---|---|
Czy urządzenie obsługuje lokalizację przestrzenną? |
getImmersiveAudioLevel() nie jest SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
Czy dostępna jest lokalizacja przestrzenna? Dostępność zależy od zgodności z bieżącym kierowaniem wyjścia audio. |
isAvailable() to true |
Czy przestrzenność jest włączona? | isEnabled() to true |
Czy ścieżka audio z podanymi parametrami może zostać zmapowana przestrzennie? | canBeSpatialized() to true |
Te warunki mogą nie być spełnione, na przykład jeśli przestrzenność jest niedostępna dla bieżącej ścieżki audio lub jest całkowicie wyłączona na urządzeniu wyjściowym.
Monitorowanie ruchów głowy
W przypadku obsługiwanych słuchawek platforma może dostosować przestrzenność dźwięku na podstawie pozycji głowy użytkownika. Aby sprawdzić, czy urządzenie do śledzenia ruchów głowy jest dostępne dla bieżącego przekierowywania wyjścia audio, zadzwoń pod numer isHeadTrackerAvailable()
.
Zgodne treści
Spatializer.canBeSpatialized()
wskazuje, czy dźwięk z danymi właściwościami może być przestrzenny przy użyciu bieżącego przekierowywania urządzenia wyjściowego. Ta metoda przyjmuje argumenty AudioAttributes
i AudioFormat
, które są opisane bardziej szczegółowo poniżej.
AudioAttributes
Obiekt AudioAttributes
opisuje użytkowanie strumienia audio (np. dźwięk z gry lub standardowe media), a także odtwarzanie i typ treści.
Podczas wywoływania canBeSpatialized()
użyj tej samej instancji AudioAttributes
, która jest skonfigurowana dla Player
. Jeśli na przykład używasz biblioteki Jetpack Media3 i nie dostosowujesz wartości AudioAttributes
, użyj wartości AudioAttributes.DEFAULT
.
Wyłączanie dźwięku przestrzennego
Aby wskazać, że Twoje treści zostały już zmapowane przestrzennie, zadzwoń na numer setIsContentSpatialized(true)
, aby nie przetwarzać dźwięku dwukrotnie. Możesz też zmienić zachowanie funkcji lokalizowania dźwięku, aby całkowicie wyłączyć tę funkcję, wywołując funkcję setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
.
AudioFormat
Obiekt AudioFormat
zawiera informacje o formacie i konfiguracji kanału ścieżki audio.
Podczas tworzenia instancji AudioFormat
, która ma być przekazana do canBeSpatialized()
, ustaw kodowanie na takie samo jak format wyjściowy oczekiwany od dekodera. Musisz też ustawić maskę kanału, która odpowiada konfiguracji kanału Twoich treści. Więcej informacji o używanych wartościach znajdziesz w sekcji Domyślne zachowanie przestrzenne.
Sprawdź, czy w pliku Spatializer
zaszły jakieś zmiany
Aby nasłuchiwać zmian w stanie Spatializer
, możesz dodać słuchacza za pomocą Spatializer.addOnSpatializerStateChangedListener()
.
Aby nasłuchiwać zmiany dostępności lokalizatora głowy, zadzwoń pod numer Spatializer.addOnHeadTrackerAvailableListener()
.
Może to być przydatne, jeśli chcesz dostosować wybór utworu podczas odtwarzania za pomocą wywołań zwrotnych listenera. Gdy na przykład użytkownik podłącza lub odłącza zestaw słuchawkowy od urządzenia, wywołanie onSpatializerAvailableChanged
wskazuje, czy efekt przestrzenny jest dostępny dla nowego routingu wyjścia audio. W tym momencie możesz rozważyć zaktualizowanie logiki wyboru ścieżki przez odtwarzacz, aby dopasować ją do nowych możliwości urządzenia. Szczegółowe informacje o zachowaniu ExoPlayera podczas wybierania ścieżek znajdziesz w sekcji ExoPlayer i dźwięk przestrzenny.
ExoPlayer i dźwięk przestrzenny
Najnowsze wersje ExoPlayer ułatwiają stosowanie dźwięku przestrzennego. Jeśli używasz samodzielnej biblioteki ExoPlayer (nazwa pakietu com.google.android.exoplayer2
), wersja 2.17 konfiguruje platformę do generowania dźwięku przestrzennego, a wersja 2.18 wprowadza ograniczenia liczby kanałów audio.
Jeśli używasz modułu ExoPlayer z biblioteki Media3 (nazwa pakietu androidx.media3
), wersje 1.0.0-beta01
i nowsze zawierają te same aktualizacje.
Po zaktualizowaniu zależności ExoPlayer do najnowszej wersji aplikacja musi zawierać treści, które można przestrzennie zlokalizować.
Ograniczenia dotyczące liczby kanałów audio
Gdy spełnione są wszystkie 4 warunki dotyczące dźwięku przestrzennego, ExoPlayer wybiera ścieżkę audio wielokanałową. W przeciwnym razie ExoPlayer wybierze ścieżkę stereo.
Jeśli właściwości Spatializer
ulegną zmianie, ExoPlayer wywoła nowy wybór ścieżki, aby wybrać ścieżkę audio odpowiadającą bieżącym właściwościom. Pamiętaj, że wybór nowego utworu może spowodować krótkie przeładowanie.
Aby wyłączyć ograniczenia dotyczące liczby kanałów audio, ustaw parametry wyboru ścieżki w odtwarzaczu w ten sposób:
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
Podobnie możesz zaktualizować parametry dotychczasowego selektora utworów, aby wyłączyć ograniczenia dotyczące liczby kanałów audio:
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() );
Jeśli ograniczenie liczby kanałów audio jest wyłączone, a treści zawierają wiele ścieżek audio, ExoPlayer początkowo wybiera ścieżkę, która ma największą liczbę kanałów i można ją odtworzyć na urządzeniu. Jeśli na przykład materiał zawiera ścieżkę audio wielokanałową i ścieżkę audio stereo, a urządzenie obsługuje odtwarzanie obu, ExoPlayer wybierze ścieżkę wielokanałową. Więcej informacji o sposobie dostosowania tego działania znajdziesz w sekcji Wybór ścieżki audio.
Wybór ścieżki audio
Gdy zachowanie ograniczeń liczby kanałów audio w ExoPlayerze jest wyłączone, ExoPlayer nie wybiera automatycznie ścieżki audio, która odpowiada właściwościom procesora dźwięku przestrzennego urządzenia. Zamiast tego możesz dostosować logikę wyboru ścieżki ExoPlayera, ustawiając parametry wyboru ścieżki przed odtwarzaniem lub podczas odtwarzania. Domyślnie ExoPlayer wybiera ścieżki audio, które są takie same jak ścieżka początkowa pod względem typu MIME (kodowania), liczby kanałów i częstotliwości próbkowania.
Zmiana parametrów wyboru utworu
Aby zmienić parametry wyboru utworu w ExoPlayerze, użyj metody Player.setTrackSelectionParameters()
.
Możesz też uzyskać bieżące parametry ExoPlayera za pomocą Player.getTrackSelectionParameters()
.
Aby na przykład wybrać ścieżkę audio stereo w trakcie odtwarzania:
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
Pamiętaj, że zmiana parametrów wyboru ścieżki w trakcie odtwarzania może spowodować przerwanie odtwarzania. Więcej informacji o dostosowywaniu parametrów wyboru utworów przez odtwarzacz znajdziesz w sekcji wyboru utworów w dokumentach ExoPlayer.
Domyślne zachowanie przestrzenne
Domyślne zachowanie lokalizacji w Androidzie obejmuje te zachowania, które mogą być dostosowywane przez producentów OEM:
Stereofonicznie są kodowane tylko treści wielokanałowe, a nie stereo. Jeśli nie używasz ExoPlayera, w zależności od formatu treści audio wielokanałowych może być konieczne skonfigurowanie maksymalnej liczby kanałów, które dekoder audio może wygenerować. Dzięki temu dekoder audio może wygenerować wielokanałowy PCM, który platforma wykorzysta do przetwarzania przestrzennego.
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);
Przykład działania znajdziesz w
MediaCodecAudioRenderer.java
ExoPlayera. Aby wyłączyć dźwięk przestrzenny, niezależnie od personalizacji OEM, zapoznaj się z artykułem Wyłączanie dźwięku przestrzennego.AudioAttributes
: dźwięk można przestrzennie zmapować, jeśli parametrusage
jest ustawiony naUSAGE_MEDIA
lubUSAGE_GAME
.AudioFormat
: użyj maski kanału, która zawiera co najmniej kanałyAudioFormat.CHANNEL_OUT_QUAD
lewej, prawej, tylnej lewej i tylnej prawej, aby dźwięk mógł zostać zmapowany przestrzennie. W przykładzie poniżej ścieżka audio 5.1 jest oznaczona jakoAudioFormat.CHANNEL_OUT_5POINT1
. W przypadku ścieżki audio stereo użyjAudioFormat.CHANNEL_OUT_STEREO
.Jeśli używasz Media3, możesz użyć funkcji
Util.getAudioTrackChannelConfig(int channelCount)
, aby przekształcić liczbę kanałów w maskę kanału.Jeśli dekoder jest skonfigurowany tak, aby generować PCM wielokanałowy, ustaw kodowanie na
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();
Testowanie dźwięku przestrzennego
Sprawdź, czy dźwięk przestrzenny jest włączony na urządzeniu testowym:
- W przypadku zestawów słuchawkowych przewodowych wybierz Ustawienia systemowe > Dźwięk i wibracje > Dźwięk przestrzenny.
- W przypadku słuchawek bezprzewodowych kliknij Ustawienia systemowe > Połączone urządzenia > Ikona koła zębatego dla urządzenia bezprzewodowego > Dźwięk przestrzenny.
Aby sprawdzić dostępność dźwięku przestrzennego dla bieżącego routingu, uruchom na urządzeniu polecenie adb shell dumpsys audio
. Podczas odtwarzania powinny się wyświetlać te parametry:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)