Dźwięk przestrzenny

Dźwięk przestrzenny to niezwykłe doznania dźwiękowe, które zapierają dech w piersiach jest w centrum akcji, dzięki czemu filmy brzmią bardziej realistycznie. Dźwięk jest „przestrzenny” aby uzyskać efekt wielu głośników, podobny do dźwięku przestrzennego konfiguracji, ale przez 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. Na czacie wideo głosy mogą być są rozdzielone i rozmieszczone wokół użytkownika, co ułatwia rozpoznanie osób mówiących.

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ę Spatializer z poziomu bazy danych AudioManager:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Po otrzymaniu Spatializer sprawdź, czy spełnione są 4 warunki true (prawda) dla urządzenia do odtwarzania dźwięku przestrzennego:

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żkę audio z podanymi parametrami można zastosować w przestrzeni przestrzennej? 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 tracker jest dla bieżącego kierowania wyjścia audio, wywołanie 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 AudioAttributesAudioFormat, 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 jest skonfigurowana dla Player. Na przykład, jeśli używasz biblioteki Jetpack Media3 i nie dostosowano AudioAttributes, użyj AudioAttributes.DEFAULT.

Wyłączanie dźwięku przestrzennego

Aby wskazać, że treść została już przestrzenna, użyj wywołania setIsContentSpatialized(true) aby dźwięk nie został przetworzony podwójnie. 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 opisuje dane dotyczące formatu i konfiguracji kanału ścieżki audio.

Podczas tworzenia instancji AudioFormat, którą chcesz przekazać 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. Zapoznaj się z W sekcji Domyślne zachowanie przestrzenne znajdziesz wskazówki na temat konkretne wartości.

Wykrywaj zmiany w: Spatializer

Aby nasłuchiwać zmian w stanie Spatializer, możesz dodać słuchacza za pomocą Spatializer.addOnSpatializerStateChangedListener(). Aby nasłuchiwać zmian w 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. Na przykład, gdy użytkownik łączy lub rozłącza swoje zestawu słuchawkowego z urządzenia onSpatializerAvailableChanged wywołanie zwrotne wskazuje, czy efekt przestrzenny jest dostępny dla nowych kierowania wyjścia audio. W tym momencie możesz rozważyć zaktualizowanie śledzić logikę wyboru pod kątem nowych możliwości urządzenia. Więcej informacji: Sposób wyboru ścieżek przez ExoPlayer 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 samodzielna biblioteka ExoPlayer (nazwa pakietu com.google.android.exoplayer2), wersja 2.17 konfiguruje platformę tak, aby wydawała dźwięk przestrzenny, 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 nowszych 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 wybiera ścieżkę stereo. Jeśli właściwości Spatializer ulegną zmianie, ExoPlayer uruchamia wybór nowej ścieżki audio, która pasuje do obecne właściwości. Pamiętaj, że wybór nowego utworu może spowodować krótką przez okres ponownego buforowania.

Aby wyłączyć ograniczenia liczby kanałów audio, ustaw parametry wyboru ścieżki w odtwarzaczu, jak pokazano poniżej:

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ą wielokanałową i stereofoniczną ścieżkę audio, a urządzenie obsługuje jednocześnie, ExoPlayer wybierze ścieżkę wielokanałową. Zobacz Wybór ścieżki dźwiękowej – szczegółowe informacje o tym, jak dostosować to działanie.

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 odtwarzaniem lub podczas odtwarzania. Domyślnie ExoPlayer wybiera dźwięk ścieżki, które są takie same jak ścieżka początkowa pod względem typu MIME. (kodowanie), liczbę kanałów i częstotliwość próbkowania.

Zmiana parametrów wyboru utworu

Aby zmienić parametry wyboru ścieżki w odtwarzaczu ExoPlayer, użyj funkcji Player.setTrackSelectionParameters() Bieżące parametry ExoPlayer można też uzyskać za pomocą parametru 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 przestrzeni

Domyślne zachowanie przestrzenne 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 ExoPlayer, w zależności od formatu Twojego wielokanałowego treści audio, może być konieczne skonfigurowanie maksymalnej liczby kanałów które mogą być wysyłane przez dekoder audio na dużą liczbę. 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 przewodniku firmy ExoPlayer MediaCodecAudioRenderer.java. Aby samodzielnie wyłączyć przestrzennie, niezależnie od producenta OEM Więcej informacji znajdziesz w sekcji o wyłączaniu dźwięku przestrzennego.

  • AudioAttributes: dźwięk kwalifikuje się do przekształcenia przestrzennego jeśli usage jest ustawiona na USAGE_MEDIA lub USAGE_GAME.

  • AudioFormat: użyj maski kanału, która zawiera co najmniej AudioFormat.CHANNEL_OUT_QUAD (przedni lewy, przedni prawy, tylny lewy i tylny prawy) i nie mogą być wykorzystywane w przestrzeni. W poniższym przykładzie używamy wyrażenia AudioFormat.CHANNEL_OUT_5POINT1 w przypadku ścieżki audio 5.1. W przypadku stereofonicznej ścieżki audio użyj AudioFormat.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.

    Dodatkowo ustaw kodowanie na AudioFormat.ENCODING_PCM_16BIT jeśli dekoder jest skonfigurowany tak, by wysyłał wielokanałowy 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();

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 adb shell dumpsys audio na urządzeniu. Strona powinna wyglądać tak: parametry w danych wyjściowych, gdy odtwarzanie jest aktywne:

Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)