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 korzystają z obsługiwanego formatu 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ę 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 można było na nim 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 jego zachowanie podczas odtwarzania i typ treści.
Podczas wywoływania canBeSpatialized()
użyj tej samej instancji AudioAttributes
, która została 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ń do setIsContentSpatialized(true)
, aby nie przetwarzać dźwięku dwukrotnie. Możesz też zmienić zachowanie funkcji dźwięku przestrzennego, aby całkowicie ją wyłączyć, wywołując funkcję setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
.
AudioFormat
Obiekt AudioFormat
zawiera informacje o formacie i konfiguracji kanałów ś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 ruchów głowy, zadzwoń pod numer Spatializer.addOnHeadTrackerAvailableListener()
.
Może to być przydatne, jeśli chcesz dostosować wybór utworu podczas odtwarzania, używając 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 utworów 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 treści zawierają ś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 tym, jak dostosować to zachowanie, 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 pasuje do właściwości procesora dźwięku przestrzennego urządzenia. Zamiast tego możesz dostosować logikę wyboru ścieżki ExoPlayera, ustawiając parametry wyboru ścieżki przed odtworzeniem 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ą funkcji 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 przestrzenne na 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ć PCM wielokanałowy, który platforma przetworzy na dźwięk przestrzenny.
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 tego, czy producent OEM wprowadził jakieś zmiany, 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 te kanały:AudioFormat.CHANNEL_OUT_QUAD
(przedni lewy, przedni prawy, tylny lewy i tylny prawy), aby dźwięk mógł zostać przestrzennie zobrazowany. W przykładzie poniżej użyliśmyAudioFormat.CHANNEL_OUT_5POINT1
do ścieżki audio 5.1. 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 w wyniku powinny się pojawiać te parametry:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)