Des problèmes surviennent lorsque vous essayez d'accéder directement au périphérique audio USB à l'aide des API USB. Ces problèmes peuvent inclure: des problèmes de sécurité, la limitation de la lecture de contenus multimédias à partir d'autres applications, et la perte d'alarmes, de notifications et de sonneries sur les appareils USB.
Pour améliorer la lecture audio, configurez plutôt les attributs du mélangeur.
Configurer les attributs du mélangeur
À l'aide des API AudioMixerAttributes
, vous pouvez configurer votre application avec les attributs de mixage préférés via USB.
Lorsque la lecture de l'application correspond au format d'encodage, au masque de canal et au taux d'échantillonnage des attributs de mélangeur préférés, la lecture est associée au flux de sortie audio dont le mélangeur est configuré avec les attributs de mixeur préférés.
Votre application peut diffuser n'importe quelle configuration vers la couche d'abstraction matérielle (HAL) et vers l'appareil, à condition que celui-ci accepte cette configuration.
Les deux comportements de mélangeur autorisés dans AudioMixerAttributes
sont DEFAULT
et BIT_PERFECT
. Lorsque le comportement du mélangeur est DEFAULT
, cela signifie que les données audio de différentes sources sont mélangées.
Lorsque le comportement du mélangeur est BIT_PERFECT
, aucun mixage audio, ajustement du volume ou effet de traitement audio n'est appliqué à la lecture. Les données sont envoyées telles quelles au HAL, puis vers le périphérique USB.
L'utilisation de BIT_PERFECT
vous permet de diffuser directement des flux numériques (DSD) via la modulation par impulsion et code (PCM) sur les appareils Android.
L'exemple de code suivant montre comment procéder:
Kotlin
val EXPECTED_FORMAT: AudioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_24BIT_PACKED) .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) .setSampleRate(44100) .build() fun startPlayback() { // Query all supported mixer attributes val mixerAttributesList: List<AudioMixerAttributes?> = mAudioManager.getSupportedMixerAttributes(usbDevice) // Find the wanted mixer attributes val mixerAttributes = mixerAttributesList.stream() .filter { mixerAttr: AudioMixerAttributes? -> EXPECTED_FORMAT.equals( mixerAttr!!.format ) } .findAny() .orElse(null) // Register a listener to mixer attributes changed val listener = MyPreferredMixerAttributesChangedListener() mAudioManager.addOnPreferredMixerAttributesChangedListener( Executors.newSingleThreadExecutor(), listener ) // Currently, only media usage over USB devices will be allowed val attr: AudioAttributes = AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build() // Set preferred mixer attributes mAudioManager.setPreferredMixerAttributes( attr, usbDevice, mixerAttributes ) // Start playback, note the playback and the audio format must // match what is set when calling `setPreferredMixerAttriutes` // API. val audioTrack = AudioTrack.Builder() .setAudioAttributes(attr) .setAudioFormat(mixerAttributes!!.format) .build() // Clear all preferred mixer attributes related stuff when // playback task is completed mAudioManager.clearPreferredMixerAttributes(attr, usbDevice) mAudioManager.removeOnPreferredMixerAttributesChangedListener(listener) } private class MyPreferredMixerAttributesChangedListener : AudioManager.OnPreferredMixerAttributesChangedListener { override fun onPreferredMixerAttributesChanged( attributes: AudioAttributes, device: AudioDeviceInfo, mixerAttributes: AudioMixerAttributes?, ) { // Do something when preferred mixer attributes changed } }
Java
final AudioFormat EXPECTED_FORMAT = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_24BIT_PACKED) .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) .setSampleRate(44100) .build(); void startPlayback() { // Query all supported mixer attributes List<AudioMixerAttributes> mixerAttributesList = mAudioManager.getSupportedMixerAttributes(usbDevice); // Find the wanted mixer attributes AudioMixerAttributes mixerAttributes = mixerAttributesList.stream() .filter(mixerAttr -> EXPECTED_FORMAT.equals(mixerAttr.getFormat())) .findAny() .orElse(null); // Register a listener to mixer attributes changed MyPreferredMixerAttributesChangedListener listener = new MyPreferredMixerAttributesChangedListener(); mAudioManager.addOnPreferredMixerAttributesChangedListener( Executors.newSingleThreadExecutor(), listener); // Currently, only media usage over USB devices will be allowed AudioAttributes attr = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA).build(); // Set preferred mixer attributes mAudioManager.setPreferredMixerAttributes( attr, usbDevice, mixerAttributes); // Start playback, note the playback and the audio format must // match what is set when calling `setPreferredMixerAttriutes` // API. AudioTrack audioTrack = new AudioTrack.Builder() .setAudioAttributes(attr) .setAudioFormat(mixerAttributes.getFormat()) .build(); // Clear all preferred mixer attributes related stuff when // playback task is completed mAudioManager.clearPreferredMixerAttributes(attr, usbDevice); mAudioManager.removeOnPreferredMixerAttributesChangedListener( listener); } private class MyPreferredMixerAttributesChangedListener implements AudioManager.OnPreferredMixerAttributesChangedListener { @Override public void onPreferredMixerAttributesChanged( AudioAttributes attributes, AudioDeviceInfo device, AudioMixerAttributes mixerAttributes) { // Do something when preferred mixer attributes changed } }