بهبود پخش صدا
با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
وقتی میخواهید مستقیماً با استفاده از APIهای USB به دستگاه جانبی صوتی USB دسترسی پیدا کنید، مشکلاتی ایجاد میشود. این مشکلات می تواند شامل موارد زیر باشد: مشکلات امنیتی، محدود کردن پخش رسانه از برنامه های دیگر، و از دست دادن هشدارها، اعلان ها و آهنگ های زنگ از طریق دستگاه های USB.
برای بهبود پخش صدا، به جای آن ویژگی های میکسر را پیکربندی کنید.
با استفاده از API های AudioMixerAttributes
، می توانید برنامه خود را با ویژگی های میکسر ترجیحی از طریق USB پیکربندی کنید.
هنگامی که پخش برنامه شما با فرمت رمزگذاری، ماسک کانال و نرخ نمونه ویژگیهای میکسر ترجیحی مطابقت دارد، پخش به جریان خروجی صوتی متصل میشود که میکسر آن با ویژگیهای میکسر ترجیحی پیکربندی شده است.
تا زمانی که دستگاه USB از پیکربندی پشتیبانی میکند، برنامه شما میتواند با هر پیکربندی به لایه انتزاعی سختافزار (HAL) و به دستگاه پخش شود.
دو رفتار میکسر مجاز در 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
}
}
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-07-29 بهوقت ساعت هماهنگ جهانی.
[[["درک آسان","easyToUnderstand","thumb-up"],["مشکلم را برطرف کرد","solvedMyProblem","thumb-up"],["غیره","otherUp","thumb-up"]],[["اطلاعاتی که نیاز دارم وجود ندارد","missingTheInformationINeed","thumb-down"],["بیشازحد پیچیده/ مراحل بسیار زیاد","tooComplicatedTooManySteps","thumb-down"],["قدیمی","outOfDate","thumb-down"],["مشکل ترجمه","translationIssue","thumb-down"],["مشکل کد / نمونهها","samplesCodeIssue","thumb-down"],["غیره","otherDown","thumb-down"]],["تاریخ آخرین بهروزرسانی 2025-07-29 بهوقت ساعت هماهنگ جهانی."],[],[],null,["# Improve audio playback\n\nWhen you try to directly access the USB audio peripheral using the USB APIs,\nproblems arise. These problems can include: security issues, limiting media\nplayback from other apps, and loss of alarms, notifications, and ringtones over\nUSB devices.\n\nTo improve audio playback, instead configure the mixer attributes.\n\n### Configure mixer attributes\n\nBy using the\n[`AudioMixerAttributes`](/reference/android/media/AudioMixerAttributes) APIs,\nyou can configure your app with preferred mixer attributes over USB.\n\nWhen your app playback matches the encoding format, channel mask, and sample\nrate of the preferred mixer attributes, the playback is attached to the audio\noutput stream whose mixer is configured with the preferred mixer attributes.\n\nYour app can stream at any configuration to the hardware abstraction\nlayer (HAL), and to the device, as long as the USB device supports the\nconfiguration.\n\nThe two allowed mixer behaviors in `AudioMixerAttributes` are `DEFAULT` and\n`BIT_PERFECT`. When the mixer behavior is `DEFAULT`, it indicates that audio\ndata from different sources is mixed.\n\nWhen the mixer behavior is `BIT_PERFECT`, no audio mixing, volume adjustment,\nor audio processed effect is applied to the playback. The data is sent as\nis to the HAL and finally down to the USB device.\n\nUsing `BIT_PERFECT` lets you direct stream\ndigital (DSD) over pulse code modulation (PCM) on Android-powered devices.\nThe following code sample shows how this can be accomplished: \n\n### Kotlin\n\n```kotlin\nval EXPECTED_FORMAT: AudioFormat = AudioFormat.Builder()\n .setEncoding(AudioFormat.ENCODING_PCM_24BIT_PACKED)\n .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)\n .setSampleRate(44100)\n .build()\n\nfun startPlayback() {\n // Query all supported mixer attributes\n val mixerAttributesList: List\u003cAudioMixerAttributes?\u003e =\n mAudioManager.getSupportedMixerAttributes(usbDevice)\n\n // Find the wanted mixer attributes\n val mixerAttributes = mixerAttributesList.stream()\n .filter { mixerAttr: AudioMixerAttributes? -\u003e\n EXPECTED_FORMAT.equals(\n mixerAttr!!.format\n )\n }\n .findAny()\n .orElse(null)\n\n // Register a listener to mixer attributes changed\n val listener = MyPreferredMixerAttributesChangedListener()\n mAudioManager.addOnPreferredMixerAttributesChangedListener(\n Executors.newSingleThreadExecutor(), listener\n )\n\n // Currently, only media usage over USB devices will be allowed\n val attr: AudioAttributes = AudioAttributes.Builder()\n .setUsage(AudioAttributes.USAGE_MEDIA).build()\n // Set preferred mixer attributes\n mAudioManager.setPreferredMixerAttributes(\n attr, usbDevice, mixerAttributes\n )\n\n // Start playback, note the playback and the audio format must\n // match what is set when calling `setPreferredMixerAttriutes`\n // API.\n val audioTrack = AudioTrack.Builder()\n .setAudioAttributes(attr)\n .setAudioFormat(mixerAttributes!!.format)\n .build()\n\n // Clear all preferred mixer attributes related stuff when\n // playback task is completed\n mAudioManager.clearPreferredMixerAttributes(attr, usbDevice)\n mAudioManager.removeOnPreferredMixerAttributesChangedListener(listener)\n}\n\nprivate class MyPreferredMixerAttributesChangedListener :\n AudioManager.OnPreferredMixerAttributesChangedListener {\n override fun onPreferredMixerAttributesChanged(\n attributes: AudioAttributes,\n device: AudioDeviceInfo,\n mixerAttributes: AudioMixerAttributes?,\n ) {\n // Do something when preferred mixer attributes changed\n }\n}\n```\n\n### Java\n\n```java\nfinal AudioFormat EXPECTED_FORMAT = new AudioFormat.Builder()\n .setEncoding(AudioFormat.ENCODING_PCM_24BIT_PACKED)\n .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)\n .setSampleRate(44100)\n .build();\n\nvoid startPlayback() {\n // Query all supported mixer attributes\n List\u003cAudioMixerAttributes\u003e mixerAttributesList =\n mAudioManager.getSupportedMixerAttributes(usbDevice);\n\n // Find the wanted mixer attributes\n AudioMixerAttributes mixerAttributes =\n mixerAttributesList.stream()\n .filter(mixerAttr -\u003e EXPECTED_FORMAT.equals(mixerAttr.getFormat()))\n .findAny()\n .orElse(null);\n\n // Register a listener to mixer attributes changed\n MyPreferredMixerAttributesChangedListener listener =\n new MyPreferredMixerAttributesChangedListener();\n mAudioManager.addOnPreferredMixerAttributesChangedListener(\n Executors.newSingleThreadExecutor(), listener);\n\n // Currently, only media usage over USB devices will be allowed\n AudioAttributes attr = new AudioAttributes.Builder()\n .setUsage(AudioAttributes.USAGE_MEDIA).build();\n // Set preferred mixer attributes\n mAudioManager.setPreferredMixerAttributes(\n attr, usbDevice, mixerAttributes);\n\n // Start playback, note the playback and the audio format must\n // match what is set when calling `setPreferredMixerAttriutes`\n // API.\n AudioTrack audioTrack = new AudioTrack.Builder()\n .setAudioAttributes(attr)\n .setAudioFormat(mixerAttributes.getFormat())\n .build();\n\n // Clear all preferred mixer attributes related stuff when\n // playback task is completed\n mAudioManager.clearPreferredMixerAttributes(attr, usbDevice);\n mAudioManager.removeOnPreferredMixerAttributesChangedListener(\n listener);\n}\n\nprivate class MyPreferredMixerAttributesChangedListener\n implements AudioManager.OnPreferredMixerAttributesChangedListener {\n @Override\n public void onPreferredMixerAttributesChanged(\n AudioAttributes attributes,\n AudioDeviceInfo device,\n AudioMixerAttributes mixerAttributes) {\n // Do something when preferred mixer attributes changed\n }\n}\n```"]]