الصوت المكاني هو تجربة صوتية غامرة تضع المستخدمين في قلب الحدث، ما يجعل صوت المحتوى أكثر واقعية. يتم "وضع الصوت في المكان" لإنشاء تأثير مكبّرات صوت متعددة، على غرار إعداد الصوت المحيطي، ولكن من خلال سماعات الرأس بدلاً من ذلك.
على سبيل المثال، في فيلم، قد يبدأ صوت سيارة من خلف المستخدم ويتحرك إلى الأمام ثم ينحسر في المسافة. في مكالمة الفيديو، يمكن فصل الأصوات ووضعها حول المستخدم، ما يسهّل التعرّف على المتحدّثين.
إذا كان المحتوى يستخدم تنسيقًا صوتيًا متوافقًا، يمكنك إضافة ميزة "الصوت المكاني" إلى تطبيقك بدءًا من الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات).
طلب معلومات عن الإمكانات
استخدِم فئة Spatializer
لمحاولة معرفة قدرات الجهاز وسلوكه في ما يتعلّق بميزة "الصوت المكاني". ابدأ باسترداد
مثيل من Spatializer
من
AudioManager
:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
بعد الحصول على الرمز Spatializer
، تحقَّق من الشروط الأربعة التي يجب أن تكون مفعّلة
لإخراج الجهاز للصوت المكاني:
المعايير | شيك |
---|---|
هل يتوافق الجهاز مع ميزة "الصوت المكاني"؟ |
getImmersiveAudioLevel() ليس SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
هل تتوفّر ميزة "الصوت المكاني"؟ يعتمد مدى التوفّر على التوافق مع مسار إخراج الصوت الحالي. |
isAvailable() هي true |
هل ميزة "الصوت المكاني" مفعّلة؟ | isEnabled() هي true |
هل يمكن تحويل مقطع صوتي يتضمّن المَعلمات المحدّدة إلى صوت مكاني؟ | canBeSpatialized() هي true |
قد لا يتم استيفاء هذه الشروط، على سبيل المثال، إذا لم تكن ميزة "الصوت المكاني" متاحة للمقطع الصوتي الحالي أو إذا كانت غير مفعّلة على جهاز إخراج الصوت تمامًا.
تتبُّع حركة الرأس
باستخدام سماعات الرأس المتوافقة، يمكن للنظام الأساسي تعديل ميزة
الصوت المكاني استنادًا إلى وضع رأس المستخدم. للتحقّق مما إذا كان جهاز تتبُّع الرأس
متاحًا لتوجيه الصوت الحالي، يُرجى الاتصال بالرقم
isHeadTrackerAvailable()
.
المحتوى المتوافق
يشير Spatializer.canBeSpatialized()
إلى ما إذا كان يمكن معالجة الصوت الذي يتضمّن السمات المحدّدة باستخدام مسار الإرسال الحالي لجهاز الإخراج. تستخدِم هذه الطريقة AudioAttributes
وAudioFormat
، وكلاهما описанان بالتفصيل أدناه.
AudioAttributes
يصف عنصر AudioAttributes
استخدام مجرى بثّ ملف صوتي (مثل صوت اللعبة
أو الوسائط العادية)،
بالإضافة إلى سلوكيات التشغيل ونوع المحتوى.
عند الاتصال بخدمة canBeSpatialized()
، استخدِم مثيل
AudioAttributes
نفسه الذي تم ضبطه لتطبيق Player
. على سبيل المثال، إذا
كنت تستخدم مكتبة Jetpack Media3 ولم تخصِّص
AudioAttributes
، استخدِم AudioAttributes.DEFAULT
.
إيقاف ميزة "الصوت المكاني"
للإشارة إلى أنّه سبق وتم تحويل المحتوى إلى صوت ثلاثي الأبعاد، استخدِم الرمز
setIsContentSpatialized(true)
كي لا تتم معالجة الصوت مرتين. بدلاً من ذلك، يمكنك تعديل سلوك
الوضع المكاني لإيقاف الوضع المكاني بالكامل من خلال الاتصال
setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
.
AudioFormat
يصف عنصر AudioFormat
تفاصيل حول تنسيق المقطع الصوتي وإعدادات القناة.
عند إنشاء مثيل للعنصر AudioFormat
لنقله إلى canBeSpatialized()
،
اضبط التشفير
على القيمة نفسها لتنسيق الإخراج المتوقّع من وحدة فك التشفير. عليك أيضًا ضبط
قناع قناة
يتوافق مع إعدادات القناة التي يتبعها المحتوى. راجِع القسم
السلوك التلقائي للوضع المكاني للحصول على إرشادات حول
القيم المحدّدة التي يجب استخدامها.
الانتباه إلى التغييرات في Spatializer
للاطّلاع على التغييرات في حالة Spatializer
، يمكنك إضافة مستمع
باستخدام Spatializer.addOnSpatializerStateChangedListener()
.
وبالمثل، للاستماع إلى التغييرات في مدى توفّر أداة تتبُّع حركة الرأس،
اتصل على الرقم Spatializer.addOnHeadTrackerAvailableListener()
.
يمكن أن يكون ذلك مفيدًا إذا كنت تريد تعديل اختيار المقطع الصوتي أثناء التشغيل
باستخدام طلبات الاستدعاء الخاصة بالمستمع. على سبيل المثال، عندما يربط المستخدم سماعات الرأس بالجهاز أو يفصلها، يشير onSpatializerAvailableChanged
الاستدعاء إلى ما إذا كان تأثير "محوِّل الصوت المكاني" متاحًا لتوجيه ناتج معالجة
الصوت الجديد. في هذه المرحلة، يمكنك تعديل منطق اختيار
المقاطع الصوتية في المشغّل ليتوافق مع الإمكانات الجديدة للجهاز. للاطّلاع على تفاصيل عن
سلوك اختيار الأغاني في ExoPlayer، يُرجى الرجوع إلى القسم ExoPlayer والصوت المكاني.
ExoPlayer والصوت المكاني
تسهّل الإصدارات الحديثة من ExoPlayer استخدام ميزة "الصوت المكاني". إذا كنت تستخدِم
مكتبة ExoPlayer المستقلة (اسم الحزمة com.google.android.exoplayer2
)،
يضبط الإصدار 2.17 النظام الأساسي لإخراج صوت محيطي، ويقدّم الإصدار
2.18 قيودًا على عدد القنوات الصوتية.
إذا كنت تستخدم وحدة ExoPlayer من مكتبة Media3 (اسم الحزمة
androidx.media3
)، يتضمّن الإصدار 1.0.0-beta01
والإصدارات الأحدث هذه التعديلات نفسها.
بعد تحديث التبعية في ExoPlayer إلى أحدث إصدار، يحتاج تطبيقك فقط إلى تضمين محتوى يمكن تحويله إلى صوت محيطي.
قيود عدد القنوات الصوتية
عند استيفاء كل الشروط الأربعة لميزة "الصوت المكاني"، يختار ExoPlayer مقطعًا صوتيًا متعدّد القنوات. وإذا لم يكن الأمر كذلك، يختار ExoPlayer مقطعًا صوتيًا استيريو بدلاً من ذلك.
في حال تغيّرت خصائص Spatializer
، سيشغّل ExoPlayer
عملية اختيار مقطع صوتي جديد لاختيار مقطع صوتي يتطابق مع
الخصائص الحالية. يُرجى العِلم أنّ اختيار المقطع الصوتي الجديد هذا قد يؤدي إلى بدء عملية إعادة تحميل قصيرة.
لإيقاف القيود المفروضة على عدد القنوات الصوتية، اضبط مَعلمات اختيار المقاطع الصوتية في المشغّل كما هو موضّح أدناه:
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
وبالمثل، يمكنك تعديل مَعلمات أداة اختيار المقاطع الصوتية الحالية لإيقاف قيود عدد قنوات الصوت على النحو التالي:
Kotlin
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
في حال إيقاف قيود عدد قنوات الصوت، إذا كان المحتوى يتضمّن عدة ملفّات صوتية، سيختار ExoPlayer في البداية الملفّ الصوتي الذي يتضمّن أكبر عدد من القنوات ويمكن تشغيله من الجهاز. على سبيل المثال، إذا كان المحتوى يتضمّن مقطعًا صوتيًا بقنوات متعددة ومقطعًا صوتيًا استيريو، وكان الجهاز يتيح تشغيل المقطعَين معًا، سيختار ExoPlayer المقطع الصوتي المتعدّد القنوات. راجِع اختيار المقطع الصوتي للحصول على تفاصيل عن كيفية تخصيص هذا السلوك.
اختيار المقطع الصوتي
عند إيقاف سلوك قيود عدد قنوات الصوت في ExoPlayer، لا يختار ExoPlayer تلقائيًا مقطعًا صوتيًا يتوافق مع خصائص أداة المعالجة الصوتية للمكان في الجهاز. بدلاً من ذلك، يمكنك تخصيص منطق اختيار الأغاني في ExoPlayer من خلال ضبط مَعلمات اختيار الأغاني قبل التشغيل أو أثناءه. يختار ExoPlayer تلقائيًا ملفّات صوتي ة مماثلة للملفّ الصوتي الأوّلي من حيث نوع MIME (التشفير) وعدد القنوات ومعدّل أخذ العينات.
تغيير مَعلمات اختيار المقاطع الصوتية
لتغيير مَعلمات اختيار المقاطع الصوتية في ExoPlayer، استخدِم
Player.setTrackSelectionParameters()
.
وبالمثل، يمكنك الحصول على المَعلمات الحالية لواجهة ExoPlayer باستخدام الرمز المميّز
Player.getTrackSelectionParameters()
.
على سبيل المثال، لاختيار مسار صوت استريو أثناء التشغيل:
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
يُرجى العلم أنّ تغيير مَعلمات اختيار المقاطع الصوتية أثناء التشغيل قد يؤدي إلى انقطاعه. تتوفّر مزيد من المعلومات حول ضبط مَعلمات اختيار المقاطع الصوتية في المشغّل في قسم اختيار المقاطع الصوتية ضمن مستندات ExoPlayer.
السلوك التلقائي للصوت المكاني
يتضمّن السلوك التلقائي للصوت المكاني في Android السلوكيات التالية التي يمكن أن تخصصها شركات المصنّعين الأصليّين للأجهزة:
لا يمكن تطبيق ميزة "الصوت المكاني" إلا على المحتوى المتعدّد القنوات، وليس على المحتوى الاستيريو. إذا كنت لا تستخدم ExoPlayer، استنادًا إلى تنسيق محتوى الوسائط الصوتية المتعدّدة القنوات، قد تحتاج إلى ضبط الحد الأقصى لعدد القنوات التي يمكن لبرنامج ترميز الصوت إخراجها إلى عدد كبير. يضمن ذلك أن يُخرج فاقِد ترميز الصوت تنسيق PCM متعدد القنوات لكي تتمكّن المنصة من معالجة الصوت المكاني.
Kotlin
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
Java
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
للاطّلاع على مثال على ذلك، اطّلِع على
MediaCodecAudioRenderer.java
في ExoPlayer. لإيقاف ميزة "الصوت المكاني" بنفسك، بغض النظر عن تخصيص المصنّع الأصلي للجهاز، يُرجى الاطّلاع على مقالة إيقاف ميزة "الصوت المكاني".AudioAttributes
: يكون الصوت مؤهلاً للعرض بتقنية الصوت المكاني إذا تم ضبطusage
علىUSAGE_MEDIA
أوUSAGE_GAME
.AudioFormat
: استخدِم قناع قناة يحتوي على قنواتAudioFormat.CHANNEL_OUT_QUAD
على الأقل (القناة الأمامية اليسرى والقنوات الأمامية اليمنى والقنوات الخلفية اليسرى والقنوات الخلفية اليمنى) لكي يكون الصوت مؤهلاً للمعالجة الصوتية المكانية. في المثال أدناه، نستخدمAudioFormat.CHANNEL_OUT_5POINT1
لمقطع صوتي بجودة 5.1. بالنسبة إلى المقطع الصوتي الاستيريو، استخدِمAudioFormat.CHANNEL_OUT_STEREO
.إذا كنت تستخدِم Media3، يمكنك استخدام
Util.getAudioTrackChannelConfig(int channelCount)
لتحويل عدد القنوات إلى قناع قناة.بالإضافة إلى ذلك، اضبط التشفير على
AudioFormat.ENCODING_PCM_16BIT
إذا كنت قد أعددت وحدة فك التشفير لإخراج تنسيق PCM متعدد القنوات.Kotlin
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
Java
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
اختبار ميزة "الصوت المكاني"
تأكَّد من تفعيل ميزة "الصوت المكاني" على جهاز الاختبار:
- بالنسبة إلى سماعات الرأس السلكية، انتقِل إلى إعدادات النظام > الصوت والاهتزاز > الصوت المجسم.
- بالنسبة إلى سماعات الرأس اللاسلكية، انتقِل إلى إعدادات النظام > الأجهزة المتصلة > رمز الترس لجهازك اللاسلكي > الصوت المكاني.
للتحقّق من توفّر ميزة "الصوت المكاني" للتوجيه الحالي، شغِّل الأمر
adb shell dumpsys audio
على جهازك. من المفترض أن تظهر لك المَعلمات التالية
في الإخراج أثناء تشغيل الفيديو:
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)