Mejora la reproducción de audio

Cuando intentas acceder directamente al periférico de audio USB con las APIs de USB, cuando surjan problemas. como problemas de seguridad, limitación de contenido multimedia la reproducción de otras apps y la pérdida de alarmas, notificaciones y tonos Dispositivos USB

Para mejorar la reproducción de audio, configura los atributos del mezclador.

Configura los atributos del mezclador

Mediante APIs de AudioMixerAttributes, puedes configurar tu aplicación con los atributos preferidos del mezclador a través de USB.

Cuando la reproducción de tu app coincide con el formato de codificación, la máscara de canal y la muestra de los atributos preferidos del mezclador, la reproducción se adjunta al audio transmisión de salida cuyo mezclador esté configurado con los atributos preferidos del mezclador.

Tu app puede transmitir en cualquier configuración a la abstracción de hardware. (HAL) y al dispositivo, siempre que el dispositivo USB admita configuración.

Los dos comportamientos permitidos del mezclador en AudioMixerAttributes son DEFAULT y BIT_PERFECT Cuando el comportamiento del mezclador es DEFAULT, indica que el audio los datos de diferentes fuentes son mixtos.

Cuando el comportamiento del mezclador es BIT_PERFECT, no hay mezcla de audio, ajuste de volumen, o el efecto de audio procesado a la reproducción. Los datos se envían como es al HAL y, finalmente, al dispositivo USB.

Usar BIT_PERFECT te permite transmitir Digital (DSD) sobre modulación de código por impulsos (PCM) en dispositivos con Android. En la siguiente muestra de código, se ve cómo se puede lograr esto:

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
 
}
}
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
   
}
}