Spatial Audio

Spatial Audio ist ein immersives Audioerlebnis, bei dem die Nutzer in den Mittelpunkt der Handlung rücken und Inhalte so realistisch klingen. Der Klang wird räumlich verarbeitet, um einen Effekt mit mehreren Lautsprechern zu erzeugen, ähnlich wie bei einem Surround-Sound-Setup, jedoch über Kopfhörer.

In einem Film könnte beispielsweise das Geräusch eines Autos hinter dem Nutzer rauskommen, sich vorwärts bewegen und in die Ferne gehen. In einem Videochat können die Stimmen getrennt und um den Nutzer herum platziert werden, damit die Sprecher leichter identifiziert werden können.

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

Abfrage von Funktionen

Verwenden Sie die Klasse Spatializer, um die Raumisierungsfunktionen 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 Spatializer abgerufen hast, prüfe, ob die vier Bedingungen erfüllt sein müssen, damit das Gerät Spatial Audio ausgeben kann:

Kriterien Prüfen
Unterstützt das Gerät die Verräumlichung? getImmersiveAudioLevel() ist nicht SPATIALIZER_IMMERSIVE_LEVEL_NONE
Ist Verräumlichung verfügbar?
Die Verfügbarkeit hängt von der Kompatibilität mit dem aktuellen Audioausgaberouting ab.
isAvailable() ist true
Ist die Raumisierung aktiviert? isEnabled() ist true
Kann eine Audiotracks mit den angegebenen Parametern räumlich erstellt werden? canBeSpatialized() ist true

Diese Bedingungen werden möglicherweise nicht erfüllt, z. B. wenn die Raumisierung 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 der Audiodaten an die Kopfposition des Nutzers anpassen. Wenn Sie prüfen möchten, ob für das aktuelle Audioausgabe-Routing ein Kopf-Tracker verfügbar ist, rufen Sie isHeadTrackerAvailable() auf.

Kompatible Inhalte

Spatializer.canBeSpatialized() gibt an, ob Audio mit den angegebenen Attributen mit dem aktuellen Routing des Ausgabegeräts räumlich dargestellt 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.

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

Spatial Audio deaktivieren

Wenn Sie angeben möchten, dass der Inhalt bereits verräumt wurde, rufen Sie setIsContentSpatialized(true) auf, damit die Audiodaten nicht doppelt verarbeitet werden. 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 beschreibt Details zum Format und der Kanalkonfiguration eines Audiotracks.

Legen Sie bei der Instanziierung von AudioFormat für die Übergabe an canBeSpatialized() die Codierung auf dasselbe Ausgabeformat fest, das vom Decodierer erwartet wird. Du solltest außerdem eine Kanalmaske festlegen, die der Kanalkonfiguration deines Inhalts entspricht. Weitere Informationen zu bestimmten Werten, die Sie verwenden sollten, finden Sie im Abschnitt Standardmäßiges Raumisierungsverhalten.

Änderungen an Spatializer überwachen

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

Dies 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 onSpatializerAvailableChanged-Callback an, ob der Spatializer-Effekt für das neue Audioausgabe-Routing 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

Mit den jüngsten Releases von ExoPlayer ist die Einführung von Spatial Audio noch einfacher. 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 Spatial Audio konfiguriert und 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, enthalten 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 Inhalte enthalten, die verräumt 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 Mehrkanal-Audiotrack aus. Ist dies nicht der Fall, wählt ExoPlayer stattdessen eine Stereospur aus. Wenn sich die Spatializer-Eigenschaften ändern, löst ExoPlayer eine neue Trackauswahl aus, um einen Audiotrack auszuwählen, der den aktuellen Eigenschaften entspricht. Diese neue Titelauswahl kann zu einem kurzen Puffer führen.

Um Einschränkungen für die Anzahl der Audiokanäle zu deaktivieren, 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()
);

Auf ähnliche Weise können Sie die Parameter einer vorhandenen Trackauswahl aktualisieren, um Einschränkungen für die Anzahl der Audiokanäle so 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 anfangs den Track mit den meisten Kanälen aus und kann auf dem Gerät wiedergegeben werden. 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 die Einschränkungen der Audiokanalzahl von ExoPlayer deaktiviert sind, wählt ExoPlayer nicht automatisch einen Audiotrack aus, der den Eigenschaften des Spatializers des Geräts entspricht. Stattdessen können Sie die Trackauswahllogik von ExoPlayer anpassen, indem Sie vor oder während der Wiedergabe Trackauswahlparameter festlegen. 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

Verwenden Sie Player.setTrackSelectionParameters(), um die Trackauswahlparameter des ExoPlayers zu ändern. Ebenso können Sie die aktuellen Parameter von ExoPlayer mit Player.getTrackSelectionParameters() abrufen. So kannst du beispielsweise einen Stereo-Audiotrack während der Wiedergabe auswählen:

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 für Verräumlichung

Das standardmäßige Verräumlichungsverhalten in Android umfasst die folgenden Verhaltensweisen, die von OEMs angepasst werden können:

  • Nur Multi-Channel-Inhalte werden räumlich dargestellt, keine Stereoinhalte. Wenn Sie ExoPlayer nicht verwenden, müssen Sie abhängig vom Format Ihres Mehrkanal-Audioinhalts möglicherweise die maximale Anzahl von Kanälen konfigurieren, die von einem Audiodecoder für eine große Anzahl ausgegeben werden können. Dadurch wird sichergestellt, dass der Audiodecoder mehrkanalige PCM für die Verrä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 findest du im ExoPlayer-MediaCodecAudioRenderer.java. Wie Sie die Spatialisierung unabhängig von der OEM-Anpassung selbst deaktivieren, erfahren Sie unter Spatial Audio deaktivieren.

  • AudioAttributes: Audioinhalte können für die Verräumlichung verwendet werden, wenn usage auf USAGE_MEDIA oder USAGE_GAME gesetzt ist.

  • AudioFormat: Verwende eine Kanalmaske, die mindestens die AudioFormat.CHANNEL_OUT_QUAD-Kanäle (vorne links, vorne rechts, hinten links und hinten rechts) enthält, damit die Audioinhalte für die Verräumlichung infrage kommen. Im folgenden Beispiel verwenden wir AudioFormat.CHANNEL_OUT_5POINT1 für einen 5.1-Audiospur. Für Stereo-Audiospuren verwendest du AudioFormat.CHANNEL_OUT_STEREO.

    Wenn Sie Media3 verwenden, können Sie mit Util.getAudioTrackChannelConfig(int channelCount) eine Kanalanzahl in eine Kanalmaske umwandeln.

    Legen Sie außerdem die Codierung auf AudioFormat.ENCODING_PCM_16BIT fest, 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

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

  • Bei kabelgebundenen Headsets rufen Sie Systemeinstellungen > Ton & Vibration > Spatial Audio auf.
  • Rufe bei kabellosen Headsets Systemeinstellungen > Verbundene Geräte > Zahnradsymbol für 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 die Wiedergabe aktiv ist, sollten die folgenden Parameter in der Ausgabe zu sehen sein:

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