เมื่อคุณพยายามเข้าถึงอุปกรณ์ต่อพ่วงเสียงทาง USB โดยตรงโดยใช้ API ของ USB มีปัญหาเกิดขึ้น ปัญหาเหล่านี้อาจรวมถึงปัญหาด้านความปลอดภัย การจำกัดสื่อ การเล่นจากแอปอื่นและการปลุก การแจ้งเตือน และเสียงเรียกเข้า อุปกรณ์ USB
หากต้องการปรับปรุงการเล่นเสียง ให้กำหนดค่าแอตทริบิวต์มิกเซอร์แทน
กำหนดค่าแอตทริบิวต์เครื่องผสม
โดยการใช้
AudioMixerAttributes
API
คุณจะกำหนดค่าแอปด้วยแอตทริบิวต์มิกเซอร์ที่ต้องการผ่านทาง USB ได้
เมื่อการเล่นแอปของคุณตรงกับรูปแบบการเข้ารหัส มาสก์ช่อง และตัวอย่าง ของแอตทริบิวต์มิกเซอร์ที่ต้องการ การเล่นจะแนบอยู่กับเสียง สตรีมเอาต์พุตที่มีการกำหนดค่าเครื่องผสมด้วยแอตทริบิวต์มิกเซอร์ที่ต้องการ
แอปสามารถสตรีมการกำหนดค่าการแอบสแตรกของฮาร์ดแวร์ได้ทุกเมื่อ (HAL) กับอุปกรณ์ตราบใดที่อุปกรณ์ USB รองรับ การกำหนดค่า
ลักษณะการทำงานของมิกเซอร์ที่อนุญาต 2 รายการใน AudioMixerAttributes
คือ DEFAULT
และ
BIT_PERFECT
เมื่อมิกเซอร์ทำงานเป็น DEFAULT
แสดงว่าเสียง
ข้อมูลจากแหล่งต่างๆ จะปะปนกัน
เมื่อการทำงานของมิกเซอร์คือ BIT_PERFECT
จะไม่มีการมิกซ์เสียง ปรับระดับเสียง
หรือเสียงที่ประมวลผลแล้ว กับการเล่น ข้อมูลจะส่งในรูปแบบ
คือ HAL และสุดท้ายก็ลงสู่อุปกรณ์ USB
เมื่อใช้ BIT_PERFECT
คุณจะสตรีมได้โดยตรง
ดิจิทัล (DSD) ผ่านการปรับโค้ด Pulse (PCM) บนอุปกรณ์ที่ใช้ Android
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีดำเนินการดังกล่าว
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 } }