Wenn Sie versuchen, über die USB-APIs direkt auf das USB-Audio-Peripheriegerät zuzugreifen, treten Probleme auf. Zu diesen Problemen gehören unter anderem Sicherheitsprobleme, die Begrenzung der Medienwiedergabe von anderen Apps und der Verlust von Weckern, Benachrichtigungen und Klingeltönen über USB-Geräte.
Wenn du die Audiowiedergabe verbessern möchtest, konfiguriere stattdessen die Mischpultattribute.
Mixerattribute konfigurieren
Mit den AudioMixerAttributes
APIs können Sie Ihre Anwendung mit bevorzugten Mixer-Attributen über USB konfigurieren.
Wenn die App-Wiedergabe mit dem Codierungsformat, der Kanalmaske und der Abtastrate der bevorzugten Mixerattribute übereinstimmt, wird die Wiedergabe an den Audioausgabestream angehängt, dessen Mixer mit den bevorzugten Mixerattributen konfiguriert ist.
Ihre Anwendung kann jede Konfiguration auf die Hardwareabstraktionsebene (HAL) und auf das Gerät streamen, solange das USB-Gerät die Konfiguration unterstützt.
Die beiden zulässigen Mischverhalten in AudioMixerAttributes
sind DEFAULT
und BIT_PERFECT
. Wenn das Mischverhalten DEFAULT
lautet, bedeutet das, dass Audiodaten aus verschiedenen Quellen gemischt werden.
Wenn das Mischverhalten BIT_PERFECT
lautet, wird kein Audiomixing, keine Lautstärkeanpassung und kein Audioverarbeitungseffekt auf die Wiedergabe angewendet. Die Daten werden unverändert an den HAL und schließlich zum USB-Gerät gesendet.
Mit BIT_PERFECT
können Sie digitale Streams (DSD) über Pulscodemodulation (PCM) auf Android-Geräten direkt streamen.
Das folgende Codebeispiel zeigt, wie dies erreicht werden kann:
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 } }