وقتی سعی میکنید بااستفاده از میاناهای برنامهسازی کاربردی USB مستقیماً به دستگاه جانبی صوتی USB دسترسی پیدا کنید، مشکلاتی بهوجود میآید. این مشکلات میتواند شامل موارد زیر باشد: مشکلات امنیتی، محدود کردن بازپخش رسانه از برنامههای دیگر، و ازدست رفتن زنگهای ساعت، اعلانها، و آهنگهای زنگ ازطریق دستگاههای USB.
برای بهبود بازپخش صدا، بهجای آن ویژگیهای میکسر را پیکربندی کنید.
پیکربندی مشخصههای میکسر
بااستفاده از
AudioMixerAttributes API،
میتوانید برنامهتان را با ویژگیهای میکسر ترجیحی ازطریق USB پیکربندی کنید.
وقتی بازپخش برنامه شما با قالب کدبندی، ماسک کانال، و نرخ نمونهبرداری ویژگیهای میکسر ترجیحی مطابقت داشته باشد، بازپخش به جاریسازی خروجی صوتی که میکسر آن با ویژگیهای میکسر ترجیحی پیکربندی شده است متصل میشود.
برنامه شما میتواند با هر پیکربندیای به لایه انتزاعی سختافزار (HAL) و به دستگاه جاریسازی کند، بهشرطی که دستگاه USB از آن پیکربندی پشتیبانی کند.
دو رفتار مجاز میکسر در AudioMixerAttributes عبارتاند از DEFAULT و
BIT_PERFECT. وقتی رفتار میکسر DEFAULT باشد، نشان میدهد که دادههای صوتی از منابع مختلف ترکیب شدهاند.
وقتی رفتار میکسر BIT_PERFECT باشد، هیچگونه ترکیب صدا، تنظیم میزان صدا،
یا جلوه پردازششده صوتی روی بازپخش اعمال نمیشود. دادهها همانطور که هستند به HAL و درنهایت به دستگاه USB ارسال میشوند.
بااستفاده از BIT_PERFECT میتوانید
جریان مستقیم دیجیتال (DSD) را ازطریق مدولاسیون کد پالس (PCM) در دستگاههای مجهز به Android پخش کنید.
نمونه کد زیر نشان میدهد که چگونه میتوان این کار را انجام داد:
کاتلین
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 } }