Spatial Audio

Spatial Audio ist ein eindrucksvolles Audioerlebnis, bei dem der Nutzer in den Mittelpunkt des Geschehens rückt und Inhalte realistischer klingen. Der Klang wird dabei „räumlich“ erzeugt, um einen Effekt mit mehreren Lautsprechern zu erzeugen, ähnlich wie bei einem Surround-Sound-System, allerdings über Kopfhörer.

In einem Film könnte der Ton eines Autos beispielsweise hinter dem Nutzer beginnen, sich vorwärts bewegen und in die Ferne abschweifen. In Videoanrufen können Stimmen getrennt und um den Nutzer herum platziert werden, um die Identifizierung der Sprecher zu erleichtern.

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

Funktionen abfragen

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

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Prüfen Sie nach Erhalt von Spatializer die vier Bedingungen, die erfüllt sein müssen, damit das Gerät Spatial Audio ausgibt:

Kriterien Ansehen
Unterstützt das Gerät die Verräumung? getImmersiveAudioLevel() ist nicht SPATIALIZER_IMMERSIVE_LEVEL_NONE
Ist Räumlichkeit verfügbar?
Die Verfügbarkeit hängt von der Kompatibilität mit dem aktuellen Audioausgaberouting ab.
isAvailable() ist true
Ist die räumliche Umgebung aktiviert? isEnabled() ist true
Kann ein Audiotrack mit den angegebenen Parametern räumlich ermittelt werden? canBeSpatialized() ist true

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

Erfassung von Kopfbewegungen

Mit unterstützten Headsets kann die Plattform die Raumisierung des Audios an die Kopfposition des Nutzers anpassen. Rufen Sie isHeadTrackerAvailable() auf, um zu prüfen, ob ein Head Tracker für das aktuelle Audioausgaberouting verfügbar ist.

Kompatible Inhalte

Spatializer.canBeSpatialized() gibt an, ob Audiodaten mit den angegebenen Eigenschaften mit dem aktuellen Routing des Ausgabegeräts räumlich dargestellt werden können. Diese Methode verwendet ein AudioAttributes- und ein AudioFormat-Element, die beide unten ausführlicher beschrieben werden.

AudioAttributes

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

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

Spatial Audio wird deaktiviert

Wenn Sie angeben möchten, dass Ihr Inhalt bereits räumlich aufgeteilt wurde, rufen Sie setIsContentSpatialized(true) auf, damit die Audiodaten nicht doppelt verarbeitet werden. Alternativ können Sie das Räumlichkeitsverhalten anpassen und setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER) aufrufen, um die Räumlichkeit zu deaktivieren.

AudioFormat

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

Wenn Sie AudioFormat instanziieren, um es an canBeSpatialized() zu übergeben, legen Sie für die Codierung dasselbe Ausgabeformat fest, das vom Decodierer erwartet wird. Außerdem solltest du eine Kanalmaske festlegen, die der Kanalkonfiguration deiner Inhalte entspricht. Informationen zu den verwendeten Werten finden Sie im Abschnitt Standardverhalten für die Räumlichkeit.

Änderungen an Spatializer beobachten

Sie können mit Spatializer.addOnSpatializerStateChangedListener() einen Listener hinzufügen, um auf Änderungen am Status der Spatializer zu warten. In ähnlicher Weise können Sie Spatializer.addOnHeadTrackerAvailableListener() aufrufen, um auf Änderungen in der Verfügbarkeit eines Head-Trackers zu warten.

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 trennt, gibt der Callback onSpatializerAvailableChanged an, ob der Spatializer-Effekt für das neue Audioausgaberouting verfügbar ist. An dieser Stelle können Sie die Logik zur Titelauswahl Ihres Players so aktualisieren, dass 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 Releases von ExoPlayer erleichtern die Einführung von Spatial Audio. Wenn Sie die eigenständige ExoPlayer-Bibliothek (Paketname com.google.android.exoplayer2) verwenden, 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, enthalten die Versionen 1.0.0-beta01 und höher dieselben Updates.

Nachdem Sie die ExoPlayer-Abhängigkeit auf die neueste Version aktualisiert haben, muss Ihre App nur noch Inhalte enthalten, die räumlich dargestellt werden können.

Beschränkungen bei der Anzahl der Audiokanäle

Wenn alle vier Bedingungen für Spatial Audio erfüllt sind, wählt ExoPlayer einen Mehrkanal-Audiotrack aus. Ist dies nicht der Fall, wählt ExoPlayer stattdessen einen Stereotitel aus. Wenn sich die Spatializer-Eigenschaften ändern, löst ExoPlayer eine neue Trackauswahl aus, um einen Audiotrack auszuwählen, der mit den aktuellen Eigenschaften übereinstimmt. Durch diese neue Track-Auswahl kann es zu einer kurzen Pufferzeit kommen.

Um die Beschränkungen für die Anzahl der Audiokanäle zu deaktivieren, lege die Parameter für die Trackauswahl im Player wie unten dargestellt fest:

Kotlin

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

Java

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

Ebenso können Sie die Parameter eines vorhandenen Track-Selektors aktualisieren, um die Einschränkungen der 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 von Audiokanälen deaktiviert sind, wählt ExoPlayer anfangs den Titel mit der höchsten Anzahl von Kanälen aus und kann auf dem Gerät wiedergegeben werden, wenn Inhalte mehrere Audiospuren haben. Wenn der Inhalt beispielsweise eine Mehrkanal-Audiospur und eine Stereo-Audiospur enthält und das Gerät die Wiedergabe beider Audiotracks unterstützt, wählt ExoPlayer die Mehrkanalspur aus. Weitere Informationen zum Anpassen dieses Verhaltens finden Sie unter Audiotrack-Auswahl.

Audiotrackauswahl

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

Parameter für die Titelauswahl ändern

Verwenden Sie Player.setTrackSelectionParameters(), um die Parameter für die Trackauswahl des ExoPlayers zu ändern. Analog können Sie die aktuellen ExoPlayer-Parameter mit Player.getTrackSelectionParameters() abrufen. So wählen Sie beispielsweise bei der Wiedergabe einen Stereo-Audiotrack aus:

Kotlin

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

Java

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

Das Ändern der Titelauswahlparameter mitten in der Wiedergabe kann zu einer Unterbrechung der Wiedergabe führen. Weitere Informationen zur Feinabstimmung der Titelauswahlparameter des Players finden Sie in der ExoPlayer-Dokumentation im Abschnitt zur Titelauswahl.

Standardverhalten für die Räumlichkeit

Das Standardverhalten der Räumlichkeit in Android umfasst die folgenden Verhaltensweisen, die von OEMs angepasst werden können:

  • Nur Multikanal-Inhalte sind räumlich dargestellt, keine Stereoinhalte. Wenn Sie ExoPlayer nicht verwenden, müssen Sie abhängig vom Format Ihrer Mehrkanal-Audioinhalte möglicherweise die maximale Anzahl an Kanälen konfigurieren, die von einem Audiodecoder an eine große Anzahl ausgegeben werden können. Dadurch wird sichergestellt, dass der Audiodecoder Mehrkanal-PCM für die Räumlichkeit der Plattform ausgibt.

    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 finden Sie unter MediaCodecAudioRenderer.java von ExoPlayer. Wie Sie die Raumisierung unabhängig von der OEM-Anpassung selbst deaktivieren, erfahren Sie unter Spatial Audio deaktivieren.

  • AudioAttributes: Audio ist für die Räumlichkeit zulässig, wenn usage entweder auf USAGE_MEDIA oder USAGE_GAME eingestellt ist.

  • AudioFormat: Verwenden Sie eine Kanalmaske, die mindestens die Kanäle AudioFormat.CHANNEL_OUT_QUAD (vorn links, vorne rechts, hinten links und hinten rechts) enthält, damit das Audio für die Räumlichkeit geeignet ist. 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.

    Setzen Sie außerdem die Codierung auf AudioFormat.ENCODING_PCM_16BIT, wenn Sie den Decoder für die Ausgabe von Mehrkanal-PCM konfiguriert haben.

    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

Vergewissere dich, dass Spatial Audio auf deinem Testgerät aktiviert ist:

  • Rufen Sie bei kabelgebundenen Headsets Systemeinstellungen > Ton und Vibration > Spatial Audio auf.
  • Rufen Sie bei kabellosen Headsets Systemeinstellungen > Verbundene Geräte > Zahnradsymbol für Ihr Mobilgerät > Spatial Audio auf.

Führen Sie den Befehl adb shell dumpsys audio auf Ihrem Gerät aus, um zu prüfen, ob Spatial Audio für das aktuelle Routing verfügbar ist. Während der Wiedergabe sollten die folgenden Parameter in der Ausgabe zu sehen sein:

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