Spatial Audio

Spatial Audio ist ein eindrucksvolles Audioerlebnis, das Nutzern das Gefühl vermittelt, mitten im Geschehen zu sein, und Inhalte besonders realistisch klingen lässt. Der entstehende Raumklang wirkt, als würde der Sound aus mehreren Lautsprechern kommen, ähnlich wie bei einem Surround-Soundsystem, aber über Kopfhörer.

In einem Film kann beispielsweise das Geräusch eines Autos hinter dem Nutzer beginnen, sich nach vorne bewegen und in der Ferne verhallen. In einem Videoanruf können Stimmen getrennt und um den Nutzer herum platziert werden, damit er die Sprecher leichter identifizieren kann.

Wenn deine Inhalte ein unterstütztes Audioformat verwenden, kannst du deiner App ab Android 13 (API-Level 33) Spatial Audio hinzufügen.

Funktionen abfragen

Verwende die Klasse Spatializer, um die Spatial Audio-Funktionen und das Verhalten des Geräts abzufragen. Rufen Sie zuerst eine Instanz von Spatializer aus dem AudioManager ab:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Nachdem du die Spatializer erhalten hast, prüfe, ob die vier Bedingungen erfüllt sind, die für die Ausgabe von Spatial Audio auf dem Gerät erfüllt sein müssen:

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

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

Erfassung von Kopfbewegungen

Bei unterstützten Headsets kann die Plattform die Räumlichkeit des Audiosignals an die Kopfposition des Nutzers anpassen. Mit isHeadTrackerAvailable() können Sie prüfen, ob für das aktuelle Audioausgabe-Routing eine Erfassung von Kopfbewegungen verfügbar ist.

Kompatible Inhalte

Spatializer.canBeSpatialized() gibt an, ob Audio mit den angegebenen Eigenschaften mit dem aktuellen Ausgabegeräte-Routing räumlich wiedergegeben werden kann. Diese Methode verwendet ein AudioAttributes und ein AudioFormat, die beide unten ausführlicher beschrieben werden.

AudioAttributes

Ein AudioAttributes-Objekt beschreibt die Nutzung eines Audiostreams (z. B. Spielaudio oder Standardmedien) sowie sein Wiedergabeverhalten und seinen Inhaltstyp.

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

Spatial Audio deaktivieren

Wenn du angeben möchtest, dass deine Inhalte bereits räumlich wiedergegeben wurden, rufe setIsContentSpatialized(true) auf, damit die Audioinhalte nicht doppelt verarbeitet werden. Alternativ können Sie das Spatialization-Verhalten anpassen, um die Spatialization vollständig zu deaktivieren, indem Sie setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER) aufrufen.

AudioFormat

Ein AudioFormat-Objekt beschreibt Details zum Format und zur Kanalkonfiguration eines Audiotracks.

Wenn Sie die AudioFormat instanziieren, die an canBeSpatialized() übergeben werden soll, legen Sie die Codierung auf das Ausgabeformat fest, das vom Decoder erwartet wird. Außerdem solltest du eine Kanalmaske festlegen, die der Kanalkonfiguration deiner Inhalte entspricht. Informationen zu den zu verwendenden Werten findest du im Abschnitt Standardverhalten für die Spatialization.

Änderungen am Spatializer überwachen

Wenn Sie auf Änderungen des Status von Spatializer reagieren möchten, können Sie mit Spatializer.addOnSpatializerStateChangedListener() einen Listener hinzufügen. Wenn du auf Änderungen bei der Verfügbarkeit der Erfassung von Kopfbewegungen reagieren möchtest, rufe Spatializer.addOnHeadTrackerAvailableListener() auf.

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

ExoPlayer und Spatial Audio

In neueren Versionen von ExoPlayer ist es einfacher, Spatial Audio zu verwenden. Wenn Sie die eigenständige ExoPlayer-Bibliothek (Paketname com.google.android.exoplayer2) verwenden, wird die Plattform in Version 2.17 so konfiguriert, dass Spatial Audio ausgegeben wird. In Version 2.18 werden Einschränkungen für die Anzahl der Audiokanäle eingeführt. Wenn Sie das ExoPlayer-Modul aus der Media3-Bibliothek (Paketname androidx.media3) verwenden, 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 räumlich wiedergegeben werden können.

Einschränkungen für die 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-Eigenschaften ändern, löst ExoPlayer eine neue Trackauswahl aus, um einen Audiotrack auszuwählen, der den aktuellen Eigenschaften entspricht. Beachten Sie, dass diese neue Trackauswahl zu einer kurzen Zwischenspeicherung führen kann.

Wenn Sie die Einschränkungen für die Anzahl der Audiokanäle deaktivieren möchten, legen Sie die Parameter für die Trackauswahl im Player wie unten gezeigt fest:

Kotlin

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

Java

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

Sie können auch die Parameter einer vorhandenen Spurauswahl aktualisieren, um die Einschränkungen für die Anzahl der Audiokanäle zu deaktivieren:

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 abgespielt 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 finden Sie unter Audiotracks auswählen.

Audiotrack-Auswahl

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

Parameter für die Trackauswahl ändern

Verwenden Sie Player.setTrackSelectionParameters(), um die Parameter für die Titelauswahl des ExoPlayers zu ändern. Ebenso können Sie die aktuellen Parameter von ExoPlayer mit Player.getTrackSelectionParameters() abrufen. So wählen Sie 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()
);

Beachte, dass das Ändern der Parameter für die Trackauswahl während der Wiedergabe zu einer Unterbrechung der Wiedergabe führen kann. Weitere Informationen zum Optimieren der Parameter für die Titelauswahl des Players finden Sie im Abschnitt Titelauswahl der ExoPlayer-Dokumentation.

Standardverhalten für die Verräumlichung

Das standardmäßige Spatial Audio-Verhalten in Android umfasst die folgenden Verhaltensweisen, die von OEMs angepasst werden können:

  • Nur Mehrkanal-Inhalte werden räumlich wiedergegeben, keine Stereo-Inhalte. Wenn du ExoPlayer nicht verwendest, musst du je nach Format deiner Mehrkanal-Audioinhalte möglicherweise die maximale Anzahl von Kanälen, die von einem Audiodecoder ausgegeben werden können, auf eine große Zahl festlegen. So wird sichergestellt, dass der Audiodecoder mehrkanaliges PCM ausgibt, das von der Plattform räumlich dargestellt werden kann.

    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 für die Verwendung finden Sie in der MediaCodecAudioRenderer.java von ExoPlayer. Wenn du die räumliche Darstellung unabhängig von der OEM-Anpassung selbst deaktivieren möchtest, findest du weitere Informationen unter Spatial Audio deaktivieren.

  • AudioAttributes: Audio ist für Spatial Audio geeignet, wenn usage entweder auf USAGE_MEDIA oder USAGE_GAME festgelegt ist.

  • AudioFormat: Verwende eine Kanalmaske, die mindestens die Kanäle AudioFormat.CHANNEL_OUT_QUAD (vorne links, vorne rechts, hinten links und hinten rechts) enthält, damit die Audiodaten für die Räumlichkeit infrage kommen. Im folgenden Beispiel verwenden wir AudioFormat.CHANNEL_OUT_5POINT1 für einen 5.1-Audiotrack. 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.

    Setze außerdem die Codierung auf AudioFormat.ENCODING_PCM_16BIT, wenn du den Decoder so konfiguriert hast, dass er Mehrkanal-PCM 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: Systemeinstellungen > Ton & Vibration > Spatial Audio.
  • Bei kabellosen Kopfhörern: Systemeinstellungen > Verbundene Geräte > Zahnradsymbol für dein kabelloses Gerät > Spatial Audio.

Führe den Befehl adb shell dumpsys audio auf deinem Gerät aus, um die Verfügbarkeit von Spatial Audio für das aktuelle Routing zu prüfen. Während der Wiedergabe sollten die folgenden Parameter in der Ausgabe angezeigt werden:

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