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 das Geräusch eines Autos beispielsweise hinter dem Nutzer stecken, sich vorwärts bewegen und in die Ferne steigen. In einem Videochat können Stimmen voneinander getrennt und um den Nutzer herum platziert werden, damit die Sprecher leichter zu identifizieren 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.

Abfrage von Funktionen

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, musst du prüfen, ob die folgenden vier 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 dem aktuellen Audioausgaberouting 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 verwendet ein AudioAttributes und ein AudioFormat, die beide weiter unten ausführlicher beschrieben werden.

AudioAttributes

Ein AudioAttributes-Objekt beschreibt die Nutzung eines Audiostreams (z. B. Audio eines Spiels oder Standardmedien) zusammen mit seinem Wiedergabeverhalten und seinem Inhaltstyp.

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

Spatial Audio deaktivieren

Wenn du angeben möchtest, dass deine Inhalte bereits räumlich ausgerichtet wurden, rufe setIsContentSpatialized(true) auf, damit das Audio nicht doppelt verarbeitet wird. Alternativ können Sie das Raumisierungsverhalten so anpassen, dass die Verräumlichung vollständig deaktiviert wird. Dazu rufen Sie 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. Weitere Informationen zu bestimmten Werten, die Sie verwenden sollten, finden Sie im Abschnitt Standardmäßiges Raumisierungsverhalten.

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 wissen möchten, ob ein Kopf-Tracker verfügbar ist, 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 die Verbindung trennt, gibt der onSpatializerAvailableChanged-Callback an, ob der Spatializer-Effekt für das neue Audioausgaberouting verfügbar ist. An dieser Stelle können Sie die Titelauswahllogik Ihres Spielers aktualisieren, damit sie den neuen Funktionen des Geräts entspricht. Weitere Informationen zur Trackauswahl von ExoPlayer finden Sie im Abschnitt ExoPlayer und Spatial 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 eine Mehrkanal-Audiospur und eine Stereospur enthält und das Gerät die Wiedergabe beider Elemente unterstützt, wählt ExoPlayer den Mehrkanalspur-Track aus. Weitere Informationen dazu, wie Sie dieses Verhalten anpassen können, finden Sie unter Auswahl von Audiospuren.

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. ExoPlayer wählt standardmäßig Audiotracks aus, die in Bezug auf MIME-Typ (Codierung), Kanalanzahl und Abtastrate mit dem ursprünglichen Track identisch sind.

Parameter für die Titelauswahl ändern

Mit Player.setTrackSelectionParameters() kannst du die Parameter für die Titelauswahl von ExoPlayer ändern. Ebenso können Sie 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()
);

Wenn Sie die Parameter für die Titelauswahl während der Wiedergabe ändern, kann dies zu einer Unterbrechung der Wiedergabe führen. Weitere Informationen zur Feinabstimmung der Titelauswahlparameter des Players sind im Abschnitt zur Titelauswahl der ExoPlayer-Dokumentation verfügbar.

Standardverhalten bei der Spatialisierung

Das Standardverhalten der Verräumlichung in Android umfasst die folgenden Verhaltensweisen, 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 Praxisbeispiel findest du im ExoPlayer-MediaCodecAudioRenderer.java. 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 Sie Media3 verwenden, können Sie 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 Sie prüfen möchten, ob Spatial Audio für das aktuelle Routing verfügbar ist, führen Sie auf Ihrem Gerät den Befehl adb shell dumpsys audio aus. Während der Wiedergabe sollten in der Ausgabe die folgenden Parameter angezeigt werden:

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