Spatial Audio

Spatial Audio ist ein eindrucksvolles Audioerlebnis, das Nutzern das Gefühl vermittelt, als wären sie mitten im Geschehen, und Inhalte viel realistischer klingen lässt. Der von Pixel Buds Pro erzeugte räumliche Klang scheint dabei aus mehreren Lautsprechern zu kommen, ähnlich wie bei einem Surround-Soundsystem, aber über Kopfhörer.

In einem Film könnte der Ton eines Autos beispielsweise hinter dem Nutzer beginnen, sich nach vorne bewegen und in der Ferne verstommen. In einem Videochat können Stimmen voneinander getrennt und um den Nutzer herum platziert werden, damit die Sprecher leichter zu erkennen sind.

Wenn Sie für Ihre Inhalte ein unterstütztes Audioformat verwenden, können Sie Ihrer App ab Android 13 (API-Level 33) räumlichen Audio hinzufügen.

Funktionen abfragen

Verwenden Sie die Klasse Spatializer, um die Spatialisierungsfunktionen und das Verhalten des Geräts abzufragen. Rufen Sie zuerst eine Instanz der Spatializer aus der AudioManager ab:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Nachdem du die Spatializer erhalten hast, prüfe, ob die vier folgenden Bedingungen erfüllt sind, damit das Gerät räumliches Audio ausgeben kann:

Kriterien Prüfen
Unterstützt das Gerät die Spatial Audio-Funktion? getImmersiveAudioLevel() ist nicht SPATIALIZER_IMMERSIVE_LEVEL_NONE
Ist die Spatialisierung verfügbar?
 Die Verfügbarkeit hängt von der Kompatibilität mit der aktuellen Audioausgabe ab.
isAvailable() ist true
Ist die räumliche Darstellung aktiviert? isEnabled() ist true
Kann ein Audiotrack mit den angegebenen Parametern räumlich lokalisiert werden? canBeSpatialized() ist true

Diese Bedingungen sind möglicherweise nicht erfüllt, wenn die Spatialisierung beispielsweise für den aktuellen Audiotrack nicht verfügbar ist oder auf dem Audioausgabegerät vollständig deaktiviert ist.

Erfassung von Kopfbewegungen

Bei unterstützten Headsets kann die Plattform die Raumklangwiedergabe anhand der Kopfposition des Nutzers anpassen. Wenn Sie prüfen möchten, ob für die aktuelle Audioausgabe ein Kopf-Tracker verfügbar ist, rufen Sie isHeadTrackerAvailable() auf.

Kompatible Inhalte

Spatializer.canBeSpatialized() gibt an, ob Audio mit den angegebenen Eigenschaften mit der aktuellen Routing-Ausgabe für das Gerät räumlich lokalisiert werden kann. Diese Methode nimmt ein AudioAttributes und ein AudioFormat entgegen, die unten genauer beschrieben werden.

AudioAttributes

Ein AudioAttributes-Objekt beschreibt die Nutzung eines Audiostreams (z. B. Game Audio oder Standardmedien) sowie die Wiedergabeeigenschaften und den Inhaltstyp.

Verwende beim Aufrufen von canBeSpatialized() dieselbe AudioAttributes-Instanz wie für deine Player festgelegt. Wenn du beispielsweise die Jetpack Media3-Bibliothek verwendest und die AudioAttributes nicht angepasst hast, verwende AudioAttributes.DEFAULT.

Spatial Audio deaktivieren

Wenn du angeben möchtest, dass deine Inhalte bereits räumlich lokalisiert wurden, rufe setIsContentSpatialized(true) auf, damit das Audio nicht doppelt verarbeitet wird. Alternativ kannst du das Spatialisierungsverhalten anpassen, um die Spatialisierung vollständig zu deaktivieren. Rufe dazu setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER) auf.

AudioFormat

Ein AudioFormat-Objekt enthält Details zum Format und zur Kanalkonfiguration eines Audiotracks.

Wenn du AudioFormat instanzierst, um sie an canBeSpatialized() zu übergeben, muss die Codierung mit dem vom Decoder erwarteten Ausgabeformat übereinstimmen. Außerdem solltest du eine Kanalmaske festlegen, die der Kanalkonfiguration deiner Inhalte entspricht. Im Abschnitt Standardverhalten für die Spatialisierung findest du Informationen zu den zu verwendenden Werten.

Auf Änderungen an Spatializer achten

Wenn Sie auf Änderungen des Status von Spatializer reagieren möchten, können Sie einen Listener mit Spatializer.addOnSpatializerStateChangedListener() hinzufügen. Wenn Sie Änderungen an der Verfügbarkeit eines Kopf-Trackers beobachten möchten, rufen Sie Spatializer.addOnHeadTrackerAvailableListener() auf.

Das kann nützlich sein, wenn du die Titelauswahl während der Wiedergabe mithilfe der Callbacks des Listeners anpassen möchtest. Wenn ein Nutzer beispielsweise sein Headset mit dem Gerät verbindet oder trennt, gibt der onSpatializerAvailableChanged-Callback an, ob der Spatializer-Effekt für die neue Audioausgabe-Weiterleitung verfügbar ist. An dieser Stelle kannst du die Logik für die Titelauswahl deines Players an die neuen Funktionen des Geräts anpassen. Weitere Informationen zum Verhalten der Titelauswahl von ExoPlayer findest du im Abschnitt ExoPlayer und räumliches Audio.

ExoPlayer und Spatial Audio

Die neuesten Versionen von ExoPlayer erleichtern die Nutzung von Spatial Audio. Wenn du die eigenständige ExoPlayer-Bibliothek (Paketname com.google.android.exoplayer2) verwendest, wird die Plattform in Version 2.17 für die Ausgabe von räumlichem Audio konfiguriert. In Version 2.18 werden Einschränkungen für die Anzahl der Audiokanäle eingeführt. Wenn du das ExoPlayer-Modul aus der Media3-Bibliothek (Paketname androidx.media3) verwendest, sind diese Updates in den Versionen 1.0.0-beta01 und höher enthalten.

Nachdem du die ExoPlayer-Abhängigkeit auf die neueste Version aktualisiert hast, muss deine App nur noch Inhalte enthalten, die lokalisiert werden können.

Einschränkungen bei der Anzahl der Audiokanäle

Wenn alle vier Bedingungen für Spatial Audio erfüllt sind, wählt ExoPlayer einen Audiotrack mit mehreren Kanälen aus. Andernfalls wählt ExoPlayer stattdessen einen Stereotrack aus. Wenn sich die Spatializer-Properties ändern, löst ExoPlayer eine neue Titelauswahl aus, um einen Audiotrack auszuwählen, der den aktuellen Properties entspricht. Beachte, dass es bei der neuen Titelauswahl zu einer kurzen Pufferung kommen kann.

Wenn du die Einschränkungen bei der Anzahl der Audiokanäle deaktivieren möchtest, musst du die Parameter für die Titelauswahl im Player wie unten gezeigt festlegen:

Kotlin

exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context)
  .setConstrainAudioChannelCountToDeviceCapabilities(false)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  new DefaultTrackSelector.Parameters.Builder(context)
    .setConstrainAudioChannelCountToDeviceCapabilities(false)
    .build()
);

Ebenso kannst du die Parameter einer vorhandenen Titelauswahl aktualisieren, um Einschränkungen bei der Anzahl der Audiokanäle zu deaktivieren. Gehe dazu so vor:

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()
);

Wenn die Einschränkungen für die Anzahl der Audiokanäle deaktiviert sind und Inhalte mehrere Audiotracks haben, wählt ExoPlayer zuerst den Track mit der höchsten Anzahl von Kanälen aus, der auf dem Gerät wiedergegeben werden kann. Wenn der Inhalt beispielsweise einen Mehrkanal-Audiotrack und einen Stereo-Audiotrack enthält und das Gerät die Wiedergabe beider unterstützt, wählt ExoPlayer den Mehrkanal-Track aus. Weitere Informationen zum Anpassen dieses Verhaltens findest du unter Audiotrackauswahl.

Auswahl des Audiotracks

Wenn das Verhalten der Einschränkungen für die Anzahl der Audiokanäle von ExoPlayer deaktiviert ist, wählt ExoPlayer nicht automatisch einen Audiotrack aus, der den Eigenschaften des Spatializers des Geräts entspricht. Stattdessen kannst du die Logik der Titelauswahl von ExoPlayer anpassen, indem du vor oder während der Wiedergabe Parameter für die Titelauswahl festlegst. Standardmäßig wählt ExoPlayer Audiotracks aus, die mit dem ursprünglichen Track hinsichtlich MIME-Typ (Codierung), Kanalanzahl und Abtastrate übereinstimmen.

Parameter für die Titelauswahl ändern

Mit Player.setTrackSelectionParameters() kannst du die Parameter für die Titelauswahl von ExoPlayer ändern. Ebenso kannst du die aktuellen Parameter von ExoPlayer mit Player.getTrackSelectionParameters() abrufen. So wählst du beispielsweise während der Wiedergabe einen Stereo-Audiotrack aus:

Kotlin

exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters
  .buildUpon()
  .setMaxAudioChannelCount(2)
  .build()

Java

exoPlayer.setTrackSelectionParameters(
  exoPlayer.getTrackSelectionParameters()
    .buildUpon()
    .setMaxAudioChannelCount(2)
    .build()
);

Hinweis: Wenn Sie die Parameter für die Titelauswahl während der Wiedergabe ändern, kann es zu Unterbrechungen kommen. Weitere Informationen zum Optimieren der Parameter für die Titelauswahl des Players findest du im Abschnitt Titelauswahl der ExoPlayer-Dokumentation.

Standardverhalten bei der Spatialisierung

Das Standardverhalten der Spatialisierung unter Android umfasst die folgenden Funktionen, die von OEMs angepasst werden können:

  • Nur Mehrkanalinhalte werden räumlich dargestellt, keine Stereoinhalte. Wenn du ExoPlayer nicht verwendest, musst du je nach Format deiner mehrkanaligen Audioinhalte möglicherweise die maximale Anzahl von Kanälen konfigurieren, die von einem Audiodecoder ausgegeben werden können. So wird sichergestellt, dass der Audiodecoder PCM mit mehreren Kanälen für die Plattform ausgibt, um eine räumliche Audiowiedergabe zu ermöglichen.

    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);
    

    Ein Beispiel in der Praxis findest du in der MediaCodecAudioRenderer.java von ExoPlayer. Informationen zum Deaktivieren der Raumorientierung unabhängig von der OEM-Anpassung finden Sie unter Spatial Audio deaktivieren.

  • AudioAttributes: Audio kann für die Spatialisierung verwendet werden, wenn usage auf USAGE_MEDIA oder USAGE_GAME festgelegt ist.

  • AudioFormat: Verwenden Sie eine Kanalmaske, die mindestens die AudioFormat.CHANNEL_OUT_QUAD-Kanäle (vorne links, vorne rechts, hinten links und hinten rechts) enthält, damit das Audiomaterial für die Spatialisierung infrage kommt. Im folgenden Beispiel wird AudioFormat.CHANNEL_OUT_5POINT1 für einen 5.1-Audiotrack verwendet. Verwenden Sie für einen Stereo-Audiotrack AudioFormat.CHANNEL_OUT_STEREO.

    Wenn du Media3 verwendest, kannst du mit Util.getAudioTrackChannelConfig(int channelCount) eine Kanalanzahl in eine Kanalmaske umwandeln.

    Lege außerdem AudioFormat.ENCODING_PCM_16BIT als Codierung fest, wenn du den Decoder so konfiguriert hast, dass er PCM mit mehreren Kanälen ausgibt.

    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();
    

Spatial Audio testen

Achte darauf, dass Spatial Audio auf deinem Testgerät aktiviert ist:

  • Bei kabelgebundenen Headsets rufen Sie Systemeinstellungen > Ton und Vibration > Raumaudio auf.
  • Bei kabellosen Headsets rufen Sie Systemeinstellungen > Verbundene Geräte > Zahnradsymbol für Ihr kabelloses Gerät > Spatial Audio auf.

Wenn du prüfen möchtest, ob Spatial Audio für die aktuelle Weiterleitung verfügbar ist, führe den Befehl adb shell dumpsys audio auf deinem Gerät aus. Während der Wiedergabe sollten in der Ausgabe die folgenden Parameter angezeigt werden:

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