Dźwięk przestrzenny to realistyczne doznania dźwiękowe, na podstawie których użytkownicy mogą znaleźć się w centrum akcji. Dźwięk jest „przestrzenny” w celu utworzenia efektu wielu głośników, podobnie jak w przypadku dźwięku przestrzennego, ale przez słuchawki.
Na przykład w filmie dźwięk samochodu może rozpoczynać się z tyłu, przesuwać się do przodu i w oddali. W trakcie czatu wideo głosy można rozdzielić i rozmieścić wokół użytkownika, co ułatwia rozpoznanie mówiących osób.
Jeśli Twoje treści zawierają obsługiwany format audio, na Androidzie 13 (poziom interfejsu API 33) możesz dodać dźwięk przestrzenny do swojej aplikacji.
Zapytanie o możliwości
Użyj klasy Spatializer
, aby przesłać zapytanie o możliwości i działanie urządzenia w zakresie przestrzennym. Zacznij od pobrania instancji Spatializer
z AudioManager
:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
Po otrzymaniu uprawnienia Spatializer
sprawdź, czy spełnione są 4 warunki, które muszą zostać spełnione, aby urządzenie mogło odtwarzać dźwięk przestrzenny:
Kryteria | Sprawdź |
---|---|
Czy urządzenie obsługuje przestrzenność? |
getImmersiveAudioLevel() nie ma wartości SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
Czy jest dostępna przestrzenność? Dostępność zależy od zgodności z aktualnym kierowaniem wyjścia audio. |
isAvailable() : true |
Czy przestrzenność jest włączona? | isEnabled() : true |
Czy ścieżka audio z podanymi parametrami może być przestrzenna? | canBeSpatialized() : true |
Te warunki mogą nie być spełnione, np. gdy funkcja przestrzenna jest niedostępna w przypadku bieżącej ścieżki audio lub całkowicie wyłączona na urządzeniu wyjściowym audio.
Monitorowanie ruchów głowy
W przypadku obsługiwanych zestawów słuchawkowych platforma może dostosować przestrzenność dźwięku w zależności od pozycji głowy użytkownika. Aby sprawdzić, czy urządzenie śledzące jest dostępne na potrzeby bieżącego kierowania dźwięku, wywołaj isHeadTrackerAvailable()
.
Zgodne treści
Spatializer.canBeSpatialized()
wskazuje, czy dźwięk o podanych właściwościach można przekształcić w przestrzenne za pomocą bieżącego routingu urządzenia wyjściowego. Ta metoda wymaga znaczników AudioAttributes
i AudioFormat
. Oba zostały opisane bardziej szczegółowo poniżej.
AudioAttributes
Obiekt AudioAttributes
opisuje użycie strumienia audio (np. dźwięk z gry lub standardowe multimedia), wraz z jego sposobem odtwarzania i typem treści.
Wywołując canBeSpatialized()
, użyj instancji AudioAttributes
ustawionej dla Player
. Jeśli np. korzystasz z biblioteki Jetpack Media3 i nie dostosowałeś AudioAttributes
, użyj właściwości AudioAttributes.DEFAULT
.
Wyłączanie dźwięku przestrzennego
Aby wskazać, że treści zostały już przestrzenne, wywołaj metodę setIsContentSpatialized(true)
. Dzięki temu dźwięk nie zostanie przetworzony podwójnie. Możesz też dostosować działanie przestrzenne, aby całkowicie wyłączyć przestrzenność, wywołując metodę setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
.
AudioFormat
Obiekt AudioFormat
zawiera szczegółowe informacje o formacie i konfiguracji kanału ścieżki audio.
Tworząc instancję AudioFormat
, która ma być przekazywana do canBeSpatialized()
, ustaw kodowanie na taki sam format wyjściowy, jaki oczekuje dekoder. Ustaw też maską kanału, która pasuje do konfiguracji kanału, w którym znajdują się Twoje treści. Wskazówki dotyczące konkretnych wartości znajdziesz w sekcji Domyślne zachowanie przestrzenne.
Wypatruj zmian w dokumencie Spatializer
Aby nasłuchiwać zmian stanu elementu Spatializer
, możesz dodać odbiornik za pomocą funkcji Spatializer.addOnSpatializerStateChangedListener()
.
Aby nasłuchiwać zmian w dostępności trackera, wywołaj metodę Spatializer.addOnHeadTrackerAvailableListener()
.
Jest to przydatne, gdy chcesz zmienić wybór ścieżek podczas odtwarzania, korzystając z wywołań zwrotnych słuchaczy. Jeśli na przykład użytkownik połączy lub odłączy zestaw słuchawkowy od urządzenia, wywołanie zwrotne onSpatializerAvailableChanged
wskazuje, czy efekt przestrzenny jest dostępny w przypadku nowego kierowania dźwięku. W tym momencie możesz rozważyć zaktualizowanie logiki wyboru ścieżki odtwarzacza, aby dopasować ją do nowych funkcji urządzenia. Szczegółowe informacje o sposobie wyboru ścieżki odtwarzacza ExoPlayer znajdziesz w sekcji ExoPlayer i dźwięk przestrzenny.
ExoPlayer i dźwięk przestrzenny
Najnowsze wersje ExoPlayer ułatwiają korzystanie z dźwięku przestrzennego. Jeśli używasz samodzielnej biblioteki ExoPlayer (nazwa pakietu com.google.android.exoplayer2
), wersja 2.17 konfiguruje platformę do odtwarzania 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.
Gdy zaktualizujesz zależność ExoPlayer do najnowszej wersji, aplikacja musi po prostu zawierać treści, które można wyskalować w sposób przestrzenny.
Ograniczenia liczby kanałów audio
Gdy zostaną spełnione wszystkie 4 warunki dźwięku przestrzennego, ExoPlayer wybierze wielokanałową ścieżkę audio. W przeciwnym razie ExoPlayer wybiera ścieżkę stereo.
Jeśli właściwości Spatializer
zmienią się, ExoPlayer uruchomi nowy wybór ścieżki, aby wybrać ścieżkę dźwiękową, która odpowiada bieżącym właściwościom. Pamiętaj, że nowy wybór ścieżki może spowodować krótki okres ponownego buforowania.
Aby wyłączyć ograniczenia liczby kanałów audio, ustaw parametry wyboru ścieżki w odtwarzaczu w następujący sposób:
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
Aby w ten sposób wyłączyć ograniczenia liczby kanałów audio, możesz w podobny sposób zaktualizować dotychczasowe parametry selektora ścieżek:
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, ExoPlayer początkowo wybiera ścieżkę z największą liczbą kanałów, którą można odtworzyć na urządzeniu, jeśli dany materiał zawiera wiele ścieżek audio. Jeśli na przykład materiał zawiera wielokanałową i stereofoniczną ścieżkę audio, a urządzenie obsługuje odtwarzanie obu, ExoPlayer wybiera ścieżkę wielokanałową. Aby dowiedzieć się, jak dostosować to działanie, przeczytaj sekcję Wybór ścieżki audio.
Wybór ścieżki audio
Gdy ograniczenie liczby kanałów audio w narzędziu ExoPlayer jest wyłączone, nie wybiera on automatycznie ścieżki audio, która odpowiada właściwościom komponentu przestrzennego urządzenia. Zamiast tego możesz dostosować logikę wyboru utworu przez ExoPlayera, ustawiając parametry wyboru przed odtworzeniem lub w trakcie 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 ExoPlayer, użyj Player.setTrackSelectionParameters()
.
Bieżące parametry ExoPlayera możesz też uzyskać za pomocą narzędzia Player.getTrackSelectionParameters()
.
Aby na przykład wybrać stereofoniczną ścieżkę dźwiękową 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 utworu w trakcie odtwarzania może zakłócić odtwarzanie. Więcej informacji o dostosowywaniu parametrów wyboru ścieżki odtwarzacza znajdziesz w sekcji wybór ścieżki w dokumentacji ExoPlayer.
Domyślne zachowanie przestrzenne
Domyślne zachowanie przestrzenne w Androidzie obejmuje te zachowania, które mogą być dostosowywane przez producentów OEM:
Tylko treści wielokanałowe są przestrzenne, a nie stereo. Jeśli nie używasz ExoPlayer, to w zależności od formatu wielokanałowych treści audio może być konieczne skonfigurowanie maksymalnej liczby kanałów, które mogą być przesyłane przez dekoder audio dla dużej liczby kanałów. Dzięki temu dekoder dźwięku generuje wielokanałowy format PCM, aby platforma mogła wykorzystać go w przestrzeni.
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 znajdziesz w dokumentacji ExoPlayer (
MediaCodecAudioRenderer.java
). Aby samodzielnie wyłączyć stosowanie dźwięku przestrzennego, niezależnie od dostosowania OEM, przeczytaj artykuł Wyłączanie dźwięku przestrzennego.AudioAttributes
: dźwięk kwalifikuje się do przestrzennego ustawienia, jeśli elementusage
ma wartośćUSAGE_MEDIA
lubUSAGE_GAME
.AudioFormat
: użyj maski kanału, która zawiera co najmniejAudioFormat.CHANNEL_OUT_QUAD
kanałów (przedni lewy, przedni prawy, tylny lewy i tylny prawy), aby dźwięk kwalifikował się do przestrzennego zastosowania. W poniższym przykładzie używamyAudioFormat.CHANNEL_OUT_5POINT1
w przypadku ścieżki audio 5.1. W przypadku ścieżki stereo użyjAudioFormat.CHANNEL_OUT_STEREO
.Jeśli korzystasz z Media3, możesz za pomocą narzędzia
Util.getAudioTrackChannelConfig(int channelCount)
przekonwertować liczbę kanałów na maskę kanału.Dodatkowo ustaw kodowanie na
AudioFormat.ENCODING_PCM_16BIT
, jeśli dekoder został skonfigurowany do odtwarzania wielokanałowego PCM.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();
Przetestuj dźwięk przestrzenny
Sprawdź, czy na urządzeniu testowym włączony jest dźwięk przestrzenny:
- W przypadku przewodowych zestawów słuchawkowych otwórz Ustawienia systemu > Dźwięk i wibracje > Dźwięk przestrzenny.
- W przypadku bezprzewodowych zestawów słuchawkowych kliknij Ustawienia systemu > Połączone urządzenia > Ikona koła zębatego 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
. Gdy odtwarzanie jest aktywne, w danych wyjściowych powinny być widoczne te parametry:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)