Spatial Audio

Spatial Audio ist ein eindrucksvolles Audioerlebnis, das Ihren Nutzern das Gefühl vermittelt, mitten im Geschehen zu sein, und Ihre Inhalte besonders realistisch 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.

In einem Film kann der Ton eines Autos beispielsweise hinter dem Nutzer beginnen, sich nach vorn bewegen und in der Ferne ausklingen. In einem Videochat können Stimmen getrennt und um den Nutzer herum platziert werden, sodass es einfacher ist, die Sprecher zu identifizieren.

Wenn für Ihre Inhalte ein unterstütztes Audioformat verwendet wird, können Sie ab Android 13 (API‑Level 33) räumliches Audio in Ihre App einfügen.

Funktionen abfragen

Verwenden Sie die Klasse Spatializer, um die Spatialization-Funktionen 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();

Nachdem Sie die Spatializer erhalten haben, prüfen Sie, ob die vier Bedingungen erfüllt sind, die für die Ausgabe von räumlichem Audio auf dem Gerät gelten:

Kriterien Prüfen
Unterstützt das Gerät die Räumlichkeit? getImmersiveAudioLevel() ist nicht SPATIALIZER_IMMERSIVE_LEVEL_NONE
Ist die Räumlichkeit verfügbar? Die Verfügbarkeit von
hängt von der Kompatibilität mit dem aktuellen Audioausgaberouting ab.
isAvailable() ist true
Ist die Verräumlichung 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 Räumlichkeit für den aktuellen Audiotrack nicht verfügbar oder auf dem Audioausgabegerät deaktiviert ist.

Erfassung von Kopfbewegungen

Bei unterstützten Headsets kann die Plattform die Räumlichkeit des Audiosignals 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 Audio mit den angegebenen Eigenschaften mit dem aktuellen Routing des Ausgabegeräts räumlich wiedergegeben werden kann. Diese Methode verwendet ein AudioAttributes und ein AudioFormat, die beide unten genauer beschrieben werden.

AudioAttributes

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

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

Spatial Audio deaktivieren

Wenn Sie angeben möchten, dass Ihre Inhalte bereits räumlich bearbeitet wurden, rufen Sie setIsContentSpatialized(true) auf, damit der Audioinhalt nicht doppelt verarbeitet wird. Alternativ können Sie das Verhalten der Räumlichkeit anpassen, um die Räumlichkeit vollständig zu deaktivieren, indem Sie setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER) aufrufen.

AudioFormat

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

Wenn Sie AudioFormat instanziieren, um es an canBeSpatialized() zu übergeben, legen Sie die Codierung auf dieselbe Codierung fest, die vom Decoder als Ausgabeformat erwartet wird. Außerdem sollten Sie eine Channel-Maske festlegen, die der Channel-Konfiguration Ihrer Inhalte entspricht. Im Abschnitt Standardverhalten bei der Räumlichkeit finden Sie Informationen zu den zu verwendenden Werten.

Auf Änderungen am Spatializer reagieren

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

Das kann nützlich sein, wenn Sie die Auswahl der Tracks während der Wiedergabe mithilfe der Listener-Callbacks 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 sollten Sie die Logik für die Auswahl der Tracks für Ihren Player an die neuen Funktionen des Geräts anpassen. Weitere Informationen zum Verhalten von ExoPlayer bei der Auswahl von Tracks finden Sie im Abschnitt ExoPlayer und räumliches Audio.

ExoPlayer und Spatial Audio

In den letzten Versionen von ExoPlayer wurde die Einführung von Spatial Audio vereinfacht. Wenn Sie die eigenständige ExoPlayer-Bibliothek (Paketname com.google.android.exoplayer2) verwenden, wird mit Version 2.17 die Plattform für die Ausgabe von räumlichem Audio konfiguriert und mit Version 2.18 werden Einschränkungen für die Anzahl der Audiochannels 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 Sie Ihre ExoPlayer-Abhängigkeit auf die aktuelle Version aktualisiert haben, muss Ihre 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 Mehrkanal-Audio-Track aus. Andernfalls wählt ExoPlayer einen Stereotrack aus. Wenn sich die Spatializer-Eigenschaften ändern, löst ExoPlayer eine neue Titelauswahl aus, um einen Audiotrack auszuwählen, der den aktuellen Eigenschaften entspricht. Hinweis: Durch die neue Auswahl des Tracks kann es zu einer kurzen Unterbrechung der Wiedergabe kommen.

Wenn Sie die Einschränkungen für die Anzahl der Audiochannels deaktivieren möchten, legen Sie die Parameter für die Titelauswahl 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 die Parameter eines vorhandenen Track-Selektors auch so aktualisieren, dass die Einschränkungen für die Anzahl der Audio-Channels deaktiviert werden:

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 Audio-Channels deaktiviert sind und Inhalte mehrere Audio-Tracks haben, wählt ExoPlayer zuerst den Track aus, der die höchste Anzahl von Channels hat und auf dem Gerät wiedergegeben werden kann. Wenn der Inhalt beispielsweise einen Mehrkanal-Audio-Track und einen Stereo-Audio-Track 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 Auswahl von Audio-Tracks.

Auswahl des Audiotracks

Wenn das Verhalten von ExoPlayer in Bezug auf Einschränkungen bei der Anzahl der Audio-Channels 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 Auswahl von ExoPlayer-Tracks anpassen, indem Sie vor oder während der Wiedergabe Parameter für die Auswahl von Tracks festlegen. Standardmäßig wählt ExoPlayer Audiotracks aus, die in Bezug auf MIME-Typ (Codierung), Anzahl der Kanäle und Samplerate mit dem ursprünglichen Track übereinstimmen.

Parameter für die Auswahl von Tracks ändern

Verwenden Sie Player.setTrackSelectionParameters(), um die Parameter für die Auswahl von ExoPlayer-Tracks 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()
);

Wenn Sie die Parameter für die Auswahl des Tracks während der Wiedergabe ändern, kann es zu einer Unterbrechung der Wiedergabe kommen. Weitere Informationen zum Optimieren der Parameter für die Auswahl von Tracks im Player finden Sie in der ExoPlayer-Dokumentation im Abschnitt Track selection (Trackauswahl).

Standardverhalten bei der Räumlichkeit

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

  • Nur Mehrkanal-Inhalte werden räumlich wiedergegeben, nicht Stereo-Inhalte. Wenn Sie ExoPlayer nicht verwenden, müssen Sie je nach Format Ihrer Mehrkanal-Audioinhalte möglicherweise die maximale Anzahl von Kanälen, die von einem Audio-Decoder ausgegeben werden können, auf einen hohen Wert festlegen. So wird sichergestellt, dass der Audio-Decoder Mehrkanal-PCM für die Plattform ausgibt, damit diese den Sound räumlich wiedergeben 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 finden Sie in der MediaCodecAudioRenderer.java von ExoPlayer. Informationen zum manuellen Deaktivieren der Räumlichkeit unabhängig von der OEM-Anpassung finden Sie unter Spatial Audio deaktivieren.

  • AudioAttributes: Audio kann räumlich wiedergegeben werden, wenn usage entweder auf USAGE_MEDIA oder USAGE_GAME festgelegt ist.

  • AudioFormat: Verwenden Sie 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-Audio-Track AudioFormat.CHANNEL_OUT_STEREO.

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

    Stellen Sie außerdem die Codierung auf AudioFormat.ENCODING_PCM_16BIT ein, 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 gehen Sie zu Systemeinstellungen > Töne & Vibration > 3D-Audio.
  • Bei kabellosen Headsets rufe Systemeinstellungen > Verbundene Geräte > Zahnradsymbol für dein kabelloses Gerät > Spatial Audio auf.

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

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