כשמנסים לגשת ישירות לציוד ההיקפי של ה-USB ב-USB באמצעות ממשקי ה-API של USB, מתעוררות בעיות. הבעיות האלה יכולות לכלול: בעיות אבטחה, הגבלת מדיה הפעלה מאפליקציות אחרות ואובדן התראות, התראות ורינגטונים מעל התקני USB.
כדי לשפר את הפעלת האודיו, צריך להגדיר את מאפייני המיקסר.
הגדרת מאפייני מיקסר
באמצעות
AudioMixerAttributes
ממשקי API,
ניתן להגדיר את האפליקציה עם מאפייני מיקסר מועדפים על פני USB.
כשהפעלת האפליקציה תואמת לפורמט הקידוד, למסכת הערוץ ולדוגמה של מאפייני המיקסר המועדפים, ההפעלה מצורפת לאודיו זרם הפלט שהמיקסר שלו מוגדר עם מאפייני המיקסר המועדף.
האפליקציה יכולה להעביר סטרימינג בכל הגדרה אל הפשטת החומרה (HAL) ולמכשיר, כל עוד התקן ה-USB תומך הגדרה אישית.
שתי ההתנהגויות המותרות של מיקסרים ב-AudioMixerAttributes
הן DEFAULT
ו
BIT_PERFECT
. כשהתנהגות המיקסר היא DEFAULT
, סימן שהאודיו
יש שילוב של נתונים ממקורות שונים.
כשהתנהגות המיקסר היא BIT_PERFECT
, אין מיקס של אודיו, כוונון עוצמת הקול
אפקט או אפקט עיבוד אודיו יוחלו על ההפעלה. הנתונים נשלחים כ-
עוברים ל-HAL ולבסוף עוברים להתקן ה-USB.
שימוש ב-BIT_PERFECT
מאפשר לך להפעיל שידור ישיר
דיגיטלי (DSD) באפנון קוד דופק (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 } }