El audio espacial es una experiencia de audio envolvente que pone a los usuarios en el centro de la acción, lo que hace que el contenido suene más realista. El sonido se "espacializa" para crear un efecto de varios interlocutores, similar a una configuración de sonido envolvente, pero a través de auriculares.
Por ejemplo, en una película, el sonido de un automóvil puede comenzar detrás del usuario, avanzar y desaparecer en la distancia. En un chat de video, las voces se pueden separar y colocar alrededor del usuario, lo que facilita la identificación de los interlocutores.
Si tu contenido usa un formato de audio compatible, puedes agregar audio espacial a tu app a partir de Android 13 (nivel de API 33).
Consulta sobre las funciones
Usa la clase Spatializer
para consultar las capacidades y el comportamiento de espacialización del dispositivo. Comienza por recuperar una instancia de Spatializer
de AudioManager
:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
Después de obtener el Spatializer
, verifica las cuatro condiciones que deben cumplirse para que el dispositivo emita audio espacializado:
Criterios | Marcar |
---|---|
¿El dispositivo admite la espacialización? |
getImmersiveAudioLevel() no es SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
¿Está disponible la espacialización? La disponibilidad depende de la compatibilidad con el enrutamiento de salida de audio actual. |
isAvailable() es true . |
¿La espacialización está habilitada? | isEnabled() es true |
¿Se puede espacializar una pista de audio con los parámetros determinados? | canBeSpatialized() es true . |
Es posible que no se cumplan estas condiciones, por ejemplo, si la espacialización no está disponible para la pista de audio actual o si está inhabilitada por completo en el dispositivo de salida de audio.
Monitoreo de cabeza
Con los auriculares compatibles, la plataforma puede ajustar la espacialización del audio según la posición de la cabeza del usuario. Para verificar si hay un dispositivo de seguimiento de la cabeza disponible para la enrutación de salida de audio actual, llama a isHeadTrackerAvailable()
.
Contenido compatible
Spatializer.canBeSpatialized()
indica si el audio con las propiedades determinadas se puede espacializar con el enrutamiento actual del dispositivo de salida. Este método toma un AudioAttributes
y un AudioFormat
, que se describen con más detalle a continuación.
AudioAttributes
Un objeto AudioAttributes
describe el uso de una transmisión de audio (por ejemplo, audio de juegos o contenido multimedia estándar), junto con sus comportamientos de reproducción y el tipo de contenido.
Cuando llames a canBeSpatialized()
, usa la misma instancia de AudioAttributes
que se configuró para tu Player
. Por ejemplo, si usas la biblioteca de Jetpack Media3 y no personalizaste AudioAttributes
, usa AudioAttributes.DEFAULT
.
Inhabilitando el audio espacial
Para indicar que tu contenido ya se espacializó, llama a setIsContentSpatialized(true)
para que el audio no se procese dos veces. Como alternativa, llama a setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
para ajustar el comportamiento de espacialización y, así, inhabilitarla por completo.
AudioFormat
Un objeto AudioFormat
describe detalles sobre el formato y la configuración de canales de una pista de audio.
Cuando crees una instancia de AudioFormat
para pasar a canBeSpatialized()
, configura la codificación con el mismo formato de salida que se espera del decodificador. También debes establecer una máscara de canal que coincida con la configuración del canal del contenido. Consulta la sección Comportamiento de espacialización predeterminado para obtener orientación sobre los valores específicos que debes usar.
Escucha los cambios en Spatializer
Para detectar cambios en el estado de Spatializer
, puedes agregar un objeto de escucha con Spatializer.addOnSpatializerStateChangedListener()
.
Del mismo modo, para detectar cambios en la disponibilidad de un dispositivo de seguimiento de la cabeza, llama a Spatializer.addOnHeadTrackerAvailableListener()
.
Esto puede ser útil si deseas ajustar la selección de pistas durante la reproducción con las devoluciones de llamada del objeto de escucha. Por ejemplo, cuando un usuario conecta o desconecta los auriculares del dispositivo, la devolución de llamada de onSpatializerAvailableChanged
indica si el efecto de espacializador está disponible para la nueva enrutación de salida de audio. En este punto, puedes considerar actualizar la lógica de selección de pistas del reproductor para que coincida con las nuevas capacidades del dispositivo. Para obtener más información sobre el comportamiento de selección de pistas de ExoPlayer, consulta la sección ExoPlayer y audio espacial.
ExoPlayer y audio espacial
Las versiones recientes de ExoPlayer facilitan la adopción del audio espacial. Si usas la biblioteca independiente de ExoPlayer (nombre del paquete com.google.android.exoplayer2
), la versión 2.17 configura la plataforma para que genere audio espacializado, y la versión 2.18 presenta restricciones de recuento de canales de audio.
Si usas el módulo ExoPlayer de la biblioteca Media3 (nombre del paquete androidx.media3
), las versiones 1.0.0-beta01
y posteriores incluyen estas mismas actualizaciones.
Después de actualizar la dependencia de ExoPlayer a la versión más reciente, tu app solo necesita incluir contenido que se pueda espacializar.
Restricciones de recuento de canales de audio
Cuando se cumplen las cuatro condiciones del audio espacial, ExoPlayer elige una pista de audio multicanal. De lo contrario, ExoPlayer elige una pista estéreo.
Si cambian las propiedades Spatializer
, ExoPlayer activará una nueva selección de pistas para elegir una pista de audio que coincida con las propiedades actuales. Ten en cuenta que esta nueva selección de pista puede causar un período de rebuffering breve.
Para inhabilitar las restricciones de recuento de canales de audio, establece los parámetros de selección de pistas en el reproductor como se muestra a continuación:
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
Del mismo modo, puedes actualizar los parámetros de un selector de pistas existente para inhabilitar las restricciones de recuento de canales de audio de la siguiente manera:
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() );
Con las restricciones de recuento de canales de audio inhabilitadas, si el contenido tiene varias pistas de audio, ExoPlayer selecciona inicialmente la pista que tiene la mayor cantidad de canales y se puede reproducir desde el dispositivo. Por ejemplo, si el contenido contiene una pista de audio multicanal y una pista de audio estéreo, y el dispositivo admite la reproducción de ambas, ExoPlayer selecciona la pista multicanal. Consulta Selección de pistas de audio para obtener detalles sobre cómo personalizar este comportamiento.
Selección de pistas de audio
Cuando se inhabilita el comportamiento de las restricciones de recuento de canales de audio de ExoPlayer, este no selecciona automáticamente una pista de audio que coincida con las propiedades del espacializador del dispositivo. En su lugar, puedes personalizar la lógica de selección de pistas de ExoPlayer configurando los parámetros de selección de pistas antes o durante la reproducción. De forma predeterminada, ExoPlayer selecciona pistas de audio que son iguales a la pista inicial en cuanto al tipo de MIME (codificación), la cantidad de canales y la tasa de muestreo.
Cómo cambiar los parámetros de selección de pistas
Para cambiar los parámetros de selección de pistas de ExoPlayer, usa Player.setTrackSelectionParameters()
.
Del mismo modo, puedes obtener los parámetros actuales de ExoPlayer con Player.getTrackSelectionParameters()
.
Por ejemplo, para seleccionar una pista de audio estéreo durante la reproducción, haz lo siguiente:
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
Ten en cuenta que cambiar los parámetros de selección de pistas durante la reproducción puede provocar una interrupción. Hay más información para ajustar los parámetros de selección de pistas del reproductor en la sección selección de pistas de la documentación de ExoPlayer.
Comportamiento de espacialización predeterminado
El comportamiento de espacialización predeterminado en Android incluye los siguientes comportamientos que los OEMs pueden personalizar:
Solo el contenido multicanal está espacializado, no el contenido estéreo. Si no usas ExoPlayer, según el formato de tu contenido de audio multicanal, es posible que debas configurar la cantidad máxima de canales que puede entregar un decodificador de audio a un número grande. Esto garantiza que el decodificador de audio genere PCM multicanal para que la plataforma lo espacialice.
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);
Para ver un ejemplo en acción, consulta
MediaCodecAudioRenderer.java
de ExoPlayer. Para desactivar la espacialización por tu cuenta, independientemente de la personalización del OEM, consulta Cómo inhabilitar el audio espacial.AudioAttributes
: El audio es apto para la espacialización siusage
está configurado comoUSAGE_MEDIA
oUSAGE_GAME
.AudioFormat
: Usa una máscara de canal que contenga al menos los canalesAudioFormat.CHANNEL_OUT_QUAD
(frontal izquierdo, frontal derecho, posterior izquierdo y posterior derecho) para que el audio sea apto para la espacialización. En el siguiente ejemplo, usamosAudioFormat.CHANNEL_OUT_5POINT1
para una pista de audio 5.1. Para una pista de audio estéreo, usaAudioFormat.CHANNEL_OUT_STEREO
.Si usas Media3, puedes usar
Util.getAudioTrackChannelConfig(int channelCount)
para convertir un recuento de canales en una máscara de canales.Además, establece la codificación en
AudioFormat.ENCODING_PCM_16BIT
si configuraste el decodificador para que genere PCM multicanal.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();
Cómo probar el audio espacial
Asegúrate de que el audio espacial esté habilitado en tu dispositivo de prueba:
- En el caso de auriculares con cable, ve a Configuración del sistema > Sonido y vibración > Audio espacial.
- Para auriculares inalámbricos, ve a Configuración del sistema > Dispositivos conectados > Ícono de ajustes del dispositivo inalámbrico > Audio espacial.
Para verificar la disponibilidad del audio espacial para la planificación de ruta actual, ejecuta el comando adb shell dumpsys audio
en tu dispositivo. Deberías ver los siguientes parámetros en el resultado mientras la reproducción esté activa:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)