الصوت المكاني هو تجربة صوتية غامرة تضع المستخدمين في قلب الحدث، ما يجعل صوت المحتوى أكثر واقعية. الصوت هو "محددة المكان" لإنشاء تأثير مكبّر صوت متعدد، يشبه الصوت المحيطي الإعداد، ولكن من خلال سماعات الرأس بدلاً من ذلك.
على سبيل المثال، في فيلم، قد يبدأ صوت سيارة من خلف المستخدم ويتحرك إلى الأمام ثم ينحسر في المسافة. في دردشة الفيديو، يمكن أن تكون الأصوات منفصلة ووضعها حول المستخدم، مما يسهل التعرف على المتحدثين.
إذا كان المحتوى يستخدم تنسيقًا صوتيًا متوافقًا، يمكنك إضافة ميزة "الصوت المكاني" إلى تطبيقك بدءًا من الإصدار 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)