Audio spaziale

L'audio spaziale è un'esperienza sonora immersiva che mette gli utenti al centro dell'azione, rendendo i contenuti più realistici. Il suono viene "spazializzato" in modo da creare un effetto multi-altoparlante, simile a una configurazione audio surround, ma attraverso le cuffie.

Ad esempio, in un film, il suono di un'auto potrebbe iniziare dietro l'utente, spostarsi in avanti e svanire in lontananza. In una videochiamata, le voci possono essere separate e posizionate intorno all'utente, facilitando l'identificazione di chi sta parlando.

Se i tuoi contenuti utilizzano un formato audio supportato, puoi aggiungere l'audio spaziale alla tua app a partire da Android 13 (livello API 33).

Query per le funzionalità

Utilizza la classe Spatializer per eseguire query sulle funzionalità e sul comportamento di spazializzazione del dispositivo. Inizia recuperando un'istanza di Spatializer da AudioManager:

Kotlin

val spatializer = audioManager.spatializer

Java

Spatializer spatializer = AudioManager.getSpatializer();

Dopo aver ottenuto Spatializer, verifica le quattro condizioni che devono essere soddisfatte affinché il dispositivo possa riprodurre l'audio spazializzato:

Criteri Assegno
Il dispositivo supporta la spazializzazione? getImmersiveAudioLevel() non è SPATIALIZER_IMMERSIVE_LEVEL_NONE
La spazializzazione è disponibile?
La disponibilità dipende dalla compatibilità con l'attuale routing dell'uscita audio.
isAvailable() è true
La spazializzazione è attiva? isEnabled() è true
È possibile spazializzare una traccia audio con i parametri specificati? canBeSpatialized() è true

Queste condizioni potrebbero non essere soddisfatte, ad esempio se la spazializzazione non è disponibile per la traccia audio corrente o se è disattivata del tutto sul dispositivo di output audio.

Tracciamento testa

Con le cuffie supportate, la piattaforma può regolare la spazializzazione dell'audio in base alla posizione della testa dell'utente. Per verificare se è disponibile un tracker della testa per il routing di uscita audio corrente, chiama isHeadTrackerAvailable().

Contenuti compatibili

Spatializer.canBeSpatialized() indica se l'audio con le proprietà specificate può essere spazializzato con il routing del dispositivo di output corrente. Questo metodo accetta un AudioAttributes e un AudioFormat, entrambi descritti in maggiore dettaglio di seguito.

AudioAttributes

Un oggetto AudioAttributes descrive l'utilizzo di uno stream audio (ad esempio, audio di gioco o contenuti multimediali standard), insieme ai relativi comportamenti di riproduzione e tipo di contenuti.

Quando chiami canBeSpatialized(), utilizza la stessa istanza AudioAttributes impostata per Player. Ad esempio, se utilizzi la libreria Jetpack Media3 e non hai personalizzato AudioAttributes, utilizza AudioAttributes.DEFAULT.

Disattivazione dell'audio spaziale

Per indicare che i tuoi contenuti sono già stati spazializzati, chiama setIsContentSpatialized(true) in modo che l'audio non venga elaborato due volte. In alternativa, regola il comportamento di spazializzazione per disattivare completamente la spazializzazione chiamando setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER).

AudioFormat

Un oggetto AudioFormat descrive i dettagli relativi alla configurazione del formato e del canale di una traccia audio.

Quando crei un'istanza di AudioFormat da passare a canBeSpatialized(), imposta encoding sullo stesso formato di output previsto dal decoder. Devi anche impostare una maschera dei canali che corrisponda alla configurazione dei canali dei tuoi contenuti. Per indicazioni sui valori specifici da utilizzare, consulta la sezione Comportamento di spazializzazione predefinito.

Ascolta le modifiche apportate a Spatializer

Per rilevare le modifiche allo stato di Spatializer, puoi aggiungere un listener con Spatializer.addOnSpatializerStateChangedListener(). Analogamente, per rilevare le modifiche alla disponibilità di un tracker della testa, chiama Spatializer.addOnHeadTrackerAvailableListener().

Questo può essere utile se vuoi regolare la selezione delle tracce durante la riproduzione utilizzando i callback del listener. Ad esempio, quando un utente collega o scollega le cuffie dal dispositivo, il callback onSpatializerAvailableChanged indica se l'effetto di spazializzazione è disponibile per il nuovo routing dell'output audio. A questo punto, puoi valutare di aggiornare la logica di selezione delle tracce del player in modo che corrisponda alle nuove funzionalità del dispositivo. Per maggiori dettagli sul comportamento di selezione delle tracce di ExoPlayer, consulta la sezione ExoPlayer e audio spaziale.

ExoPlayer e audio spaziale

Le versioni recenti di ExoPlayer semplificano l'adozione dell'audio spaziale. Se utilizzi la libreria ExoPlayer autonoma (nome del pacchetto com.google.android.exoplayer2), la versione 2.17 configura la piattaforma per l'output dell'audio spazializzato, mentre la versione 2.18 introduce vincoli per il numero di canali audio. Se utilizzi il modulo ExoPlayer della libreria Media3 (nome del pacchetto androidx.media3), le versioni 1.0.0-beta01 e successive includono gli stessi aggiornamenti.

Dopo aver aggiornato la dipendenza ExoPlayer all'ultima release, l'app deve solo includere contenuti che possono essere spazializzati.

Vincoli relativi al numero di canali audio

Quando vengono soddisfatte tutte e quattro le condizioni per l'audio spaziale, ExoPlayer sceglie una traccia audio multicanale. In caso contrario, ExoPlayer sceglie una traccia stereo. Se le proprietà di Spatializer cambiano, ExoPlayer attiverà una nuova selezione della traccia per selezionare una traccia audio che corrisponda alle proprietà correnti. Tieni presente che questa nuova selezione della traccia potrebbe causare un breve periodo di rebuffering.

Per disattivare i vincoli relativi al numero di canali audio, imposta i parametri di selezione della traccia sul player come mostrato di seguito:

Kotlin

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

Java

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

Allo stesso modo, puoi aggiornare i parametri di un selettore di tracce esistente per disattivare i vincoli relativi al numero di canali audio nel seguente modo:

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()
);

Se i vincoli relativi al numero di canali audio sono disattivati, se i contenuti hanno più tracce audio, ExoPlayer seleziona inizialmente la traccia con il maggior numero di canali e riproducibile dal dispositivo. Ad esempio, se i contenuti contengono una traccia audio multicanale e una traccia audio stereo e il dispositivo supporta la riproduzione di entrambe, ExoPlayer seleziona la traccia multicanale. Per informazioni dettagliate su come personalizzare questo comportamento, consulta la sezione Selezione della traccia audio.

Selezione della traccia audio

Quando il comportamento dei vincoli per il numero di canali audio di ExoPlayer è disattivato, ExoPlayer non seleziona automaticamente una traccia audio che corrisponde alle proprietà dello spazializzatore del dispositivo. In alternativa, puoi personalizzare la logica di selezione delle tracce di ExoPlayer impostando i parametri di selezione delle tracce prima o durante la riproduzione. Per impostazione predefinita, ExoPlayer seleziona tracce audio uguali alla traccia iniziale per quanto riguarda il tipo MIME (codifica), il numero di canali e la frequenza di campionamento.

Modifica dei parametri di selezione della traccia

Per modificare i parametri di selezione della traccia di ExoPlayer, utilizza Player.setTrackSelectionParameters(). Allo stesso modo, puoi ottenere i parametri attuali di ExoPlayer con Player.getTrackSelectionParameters(). Ad esempio, per selezionare una traccia audio stereo durante la riproduzione:

Kotlin

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

Java

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

Tieni presente che la modifica dei parametri di selezione della traccia durante la riproduzione potrebbe causare un'interruzione della riproduzione. Per saperne di più sulla regolazione dei parametri di selezione delle tracce del player, consulta la sezione Selezione delle tracce della documentazione di ExoPlayer.

Comportamento di spazializzazione predefinito

Il comportamento di spazializzazione predefinito in Android include i seguenti comportamenti che possono essere personalizzati dagli OEM:

  • Vengono spazializzati solo i contenuti multicanale, non quelli stereo. Se non utilizzi ExoPlayer, a seconda del formato dei tuoi contenuti audio multicanale, potresti dover configurare il numero massimo di canali che possono essere emessi da un decodificatore audio su un numero elevato. In questo modo, il decoder audio genera un PCM multicanale che la piattaforma può spazializzare.

    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);

    Per un esempio in azione, consulta MediaCodecAudioRenderer.java di ExoPlayer. Per disattivare la spazializzazione autonomamente, indipendentemente dalla personalizzazione dell'OEM, consulta Disattivazione dell'audio spaziale.

  • AudioAttributes: l'audio è idoneo per la spazializzazione se usage è impostato su USAGE_MEDIA o USAGE_GAME.

  • AudioFormat: utilizza una maschera di canali che contenga almeno i canali AudioFormat.CHANNEL_OUT_QUAD (anteriore sinistro, anteriore destro, posteriore sinistro e posteriore destro) affinché l'audio sia idoneo alla spazializzazione. Nell'esempio seguente, utilizziamo AudioFormat.CHANNEL_OUT_5POINT1 per una traccia audio 5.1. Per una traccia audio stereo, utilizza AudioFormat.CHANNEL_OUT_STEREO.

    Se utilizzi Media3, puoi utilizzare Util.getAudioTrackChannelConfig(int channelCount) per convertire un numero di canali in una maschera di canali.

    Inoltre, imposta la codifica su AudioFormat.ENCODING_PCM_16BIT se hai configurato il decoder per l'output PCM multicanale.

    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();

Testa l'audio spaziale

Assicurati che l'audio spaziale sia attivato sul dispositivo di test:

  • Per le cuffie con cavo, vai a Impostazioni di sistema > Suoni e vibrazione > Audio spaziale.
  • Per le cuffie wireless, vai a Impostazioni di sistema > Dispositivi connessi > Icona dell'ingranaggio per il tuo dispositivo wireless > Audio spaziale.

Per verificare la disponibilità dell'audio spaziale per il routing corrente, esegui il comando adb shell dumpsys audio sul tuo dispositivo. Durante la riproduzione, nell'output dovresti vedere i seguenti parametri:

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