Ajouter le son spatial à votre application XR

Appareils XR concernés
Ces conseils vous aideront à créer des expériences pour ces types d'appareils XR.
Casques XR
Lunettes XR filaires

Les fonctionnalités de son spatial de Jetpack SceneCore vous permettent de créer des expériences audio immersives dans vos applications Android XR.

Le son spatial simule la façon dont les utilisateurs perçoivent le son dans un environnement 3D. Il donne l'impression que le son provient de toutes les directions, y compris au-dessus et en dessous de l'utilisateur. Pour ce faire, le système simule une ou plusieurs "enceintes virtuelles" à des emplacements spécifiques dans l'espace 3D.

Les applications existantes qui n'ont pas été conçues ni modifiées pour Android XR voient leur audio automatiquement spatialisé dans Android XR. Lorsque l'utilisateur se déplace dans son espace, tout l'audio de l'application est émis depuis le panneau sur lequel l'UI de l'application est affichée. Par exemple, si un minuteur se déclenche dans une application d'horloge, le son semblera provenir de la position du panneau de l'application. Android XR modifiera automatiquement le son pour un réalisme positionnel. Par exemple, la distance perçue entre le panneau de l'application et l'utilisateur aura un impact subtil sur le volume audio pour une plus grande sensation de réalisme.

Pour en savoir plus sur la façon dont les applications existantes affichent le son spatial, consultez Ajouter un son stéréo et surround à votre application sur cette page.

Si vous optimisez votre application pour la XR, Jetpack SceneCore fournit des outils de personnalisation avancée du son spatial. Vous pouvez positionner précisément les sons dans l'environnement 3D, utiliser l'audio ambisonique pour des champs sonores réalistes et profiter de l'intégration du son surround.

Types de son spatial disponibles dans Android XR

Android XR est compatible avec le son positionnel, stéréo, surround et ambisonique.

Audio positionnel

Un son positionnel peut être placé de manière à être diffusé à partir d'un point spécifique de l'espace 3D. Par exemple, vous pouvez avoir un modèle 3D d'un chien qui aboie dans un coin de votre environnement virtuel. Vous pouvez avoir plusieurs entités émettant du son à partir de chacune de leurs positions respectives. Pour afficher l'audio positionnel, les fichiers doivent être au format mono ou stéréo.

Son stéréo et surround spatialisé

Tous les formats multimédias Android sont compatibles avec le son positionnel, stéréo et surround. En plus de ces formats, les appareils Android XR peuvent être compatibles avec les formats audio Dolby Atmos, Dolby Digital et Dolby Digital+.

Le son stéréo fait référence aux formats audio à deux canaux, et le son surround aux formats audio à plus de deux canaux, tels que les configurations de son surround 5.1 ou de son surround 7.1. Les données audio de chaque canal sont associées à un locuteur. Par exemple, lors de la lecture de musique en stéréo, le canal de l'enceinte gauche peut émettre des pistes d'instruments différentes de celles de l'enceinte droite.

Le son surround est souvent utilisé dans les films et les séries TV pour renforcer le réalisme et l'immersion grâce à l'utilisation de plusieurs canaux d'enceintes. Par exemple, les dialogues sont souvent diffusés par un canal d'enceinte central, tandis que le son d'un hélicoptère en vol peut utiliser différents canaux en séquence pour donner l'impression que l'hélicoptère vole dans votre espace 3D.

Audio ambisonique

L'audio ambisonique (ou ambisonie) est comme une skybox pour l'audio, offrant un paysage sonore immersif à vos utilisateurs. Utilisez l'ambisonie pour les sons d'ambiance ou d'autres scénarios dans lesquels vous souhaitez reproduire un champ sonore sphérique complet qui entoure l'auditeur. Android XR est compatible avec le format audio ambisonique AmbiX en ambisonie de premier, deuxième et troisième ordre. Nous vous recommandons les types de fichiers Opus (.ogg) et PCM/Wave (.wav).

Utiliser le son spatial avec Jetpack SceneCore

Pour implémenter le son spatial avec Jetpack SceneCore, vous devez vérifier les fonctionnalités spatiales et choisir une API pour charger le son spatial.

Vérifier les fonctionnalités spatiales

Avant d'utiliser les fonctionnalités de son spatial, vérifiez que l'Session est compatible avec le son spatial. Dans tous les extraits de code des sections suivantes, les fonctionnalités sont vérifiées avant de tenter de lire du son spatialisé.

Charger le son spatial

Vous pouvez utiliser l'une des API suivantes pour charger du son spatial à utiliser dans Jetpack SceneCore.

  • SoundPool : idéal pour les effets sonores courts de moins de 1 Mo. Ils sont chargés à l'avance et les sons peuvent être utilisés de manière répétée. C'est un excellent moyen de charger l'audio pour l'audio positionnel.
  • ExoPlayer : idéal pour charger des contenus audio stéréo et surround, tels que de la musique et des vidéos. Permet également la lecture de contenus multimédias en arrière-plan.
  • MediaPlayer : fournit le moyen le plus simple de charger du contenu audio ambisonique.
  • AudioTrack : offre un contrôle optimal sur le chargement des données audio. Permet d'écrire directement des tampons audio ou si vous avez synthétisé ou décodé vos propres fichiers audio.

Vérifier la compatibilité des formats multimédias

Certains formats multimédias sont compatibles avec la plate-forme Android. Toutefois, un appareil Android XR particulier peut être compatible avec d'autres formats, comme Dolby Atmos. Pour interroger la compatibilité avec les formats multimédias, utilisez AudioCapabilities d'ExoPlayer :

val audioCapabilities = AudioCapabilities.getCapabilities(
    context,
    androidx.media3.common.AudioAttributes.DEFAULT,
    null,
    emptyList()
)

if (audioCapabilities.supportsEncoding(C.ENCODING_AC3)) {
    // Device supports playback of the Dolby Digital media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) {
    // Device supports playback of the Dolby Digital Plus media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3_JOC)) {
    // Device supports playback of the Dolby Digital Plus with Dolby Atmos media format.
}

La vérification de ces fonctionnalités peut potentiellement impliquer des appels bloquants et ne doit pas être appelée sur le thread principal.

Ajouter l'audio positionnel à votre application

Les sources sonores positionnelles sont définies par PointSourceParams et un Entity associé. La position et l'orientation de Entity déterminent l'emplacement de l'affichage de PointSourceParams dans l'espace 3D. Appelez setPointSourceParams sur SpatialMediaPlayer pour définir PointSourceParams et son entity associé sur une instance MediaPlayer.

Exemple d'audio positionnel

L'exemple suivant charge un fichier audio d'effet sonore dans un pool de sons et le lit à la position de l'Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.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()

    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,
                entity = entity,
                soundPool = soundPool,
                soundID = pointSoundId,
                params = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

Points clés à retenir concernant le code

  • La première étape consiste à vérifier si les fonctionnalités de son spatial sont disponibles à l'aide de spatialCapabilities.
  • Définir contentType sur CONTENT_TYPE_SONIFICATION et usage sur USAGE_ASSISTANCE_SONIFICATION permet au système de traiter ce fichier audio comme un effet sonore.
  • L'exemple précédent charge le fichier audio dans le pool juste avant de l'utiliser pour que le code reste regroupé, par souci de simplicité. Idéalement, vous devez charger tous vos effets sonores de manière asynchrone lorsque vous chargez votre application, afin que tous les fichiers audio soient disponibles dans le pool lorsque vous en avez besoin.

Ajouter le son stéréo et surround à votre application

Pour ajouter du son stéréo et surround à votre application, nous vous recommandons d'utiliser Exoplayer. Pour en savoir plus sur l'utilisation du son spatial avec Exoplayer, consultez le guide sur le son spatial.

Positionnement des enceintes stéréo et son surround

Avec le positionnement des enceintes de son surround, les enceintes de son surround virtuel sont positionnées et orientées par rapport à une enceinte centrale, autour de l'utilisateur, dans une configuration ITU standard.

Par défaut, l'enceinte du canal central est placée sur l'mainPanelEntity de l'application. Cela inclut les applications mobiles dont l'audio est spatialisé automatiquement par Android XR.

Pour la stéréo, l'emplacement des enceintes est similaire à celui du son surround, sauf que seuls les canaux gauche et droit sont positionnés respectivement sur les côtés gauche et droit du panneau.

Si vous avez plusieurs panneaux et que vous souhaitez choisir celui qui émet l'audio, ou si vous souhaitez que l'audio stéréo ou surround soit rendu par rapport à un autre Entity, vous pouvez utiliser PointSourceAttributes pour définir l'emplacement du canal central. Les canaux restants seront placés comme mentionné précédemment. Dans ce cas, vous devez également utiliser MediaPlayer.

Lorsque l'utilisateur se déplace dans l'espace, les enceintes virtuelles stéréo et son surround se déplacent et s'ajustent pour s'assurer qu'elles sont toujours dans une position optimale.

Si vous avez configuré MediaPlayer ou ExoPlayer pour continuer à lire du son stéréo ou surround en arrière-plan, le positionnement des enceintes virtuelles sera modifié lorsque l'application sera en arrière-plan. Comme il n'y a pas de panneau ni d'autre point dans l'espace auquel ancrer le son, le son spatial se déplace avec l'utilisateur (en d'autres termes, il est "verrouillé sur la tête").

Exemple de son surround

L'exemple suivant charge un fichier audio 5.1 à l'aide de MediaPlayer et définit le canal central du fichier sur Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceParams()

    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,
        entity = session.scene.mainPanelEntity,
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

Points clés à retenir concernant le code

Ajouter des champs sonores ambisoniques à votre application

Le moyen le plus simple de lire des champs sonores ambisoniques consiste à charger le fichier avec un MediaPlayer. Comme le son ambisonique s'applique à l'ensemble du paysage sonore, vous n'avez pas besoin de spécifier un Entity pour indiquer une position. À la place, vous créez une instance de SoundFieldAttributes avec l'ordre ambisonique approprié spécifiant le nombre de canaux.

Exemple d'Ambionics

L'exemple suivant lit un champ sonore ambisonique à l'aide de MediaPlayer.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AmbisonicsOrder.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
}

Points clés à retenir concernant le code

  • Comme pour les extraits précédents, la première étape consiste à vérifier si les fonctionnalités de son spatial sont disponibles à l'aide de spatialCapabilities.
  • Le contentType et l'utilisation sont fournis à titre purement informatif.
  • SpatializerConstants.AmbisonicsOrder.FIRST_ORDER indique à SceneCore que le fichier de champ sonore définit quatre canaux.