Le son spatial est une expérience audio immersive qui permet à vos utilisateurs de plonger au cœur de l'action, pour un son toujours plus réaliste. Le son est "spatialisé" pour créer un effet multi-enceintes, semblable à une configuration de son surround mais avec un casque.
Par exemple, dans un film, le son d'une voiture peut commencer derrière l'utilisateur, se déplacer vers l'avant et s'éloigner au loin. Lors d'un appel vidéo, les voix peuvent être séparées et placées autour de l'utilisateur, ce qui permet d'identifier plus facilement les personnes qui parlent.
Si votre contenu utilise un format audio compatible, vous pouvez ajouter le son spatial à votre application à partir d'Android 13 (niveau d'API 33).
Requête pour les fonctionnalités
Utilisez la Spatializer classe pour
interroger les fonctionnalités et le comportement de spatialisation de l'appareil. Commencez par récupérer
une instance de Spatializer à partir de
AudioManager :
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
Une fois que vous avez obtenu le Spatializer, vérifiez les quatre conditions qui doivent être remplies
pour que l'appareil génère un son spatialisé :
| Critères | Vérifier |
|---|---|
| L'appareil est-il compatible avec la spatialisation ? |
getImmersiveAudioLevel() n'est pas SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
| La spatialisation est-elle disponible ? La disponibilité dépend de la compatibilité avec le routage de sortie audio actuel. |
isAvailable() est true |
| La spatialisation est-elle activée ? | isEnabled() est true |
| Une piste audio avec les paramètres donnés peut-elle être spatialisée ? | canBeSpatialized() est true |
Ces conditions peuvent ne pas être remplies, par exemple si la spatialisation n'est pas disponible pour la piste audio actuelle ou si elle est complètement désactivée sur l'appareil de sortie audio.
Suivi de la tête
Avec les casques compatibles, la plate-forme peut ajuster la spatialisation
de l'audio en fonction de la position de la tête de l'utilisateur. Pour vérifier si un dispositif de suivi de la tête est
disponible pour le routage de sortie audio actuel, appelez
isHeadTrackerAvailable().
Contenu compatible
Spatializer.canBeSpatialized()
indique si l'audio avec les propriétés données peut être spatialisé avec le
routage de l'appareil de sortie actuel. Cette méthode prend un AudioAttributes
et un AudioFormat, qui sont
décrits plus en détail ci-dessous.
AudioAttributes
Un objet AudioAttributes
décrit l'utilisation d'un
flux audio (par exemple, l'audio d'un jeu
ou un contenu multimédia standard),
ainsi que ses comportements de lecture et son type de contenu.
Lorsque vous appelez canBeSpatialized(), utilisez la même
AudioAttributes instance que celle définie pour votre Player. Par exemple, si
vous utilisez la bibliothèque Jetpack Media3 et que vous n'avez pas personnalisé les
AudioAttributes, utilisez AudioAttributes.DEFAULT.
Désactiver le son spatial
Pour indiquer que votre contenu a déjà été spatialisé, appelez
setIsContentSpatialized(true)
afin que l'audio ne soit pas traité deux fois. Vous pouvez également ajuster le
comportement de spatialisation pour désactiver complètement la spatialisation en appelant
setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER).
AudioFormat
Un AudioFormat objet décrit
des informations sur le format et la configuration des canaux d'une piste audio.
Lorsque vous instanciez le AudioFormat à transmettre à canBeSpatialized(),
définissez l'encodage
sur le même que le format de sortie attendu du décodeur. Vous devez également définir
un masque de canal
qui correspond à la configuration des canaux de votre contenu. Pour obtenir des conseils sur les
valeurs spécifiques à utiliser, consultez la section
Comportement de spatialisation par défaut.
Écouter les modifications apportées au Spatializer
Pour écouter les modifications apportées à l'état du Spatializer, vous pouvez ajouter un écouteur
avec Spatializer.addOnSpatializerStateChangedListener().
De même, pour écouter les modifications apportées à la disponibilité d'un dispositif de suivi de la tête,
appelez Spatializer.addOnHeadTrackerAvailableListener().
Cela peut être utile si vous souhaitez ajuster la sélection de votre piste pendant la lecture
à l'aide des rappels de l'écouteur. Par exemple, lorsqu'un utilisateur connecte ou déconnecte son
casque de l'appareil, le onSpatializerAvailableChanged
rappel indique si l'effet de spatialisation est disponible pour le nouveau
routage de sortie audio. À ce stade, vous pouvez envisager de mettre à jour la logique de sélection de piste de votre lecteur
pour qu'elle corresponde aux nouvelles fonctionnalités de l'appareil. Pour en savoir plus sur le comportement de sélection de piste d'ExoPlayer, consultez la section ExoPlayer et son spatial.
ExoPlayer et son spatial
Les dernières versions d'ExoPlayer facilitent l'adoption du son spatial. Si vous utilisez
la bibliothèque ExoPlayer autonome (nom de package com.google.android.exoplayer2),
la version 2.17 configure la plate-forme pour générer un son spatialisé, et la version
2.18 introduit des contraintes sur le nombre de canaux audio.
Si vous utilisez le module ExoPlayer de la bibliothèque Media3 (nom de package
androidx.media3), les versions 1.0.0-beta01
et ultérieures incluent ces mêmes mises à jour.
Une fois que vous avez mis à jour votre dépendance ExoPlayer vers la dernière version, votre application n'a plus qu'à inclure du contenu qui peut être spatialisé.
Contraintes sur le nombre de canaux audio
Lorsque les quatre conditions pour le son spatial sont remplies, ExoPlayer choisit
une piste audio multicanal. Sinon, ExoPlayer choisit une piste stéréo.
Si les Spatializer propriétés changent, ExoPlayer
déclenche une nouvelle sélection de piste pour sélectionner une piste audio qui correspond aux
propriétés actuelles. Notez que cette nouvelle sélection de piste peut entraîner une courte
période de mise en mémoire tampon.
Pour désactiver les contraintes sur le nombre de canaux audio, définissez les paramètres de sélection de piste sur le lecteur comme indiqué ci-dessous :
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
De même, vous pouvez mettre à jour les paramètres d'un sélecteur de piste existant pour désactiver les contraintes sur le nombre de canaux audio comme suit :
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() );
Lorsque les contraintes sur le nombre de canaux audio sont désactivées, si le contenu comporte plusieurs pistes audio, ExoPlayer sélectionne initialement la piste qui comporte le plus grand nombre de canaux et qui peut être lue à partir de l'appareil. Par exemple, si le contenu contient une piste audio multicanal et une piste audio stéréo, et que l'appareil est compatible avec la lecture des deux, ExoPlayer sélectionne la piste multicanal. Pour en savoir plus sur la personnalisation de ce comportement, consultez la section Sélection de piste audio.
Sélection de piste audio
Lorsque le comportement de contrainte sur le nombre de canaux audio d'ExoPlayer est désactivé, ExoPlayer ne sélectionne pas automatiquement une piste audio qui correspond aux propriétés du spatialiseur de l'appareil. Vous pouvez plutôt personnaliser la logique de sélection de piste d'ExoPlayer en définissant des paramètres de sélection de piste avant ou pendant la lecture. Par défaut, ExoPlayer sélectionne les pistes audio qui sont identiques à la piste initiale en ce qui concerne le type MIME (encodage), le nombre de canaux et la fréquence d'échantillonnage.
Modifier les paramètres de sélection de piste
Pour modifier les paramètres de sélection de piste d'ExoPlayer, utilisez
Player.setTrackSelectionParameters().
De même, vous pouvez obtenir les paramètres actuels d'ExoPlayer avec
Player.getTrackSelectionParameters().
Par exemple, pour sélectionner une piste audio stéréo en milieu de lecture :
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
Notez que la modification des paramètres de sélection de piste en milieu de lecture peut entraîner une interruption de la lecture. Pour en savoir plus sur le réglage des paramètres de sélection de piste du lecteur, consultez la section Sélection de piste de la documentation ExoPlayer.
Comportement de spatialisation par défaut
Le comportement de spatialisation par défaut dans Android inclut les comportements suivants qui peuvent être personnalisés par les OEM :
Seul le contenu multicanal est spatialisé, et non le contenu stéréo. Si vous n'utilisez pas ExoPlayer, en fonction du format de votre contenu audio multicanal, vous devrez peut-être configurer le nombre maximal de canaux pouvant être générés par un décodeur audio sur un nombre élevé. Cela garantit que le décodeur audio génère un PCM multicanal pour que la plate-forme puisse le spatialiser.
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);
Pour voir un exemple en action, consultez
MediaCodecAudioRenderer.javad'ExoPlayer. Pour désactiver vous-même la spatialisation, quelle que soit la personnalisation de l'OEM, consultez la section Désactiver le son spatial.AudioAttributes: l'audio est éligible à la spatialisation si l'usageest défini surUSAGE_MEDIAouUSAGE_GAME.AudioFormat: utilisez un masque de canal qui contient au moins les canauxAudioFormat.CHANNEL_OUT_QUAD(avant gauche, avant droit, arrière gauche et arrière droit) pour que l'audio soit éligible à la spatialisation. Dans l'exemple ci-dessous, nous utilisonsAudioFormat.CHANNEL_OUT_5POINT1pour une piste audio 5.1. Pour une piste audio stéréo, utilisezAudioFormat.CHANNEL_OUT_STEREO.Si vous utilisez Media3, vous pouvez utiliser
Util.getAudioTrackChannelConfig(int channelCount)pour convertir un nombre de canaux en masque de canal.De plus, définissez l'encodage sur
AudioFormat.ENCODING_PCM_16BITsi vous avez configuré le décodeur pour générer un 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();
Tester le son spatial
Assurez-vous que le son spatial est activé sur votre appareil de test :
- Pour les casques filaires, accédez à Paramètres système > Son et vibration > Son spatial.
- Pour les casques sans fil, accédez à Paramètres système > Appareils connectés > Icône en forme d'engrenage de votre appareil sans fil > Son spatial.
Pour vérifier la disponibilité du son spatial pour le routage actuel, exécutez la
adb shell dumpsys audio commande sur votre appareil. Les paramètres suivants devraient s'afficher dans la sortie pendant la lecture :
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)