Las funciones de audio espacial en Jetpack SceneCore te permiten crear experiencias de audio inmersivas en tus aplicaciones de realidad extendida para Android.
El audio espacial simula cómo los usuarios perciben el sonido en un entorno 3D. Crea la sensación de que el sonido emana de todas las direcciones, incluso por encima y por debajo del usuario. El sistema simula uno o más "parlantes virtuales" en ubicaciones específicas del espacio 3D.
Las apps existentes que no se diseñaron ni modificaron para Android XR tienen su audio espacializado automáticamente en Android XR. A medida que el usuario se mueve por su espacio, todo el audio de la app se emitirá desde el panel en el que se renderiza la IU de la app. Por ejemplo, si suena un temporizador de una app de reloj, el audio sonará como si proviniera de la posición del panel de la app. Android XR alterará automáticamente el sonido para lograr un realismo posicional. Por ejemplo, la distancia percibida entre el panel de la app y el usuario afectará sutilmente el volumen del audio para generar una mayor sensación de realismo.
Para obtener más información sobre cómo las apps existentes renderizan el audio espacial, consulta Agrega sonido estéreo y envolvente a tu app en esta página.
Si optimizas tu app para XR, Jetpack SceneCore proporciona herramientas para la personalización avanzada del audio espacial. Puedes posicionar los sonidos con precisión en el entorno 3D, usar audio ambisónico para obtener campos de sonido realistas y aprovechar la integración de sonido envolvente integrada.
Tipos de sonido espacial disponibles en Android XR
Android XR admite audio posicional, estéreo, envolvente y ambisónico.
Audio posicional
El audio posicional se puede colocar para que se reproduzca desde un punto específico en el espacio 3D. Por ejemplo, puedes tener un modelo 3D de un perro ladrando en la esquina de tu entorno virtual. Puedes tener varias entidades que emitan sonido desde sus respectivas posiciones. Para renderizar audio posicional, los archivos deben ser mono o estéreo.
Sonido envolvente y estéreo espacializado
Todos los formatos de medios de Android son compatibles con el sonido posicional, estéreo y envolvente.
El audio estéreo hace referencia a los formatos de audio con dos canales, y el sonido envolvente, a los formatos de audio con más de dos canales, como las configuraciones de sonido envolvente 5.1 o sonido envolvente 7.1. Los datos de sonido de cada canal se asocian con un altavoz. Por ejemplo, cuando se reproduce música en estéreo, el canal del altavoz izquierdo puede emitir pistas de instrumentos diferentes a las del derecho.
El sonido envolvente se usa a menudo en películas y programas de televisión para mejorar el realismo y la inmersión a través del uso de varios canales de bocinas. Por ejemplo, el diálogo suele reproducirse desde un canal de altavoz central, mientras que el sonido de un helicóptero volando puede usar diferentes canales en secuencia para dar la sensación de que el helicóptero está volando alrededor de tu espacio 3D.
Audio ambisónico
El audio ambisónico (o ambisonics) es como una skybox para el audio, ya que proporciona un paisaje sonoro envolvente para los usuarios. Usa ambisonics para los sonidos ambientales de fondo o en otras situaciones en las que quieras replicar un campo de sonido esférico completo que rodee al usuario. Android XR admite el formato de audio ambisónico AmbiX en ambisónico de primer, segundo y tercer orden. Te recomendamos los tipos de archivo Opus (.ogg
) y PCM/Wave (.wav
).
Cómo usar el audio espacial con Jetpack SceneCore
Para implementar el audio espacial con Jetpack SceneCore, se deben verificar las capacidades espaciales y elegir una API para cargar el audio espacial.
Verifica las capacidades espaciales
Antes de usar las funciones de audio espacial, verifica que el Session
sea compatible con el audio espacial. En todos los fragmentos de código de las siguientes secciones, se verifican las capacidades antes de intentar reproducir audio espacializado.
Cargar audio espacial
Puedes usar cualquiera de las siguientes APIs para cargar audio espacial y usarlo en Jetpack SceneCore.
SoundPool
: Son ideales para efectos de sonido cortos de menos de 1 MB, se cargan con anticipación y se pueden usar repetidamente. Esta es una excelente manera de cargar audio para el audio posicional.ExoPlayer
: Ideal para cargar contenido de sonido estéreo y envolvente, como música y videos. También permite la reproducción de contenido multimedia en segundo plano.MediaPlayer
: Proporciona la forma más sencilla de cargar audio ambisónico.AudioTrack
: Proporciona el mayor control sobre cómo cargar los datos de audio. Permite escribir directamente búferes de audio o si sintetizaste o decodificaste tus propios archivos de audio.
Agrega audio posicional a tu app
Las fuentes de sonido posicionales se definen con PointSourceParams
y un Entity
asociado. La posición y la orientación del Entity
determinan dónde se renderiza el PointSourceParams
en el espacio 3D.
Ejemplo de audio posicional
En el siguiente ejemplo, se carga un archivo de audio de efecto de sonido en un grupo de sonidos y se reproduce en la posición del Entity
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO) ) { // The session has spatial audio capabilities val maxVolume = 1F val lowPriority = 0 val infiniteLoop = -1 val normalSpeed = 1F val soundPool = SoundPool.Builder() .setAudioAttributes( AudioAttributes.Builder() .setContentType(CONTENT_TYPE_SONIFICATION) .setUsage(USAGE_ASSISTANCE_SONIFICATION) .build() ) .build() val pointSource = PointSourceParams(entity) val soundEffect = appContext.assets.openFd("sounds/tiger_16db.mp3") val pointSoundId = soundPool.load(soundEffect, lowPriority) soundPool.setOnLoadCompleteListener { soundPool, sampleId, status -> // wait for the sound file to be loaded into the soundPool if (status == 0) { SpatialSoundPool.play( session = session, soundPool = soundPool, soundID = pointSoundId, params = pointSource, volume = maxVolume, priority = lowPriority, loop = infiniteLoop, rate = normalSpeed ) } } } else { // The session does not have spatial audio capabilities }
Puntos clave sobre el código
- El primer paso es verificar si las capacidades de audio espacial están disponibles actualmente con
spatialCapabilities
. - Si configuras contentType como
CONTENT_TYPE_SONIFICATION
y usage comoUSAGE_ASSISTANCE_SONIFICATION
, el sistema tratará este archivo de audio como un efecto de sonido. - En el ejemplo anterior, se carga el archivo de audio en el grupo inmediatamente antes de usarlo para mantener el código unido y simplificarlo. Lo ideal es que cargues todos tus efectos de sonido de forma asíncrona a medida que cargas tu app, de modo que todos los archivos de audio estén disponibles en el grupo cuando los necesites.
Agrega sonido estéreo y envolvente a tu app
La forma recomendada de agregar sonido estéreo y envolvente a tu app es usar Exoplayer
. Para obtener más información sobre cómo usar el audio espacial con Exoplayer
, consulta la guía de audio espacial.
Posicionamiento de las bocinas de sonido envolvente y estéreo
Con el posicionamiento de bocinas de sonido envolvente, las bocinas virtuales de sonido envolvente se posicionan y orientan en relación con una bocina central, alrededor del usuario en una configuración de la ITU estándar.
De forma predeterminada, la bocina del canal central se coloca en el mainPanelEntity
de la app. Esto incluye las apps para dispositivos móviles cuyo audio se espacializa automáticamente con Android XR.
En el caso del sonido estéreo, la colocación de las bocinas es similar a la del sonido envolvente, excepto que solo los canales izquierdo y derecho se colocan en el lado izquierdo y derecho del panel, respectivamente.
Si tienes varios paneles y quieres elegir cuál emite audio, o si quieres que el audio estéreo o envolvente se renderice en relación con otro Entity
, puedes usar PointSourceAttributes
para definir la ubicación del canal central. Los canales restantes se colocarán como se mencionó anteriormente. En estas situaciones, también debes usar MediaPlayer
.
A medida que el usuario se mueve por su espacio, las bocinas virtuales de sonido estéreo y envolvente se moverán y ajustarán para garantizar que siempre estén en una posición óptima.
Si configuraste MediaPlayer
o ExoPlayer
para que se siga reproduciendo sonido estéreo o envolvente en segundo plano, la posición de las bocinas virtuales se modificará cuando la app pase a segundo plano. Como no hay un panel ni otro punto en el espacio al que anclar el sonido, el audio espacial se mueve con el usuario (en otras palabras, está "bloqueado en la cabeza").
Ejemplo de sonido envolvente
En el siguiente ejemplo, se carga un archivo de audio 5.1 con MediaPlayer
y se configura el canal central del archivo como un Entity
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) { // The session has spatial audio capabilities val pointSourceAttributes = PointSourceParams(session.scene.mainPanelEntity) val mediaPlayer = MediaPlayer() val fivePointOneAudio = appContext.assets.openFd("sounds/aac_51.ogg") mediaPlayer.reset() mediaPlayer.setDataSource(fivePointOneAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setPointSourceParams( session, mediaPlayer, pointSourceAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
Puntos clave sobre el código
- Al igual que en el ejemplo de audio posicional, el primer paso es verificar si las capacidades de audio espacial están disponibles con
spatialCapabilities
. - Si se configura
contentType
comoAudioAttributes.CONTENT_TYPE_MUSIC
y el uso comoAudioAttributes.USAGE_MEDIA
, el sistema tratará este archivo de audio como sonido envolvente.
Agrega campos de sonido ambisónico a tu app
La forma más sencilla de reproducir campos de sonido ambisónicos es cargar el archivo con un MediaPlayer
. Dado que el sonido ambisónico se aplica a todo el paisaje sonoro, no es necesario que especifiques un Entity
para proporcionar una posición. En su lugar, creas una instancia de SoundFieldAttributes
con el orden ambisónico adecuado que especifica la cantidad de canales.
Ejemplo de Ambionics
En el siguiente ejemplo, se reproduce un campo de sonido ambisónico con MediaPlayer
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) { // The session has spatial audio capabilities val soundFieldAttributes = SoundFieldAttributes(SpatializerConstants.AMBISONICS_ORDER_FIRST_ORDER) val mediaPlayer = MediaPlayer() val soundFieldAudio = appContext.assets.openFd("sounds/foa_basketball_16bit.wav") mediaPlayer.reset() mediaPlayer.setDataSource(soundFieldAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setSoundFieldAttributes( session, mediaPlayer, soundFieldAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
Puntos clave sobre el código
- Al igual que con los fragmentos anteriores, el primer paso es verificar si las capacidades de audio espacial están disponibles con
hasCapability()
. - El
contentType
y el uso son meramente informativos. AMBISONICS_ORDER_FIRST_ORDER
indica a SceneCore que el archivo de campo de sonido define cuatro canales.