تتيح لك ميزات "الصوت المكاني" في Jetpack SceneCore تصميم تجارب صوتية غامرة داخل تطبيقات Android XR.
تحاكي ميزة "الصوت المكاني" طريقة سماع المستخدمين للأصوات في بيئة ثلاثية الأبعاد. تخلق هذه التقنية إحساسًا بأنّ الصوت يأتي من جميع الاتجاهات، بما في ذلك من فوق المستخدم ومن تحته. ويتم ذلك من خلال محاكاة مكبّر صوت افتراضي واحد أو أكثر في مواقع جغرافية محددة في المساحة الثلاثية الأبعاد.
يتم تلقائيًا تحويل الصوت في التطبيقات الحالية التي لم يتم تصميمها أو تعديلها لنظام Android XR إلى صوت مكاني في Android XR. عندما يتنقّل المستخدم في المساحة، سيصدر كل صوت التطبيق من اللوحة التي يتم عرض واجهة مستخدم التطبيق عليها. على سبيل المثال، إذا رنّ موقّت من تطبيق ساعة، سيصدر الصوت من موضع لوحة التطبيق. ستعدّل منصة Android XR الصوت تلقائيًا ليكون أكثر واقعية. على سبيل المثال، ستؤثر المسافة المحسوسة بين لوحة التطبيق والمستخدم بشكل طفيف على مستوى صوت الصوت لإضفاء إحساس أكبر بالواقعية.
لمزيد من المعلومات حول كيفية عرض التطبيقات الحالية للصوت المكاني، يمكنك الاطّلاع على مقالة إضافة صوت استريو وصوت محيطي إلى تطبيقك في هذه الصفحة.
إذا كنت بصدد تحسين تطبيقك ليتوافق مع تقنيات الواقع الممتد، يوفّر Jetpack SceneCore أدوات لتخصيص الصوت المكاني بشكل متقدّم. يمكنك تحديد موضع الأصوات بدقة في البيئة الثلاثية الأبعاد، واستخدام الصوت المجسم لإنشاء مجالات صوتية واقعية، والاستفادة من ميزة الدمج المضمّنة للصوت المحيطي.
أنواع الصوت المكاني المتاحة في Android XR
يتوافق نظام التشغيل Android XR مع الصوت الموضعي والاستيريو والمحيطي والصوت المجسم.
الصوت الموضعي
يمكن ضبط موضع الصوت المكاني ليتم تشغيله من نقطة معيّنة في المساحة الثلاثية الأبعاد. على سبيل المثال، يمكنك عرض تصميم ثلاثي الأبعاد لكلب ينبح في زاوية بيئتك الافتراضية. يمكن أن يكون لديك عناصر متعددة تصدر صوتًا من كل موضع من مواضعها. لعرض الصوت المكاني، يجب أن تكون الملفات أحادية القناة أو استريو.
صوت الاستيريو المكاني والصوت المحيطي
تتوافق جميع تنسيقات الوسائط على Android مع الصوت الموضعي وصوت الاستيريو والصوت المحيطي.
يشير صوت الاستريو إلى تنسيقات الصوت التي تتضمّن قناتين، بينما يشير الصوت المحيطي إلى تنسيقات الصوت التي تتضمّن أكثر من قناتين، مثل إعدادات الصوت المحيطي بتقنية 5.1 أو الصوت المحيطي بتقنية 7.1. ترتبط بيانات الصوت لكل قناة بمكبر صوت واحد. على سبيل المثال، عند تشغيل الموسيقى بنظام الاستريو، قد تبث قناة مكبّر الصوت الأيسر مقاطع صوتية مختلفة عن تلك التي تبثها قناة مكبّر الصوت الأيمن.
يُستخدَم الصوت المحيطي غالبًا في الأفلام والبرامج التلفزيونية لتعزيز الواقعية والانغماس في المحتوى من خلال استخدام قنوات متعددة لمكبرات الصوت. على سبيل المثال، غالبًا ما يتم تشغيل الحوار من قناة مكبّر الصوت المركزي، بينما قد يستخدم صوت طائرة هليكوبتر تحلّق قنوات مختلفة بالتسلسل لإعطاء الإحساس بأنّ الطائرة تحلّق حول المساحة الثلاثية الأبعاد.
الصوت المجسم
الصوت المجسم (أو الصوت المحيطي) هو بمثابة صندوق سماوي للصوت،
يوفر تجربة صوتية غامرة للمستخدمين. استخدِم تنسيق الصوت المجسم الشامل للأصوات البيئية في الخلفية أو في سيناريوهات أخرى تريد فيها محاكاة مجال صوتي كروي كامل يحيط بالمستمع. يتوافق نظام التشغيل Android XR مع تنسيق الصوت المجسم AmbiX في الصوت المجسم من الدرجة الأولى والثانية والثالثة. ننصحك باستخدام نوعَي الملفات Opus (.ogg
) وPCM/Wave (.wav
).
استخدام ميزة "الصوت المكاني" مع Jetpack SceneCore
يتضمّن تنفيذ ميزة "الصوت المكاني" باستخدام Jetpack SceneCore التحقّق من توفّر إمكانات الصوت المكاني واختيار واجهة برمجة تطبيقات لتحميل الصوت المكاني.
التحقّق من إمكانات العرض المكاني
قبل استخدام ميزات "الصوت المكاني"، تأكَّد من أنّ Session
يتيح استخدام هذه الميزات. في جميع مقتطفات الرموز البرمجية في الأقسام التالية، يتم التحقّق من الإمكانات قبل محاولة تشغيل الصوت المكاني.
تحميل الصوت المكاني
يمكنك استخدام أي من واجهات برمجة التطبيقات التالية لتحميل الصوت المكاني لاستخدامه في Jetpack SceneCore.
SoundPool
: مثالية للتأثيرات الصوتية القصيرة التي يقل حجمها عن 1 ميغابايت، ويتم تحميلها مسبقًا ويمكن استخدامها بشكل متكرر. هذه طريقة رائعة لتحميل الصوت المكاني.-
ExoPlayer
: مثالي لتحميل محتوى صوتي مجسّم ومحيطي، مثل الموسيقى والفيديو. يسمح أيضًا بتشغيل الوسائط في الخلفية. MediaPlayer
: يوفّر أبسط طريقة لتحميل الصوت المجسم.-
AudioTrack
: يوفّر أكبر قدر من التحكّم في طريقة تحميل بيانات الصوت. تتيح هذه السمة كتابة مخازن مؤقتة للصوت مباشرةً أو ما إذا كنت قد ركّبت أو فككت ترميز ملفاتك الصوتية.
إضافة صوت موضعي إلى تطبيقك
يتم تحديد مصادر الصوت الموضعي من خلال PointSourceParams
وEntity
مرتبط. يحدّد موضع Entity
واتجاهه
المكان الذي يتم فيه عرض PointSourceParams
في المساحة الثلاثية الأبعاد.
مثال على الصوت المكاني
يحمّل المثال التالي ملفًا صوتيًا لمؤثر صوتي في مجموعة أصوات ثم يعيد تشغيله في موضع Entity
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO) ) { // The session has spatial audio capabilities val maxVolume = 1F val lowPriority = 0 val infiniteLoop = -1 val normalSpeed = 1F val soundPool = SoundPool.Builder() .setAudioAttributes( AudioAttributes.Builder() .setContentType(CONTENT_TYPE_SONIFICATION) .setUsage(USAGE_ASSISTANCE_SONIFICATION) .build() ) .build() val pointSource = PointSourceParams(entity) val soundEffect = appContext.assets.openFd("sounds/tiger_16db.mp3") val pointSoundId = soundPool.load(soundEffect, lowPriority) soundPool.setOnLoadCompleteListener { soundPool, sampleId, status -> // wait for the sound file to be loaded into the soundPool if (status == 0) { SpatialSoundPool.play( session = session, soundPool = soundPool, soundID = pointSoundId, params = pointSource, volume = maxVolume, priority = lowPriority, loop = infiniteLoop, rate = normalSpeed ) } } } else { // The session does not have spatial audio capabilities }
نقاط رئيسية حول الرمز
- الخطوة الأولى هي التحقّق مما إذا كانت إمكانات "الصوت المكاني" متاحة حاليًا باستخدام
spatialCapabilities
. - يؤدي ضبط contentType على
CONTENT_TYPE_SONIFICATION
وضبط الاستخدام علىUSAGE_ASSISTANCE_SONIFICATION
إلى السماح للنظام بالتعامل مع ملف الصوت هذا كمؤثر صوتي. - يحمّل المثال السابق ملف الصوت إلى المجموعة مباشرةً قبل استخدامه للحفاظ على التعليمات البرمجية معًا لتبسيطها. من المفترض أن يتم تحميل جميع المؤثرات الصوتية بشكل غير متزامن أثناء تحميل تطبيقك، وذلك لكي تكون جميع ملفات الصوت متاحة في مجموعة الموارد عند الحاجة إليها.
إضافة صوت مجسّم ومحيطي إلى تطبيقك
الطريقة المقترَحة لإضافة صوت ستيريو وصوت محيطي إلى تطبيقك هي استخدام
Exoplayer
. لمزيد من المعلومات حول كيفية استخدام ميزة "الصوت المكاني" مع Exoplayer
،
يُرجى الرجوع إلى دليل "الصوت المكاني".
تحديد موضع مكبّرات الصوت الاستيريو والصوت المحيطي
من خلال تحديد موضع مكبّرات الصوت المحيطي، يتم تحديد موضع مكبّرات الصوت المحيطي الافتراضية وتوجيهها بالنسبة إلى مكبّر صوت مركزي، حول المستخدم في إعداد ITU عادي.
يتم وضع مكبّر صوت القناة المركزية تلقائيًا على mainPanelEntity
في التطبيق. ويشمل ذلك تطبيقات الأجهزة الجوّالة التي يتم تحويل الصوت فيها إلى صوت مكاني تلقائيًا من خلال Android XR.
بالنسبة إلى صوت الاستيريو، يكون موضع مكبّرات الصوت مشابهًا لموضعها في الصوت المحيطي، ولكن مع وضع قناتَي الصوت اليمنى واليسرى على الجانبين الأيمن والأيسر من اللوحة، على التوالي.
إذا كان لديك لوحات متعددة وأردت اختيار اللوحة التي تصدر الصوت، أو إذا أردت عرض الصوت المجسم أو المحيطي بالنسبة إلى Entity
آخر، يمكنك استخدام PointSourceAttributes
لتحديد موقع القناة المركزية. سيتم وضع القنوات المتبقية كما ذكرنا سابقًا. في هذه الحالات، يجب أيضًا استخدام MediaPlayer
.
أثناء تنقّل المستخدم في المساحة، ستتحرّك مكبّرات الصوت الافتراضية التي تعمل بنظامَي الاستيريو والصوت المحيطي وتتكيّف لضمان أن تكون مكبّرات الصوت دائمًا في وضع مثالي.
إذا كنت قد أعددت MediaPlayer
أو ExoPlayer
لمواصلة تشغيل الصوت المجسم أو المحيطي في الخلفية، سيتم تغيير موضع مكبر الصوت الافتراضي عند تشغيل التطبيق في الخلفية. وبما أنّه لا توجد لوحة أو نقطة أخرى في المساحة لتثبيت الصوت عليها، يتحرّك الصوت المكاني مع المستخدم (أي أنّه "مُثبّت على الرأس").
مثال على الصوت المحيطي
يحمّل المثال التالي ملفًا صوتيًا بتنسيق 5.1 باستخدام MediaPlayer
ويضبط القناة المركزية للملف على Entity
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) { // The session has spatial audio capabilities val pointSourceAttributes = PointSourceParams(session.scene.mainPanelEntity) val mediaPlayer = MediaPlayer() val fivePointOneAudio = appContext.assets.openFd("sounds/aac_51.ogg") mediaPlayer.reset() mediaPlayer.setDataSource(fivePointOneAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setPointSourceParams( session, mediaPlayer, pointSourceAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
نقاط رئيسية حول الرمز
- كما هو الحال في مثال الصوت الموضعي، الخطوة الأولى هي التحقّق مما إذا كانت إمكانات الصوت المكاني متاحة باستخدام
spatialCapabilities
. - يؤدي ضبط
contentType
علىAudioAttributes.CONTENT_TYPE_MUSIC
وضبط الاستخدام علىAudioAttributes.USAGE_MEDIA
إلى تعامل النظام مع ملف الصوت هذا على أنّه صوت محيطي.
إضافة مجالات صوتية متعددة الاتجاهات إلى تطبيقك
إنّ أبسط طريقة لتشغيل مجالات الصوت المجسم هي تحميل الملف باستخدام
MediaPlayer
. بما أنّ الصوت المجسم ينطبق على المشهد الصوتي بأكمله، ليس عليك تحديد Entity
لتوفير موضع. بدلاً من ذلك، يمكنك إنشاء مثيل من SoundFieldAttributes
مع ترتيب الصوت المجسم المناسب الذي يحدّد عدد القنوات.
مثال على Ambionics
يعرض المثال التالي مجال صوتي متعدد الاتجاهات باستخدام MediaPlayer
.
// Check spatial capabilities before using spatial audio if (session.scene.spatialCapabilities.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) { // The session has spatial audio capabilities val soundFieldAttributes = SoundFieldAttributes(SpatializerConstants.AMBISONICS_ORDER_FIRST_ORDER) val mediaPlayer = MediaPlayer() val soundFieldAudio = appContext.assets.openFd("sounds/foa_basketball_16bit.wav") mediaPlayer.reset() mediaPlayer.setDataSource(soundFieldAudio) val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() SpatialMediaPlayer.setSoundFieldAttributes( session, mediaPlayer, soundFieldAttributes ) mediaPlayer.setAudioAttributes(audioAttributes) mediaPlayer.prepare() mediaPlayer.start() } else { // The session does not have spatial audio capabilities }
نقاط رئيسية حول الرمز
- كما هو الحال مع المقتطفات السابقة، تتمثّل الخطوة الأولى في التحقّق من توفّر إمكانات "الصوت المكاني" باستخدام
hasCapability()
. - إنّ
contentType
والاستخدام هما لأغراض إعلامية فقط. - تشير
AMBISONICS_ORDER_FIRST_ORDER
إلى SceneCore بأنّ ملف مجال الصوت يحدّد أربع قنوات.