Le son spatial est une expérience audio immersive qui place les utilisateurs au centre de l'action, ce qui rend votre contenu 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, avancer et reculer. Dans un chat vidéo, les voix peuvent être séparées et placées autour de l'utilisateur, ce qui facilite l'identification des locuteurs.
Si votre contenu utilise un format audio compatible, vous pouvez ajouter du son spatial à votre application à partir d'Android 13 (niveau d'API 33).
Requête pour des fonctionnalités
Utilisez la classe Spatializer
pour interroger les fonctionnalités de spatialisation et le comportement 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 vraies pour que l'appareil puisse générer du son spatialisé:
Critères | Vérifier |
---|---|
L'appareil est-il compatible avec la spatialisation ? |
getImmersiveAudioLevel() n'est pas SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
Le spatialisation est-il 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 |
Est-il possible de spatiser une piste audio avec les paramètres fournis ? | 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 le périphérique de sortie audio.
Suivi des mouvements de la tête
Avec les casques compatibles, la plate-forme peut ajuster la spatialisation du contenu audio en fonction de la position de la tête de l'utilisateur. Pour vérifier si un traceur de la tête est disponible pour le routage de la sortie audio actuel, appelez isHeadTrackerAvailable()
.
Contenus compatibles
Spatializer.canBeSpatialized()
indique si l'audio ayant les propriétés données peut être spatialisé avec le routage actuel de l'appareil de sortie. Cette méthode utilise un objet AudioAttributes
et un élément AudioFormat
, qui sont tous deux décrits plus en détail ci-dessous.
AudioAttributes
Un objet AudioAttributes
décrit l'utilisation d'un flux audio (par exemple, de l'audio de jeu ou d'un contenu multimédia standard), ainsi que ses comportements de lecture et son type de contenu.
Lorsque vous appelez canBeSpatialized()
, utilisez la même instance AudioAttributes
que celle définie pour votre Player
. Par exemple, si vous utilisez la bibliothèque Jetpack Media3 et que vous n'avez pas personnalisé AudioAttributes
, utilisez AudioAttributes.DEFAULT
.
Désactiver le son spatial
Pour indiquer que votre contenu a déjà été spatialisé, appelez setIsContentSpatialized(true)
afin que le contenu 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 objet AudioFormat
décrit en détail le format et la configuration des canaux d'une piste audio.
Lorsque vous instanciez le AudioFormat
à transmettre dans canBeSpatialized()
, définissez l'encodage sur le même format de sortie que le décodeur. Vous devez également définir un masque de chaîne correspondant à la configuration des chaînes de votre contenu. Reportez-vous à la section Comportement de spatialisation par défaut pour obtenir des conseils sur les valeurs spécifiques à utiliser.
Écouter les modifications apportées au Spatializer
Pour écouter les modifications de l'état de Spatializer
, vous pouvez ajouter un écouteur avec Spatializer.addOnSpatializerStateChangedListener()
.
De même, pour écouter les changements de disponibilité d'un Head Tracker, appelez Spatializer.addOnHeadTrackerAvailableListener()
.
Cela peut être utile si vous souhaitez ajuster la sélection de la 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 rappel onSpatializerAvailableChanged
indique si l'effet spatialisateur est disponible pour le nouveau routage de la sortie audio. À ce stade, vous pouvez envisager de mettre à jour la logique de sélection des titres de votre joueur pour qu'elle corresponde aux nouvelles fonctionnalités de l'appareil. Pour en savoir plus sur le comportement de sélection des pistes 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 la sortie audio spatialisée, tandis que la version 2.18 introduit des contraintes de nombre de canaux audio.
Si vous utilisez le module ExoPlayer de la bibliothèque Media3 (nom du package androidx.media3
), les versions 1.0.0-beta01
et ultérieures incluent ces mêmes mises à jour.
Après avoir mis à jour votre dépendance ExoPlayer vers la dernière version, votre application doit simplement inclure du contenu pouvant être spatialisé.
Contraintes liées au nombre de canaux audio
Lorsque les quatre conditions de son spatial sont remplies, ExoPlayer choisit une piste audio multicanal. Si ce n'est pas le cas, ExoPlayer choisit une piste stéréo à la place.
Si les propriétés Spatializer
changent, ExoPlayer déclenche une nouvelle sélection de piste pour sélectionner une piste audio correspondant aux propriétés actuelles. Notez que cette nouvelle sélection de piste peut entraîner une courte période de remise en mémoire tampon.
Pour désactiver les contraintes de nombre de canaux audio, définissez les paramètres de sélection des pistes 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 de 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 de nombre de canaux audio sont désactivées, si le contenu comporte plusieurs pistes audio, ExoPlayer sélectionne initialement la piste comportant le plus grand nombre de canaux et pouvant ê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 des pistes audio.
Sélection de piste audio
Lorsque le comportement des contraintes liées au nombre de canaux audio d'ExoPlayer est désactivé, ExoPlayer ne sélectionne pas automatiquement une piste audio correspondant aux propriétés du spatialisateur de l'appareil. À la place, vous pouvez personnaliser la logique de sélection des pistes d'ExoPlayer en définissant les paramètres de sélection des pistes avant ou pendant la lecture. Par défaut, ExoPlayer sélectionne les pistes audio identiques à la piste initiale en ce qui concerne le type MIME (encodage), le nombre de canaux et le taux d'échantillonnage.
Modifier les paramètres de sélection de la piste
Pour modifier les paramètres de sélection des pistes 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 cours 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 cours 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 des pistes de la documentation sur 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é, pas 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 qu'un décodeur audio peut générer en sortie vers un grand nombre de canaux. Cela garantit que le décodeur audio génère une sortie PCM multicanal pour la plate-forme de spatialisation.
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 obtenir un exemple concret, consultez
MediaCodecAudioRenderer.java
d'ExoPlayer. Pour désactiver vous-même la spatialisation, quelle que soit la personnalisation de l'OEM, consultez Désactiver le son spatial.AudioAttributes
: l'audio peut être spatialisé siusage
est défini surUSAGE_MEDIA
ouUSAGE_GAME
.AudioFormat
: utilisez un masque de canal contenant au moins les canauxAudioFormat.CHANNEL_OUT_QUAD
(avant gauche, avant droite, arrière-gauche et arrière-droite) pour que l'audio soit éligible à la spatialisation. Dans l'exemple ci-dessous, nous utilisonsAudioFormat.CHANNEL_OUT_5POINT1
pour 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.En outre, définissez l'encodage sur
AudioFormat.ENCODING_PCM_16BIT
si vous avez configuré le décodeur pour qu'il génère une sortie 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 vibreur > Son spatial.
- Pour les casques sans fil, accédez à Paramètres système > Appareils connectés > Icône en forme de roue dentée de votre appareil sans fil > Son spatial.
Pour vérifier la disponibilité du son spatial pour le routage actuel, exécutez la commande adb shell dumpsys audio
sur votre appareil. Lorsque la lecture est active, les paramètres suivants doivent s'afficher dans la sortie:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)