إضافة ميزة "الصوت المكاني" إلى تطبيق الواقع المعزّز

أجهزة XR المشمولة
تساعدك هذه الإرشادات في إنشاء تجارب لهذه الأنواع من أجهزة XR.
سماعات الرأس بنظام الواقع الممتد
نظارات سلكية بنظام الواقع الممتد

تتيح لك ميزات الصوت المكاني في Jetpack SceneCore إنشاء تجارب صوتية غامرة في تطبيقات Android XR.

تحاكي ميزة "الصوت المكاني" كيفية إدراك المستخدمين للصوت في بيئة ثلاثية الأبعاد. فهي تخلق إحساسًا بالصوت الصادر من جميع الاتجاهات، بما في ذلك من أعلى المستخدم وأسفله. ويتم ذلك من خلال محاكاة "مكبّر صوت افتراضي" واحد أو أكثر في مواقع جغرافية محدّدة في مساحة ثلاثية الأبعاد.

بالنسبة إلى التطبيقات الحالية التي لم يتم تصميمها أو تعديلها لتتوافق مع Android XR، يتم تحويل الصوت فيها تلقائيًا إلى صوت مكاني في Android XR. وعندما يتحرّك المستخدم في مساحته، سيتم إصدار كل صوت التطبيق من اللوحة التي يتم عرض واجهة مستخدم التطبيق عليها. على سبيل المثال، إذا رنّ موقّت من تطبيق ساعة، سيصدر الصوت كما لو أنّه صادر من موضع لوحة التطبيق. سيعدّل Android XR الصوت تلقائيًا لتحقيق واقعية في تحديد المواقع. على سبيل المثال، ستؤثر المسافة المتصوَّرة بين لوحة التطبيق والمستخدم بشكل طفيف في مستوى الصوت لتعزيز الشعور بالواقعية.

لمزيد من المعلومات حول كيفية عرض التطبيقات الحالية للصوت المكاني، يُرجى الاطّلاع على مقالة إضافة صوت ستيريو وصوت محيطي إلى تطبيقك في هذه الصفحة.

إذا كنت تعمل على تحسين تطبيقك ليتوافق مع الواقع الممتد، يوفّر Jetpack SceneCore أدوات لتخصيص الصوت المكاني المتقدّم. يمكنك تحديد موضع الأصوات بدقة في البيئة الثلاثية الأبعاد، واستخدام الصوت المحيطي للحصول على حقول صوتية واقعية، والاستفادة من ميزة الصوت المحيطي المدمجة.

أنواع الصوت المكاني المتاحة في Android XR

يتيح Android XR استخدام الصوت الموضعي والستيريو والصوت المحيطي والصوت المحيطي الثلاثي الأبعاد.

الصوت الموضعي

يمكن ضبط موضع الصوت الموضعي ليتم تشغيله من نقطة معيّنة في مساحة ثلاثية الأبعاد. على سبيل المثال، يمكنك الحصول على نموذج ثلاثي الأبعاد لكلب ينبح في زاوية بيئتك الافتراضية. يمكن أن يكون لديك كيانات متعددة تصدر صوتًا من كل من مواقعها الخاصة. لعرض الصوت الموضعي، يجب أن تكون الملفات أحادية أو ستيريو.

صوت الاستيريو المجسّم والصوت المحيطي

تتوفّر جميع تنسيقات وسائط Android للصوت الموضعي والستيريو والصوت المحيطي. بالإضافة إلى هذه التنسيقات، قد تتوافق أجهزة Android XR مع تنسيقات الصوت Dolby Atmos وDolby Digital وDolby Digital+‎.

يشير صوت الاستيريو إلى تنسيقات الصوت التي تتضمّن قناتَين، بينما يشير الصوت المحيطي إلى تنسيقات الصوت التي تتضمّن أكثر من قناتَين، مثل إعدادات الصوت المحيطي بتقنية 5.1 أو الصوت المحيطي بتقنية 7.1. ترتبط بيانات الصوت لكل قناة بمكبّر صوت واحد. على سبيل المثال، عند تشغيل الموسيقى في وضع الاستيريو، قد تصدر قناة مكبّر الصوت الأيسر مسارات آلات موسيقية مختلفة عن مكبّر الصوت الأيمن.

غالبًا ما يُستخدم الصوت المحيطي في الأفلام والبرامج التلفزيونية لتعزيز الواقعية والانغماس من خلال استخدام قنوات مكبرات صوت متعددة. على سبيل المثال، غالبًا ما يتم تشغيل الحوار من قناة مكبر صوت مركزي بينما قد يستخدم صوت طائرة هليكوبتر تحلق قنوات مختلفة بالتسلسل لإعطاء الإحساس بأن المروحية تحلق حول مساحتك ثلاثية الأبعاد.

صوت محيطي ثلاثي الأبعاد

الصوت المحيطي (أو الصوتيات المحيطية) يشبه صندوق السماء للصوت، ويوفّر مشهدًا صوتيًا غامرًا للمستخدمين. استخدِم الصوت المحيطي الثلاثي الأبعاد للأصوات البيئية في الخلفية أو في سيناريوهات أخرى تريد فيها تكرار مجال صوتي كروي كامل يحيط بالمستمع. يتيح Android XR تنسيق الصوت المحيطي AmbiX من الدرجة الأولى والثانية والثالثة. ننصح باستخدام نوعَي الملفات Opus (.ogg) وPCM/Wave (.wav).

استخدام الصوت المكاني مع Jetpack SceneCore

يتطلّب تنفيذ ميزة "الصوت المكاني" باستخدام Jetpack SceneCore التحقّق من الإمكانات المكانية واختيار واجهة برمجة تطبيقات لتحميل الصوت المكاني.

التحقّق من إمكانات الصوت المكاني

قبل استخدام ميزات الصوت المكاني، تأكَّد من أنّ Session يتيح استخدام الصوت المكاني. في جميع مقتطفات الرموز البرمجية في الأقسام التالية، يتم التحقّق من الإمكانات قبل محاولة تشغيل الصوت المكاني.

تحميل الصوت المكاني

يمكنك استخدام أي من واجهات برمجة التطبيقات التالية لتحميل الصوت المكاني لاستخدامه في Jetpack SceneCore.

  • SoundPool: مثالية للمؤثرات الصوتية القصيرة التي يقل حجمها عن 1 ميغابايت، ويتم تحميلها مسبقًا ويمكن استخدام الأصوات بشكل متكرر. هذه طريقة رائعة لتحميل الصوت للصوت الموضعي.
  • ExoPlayer: مثالي لتحميل محتوى الصوت المجسّم والصوت المحيطي، مثل الموسيقى والفيديو ويسمح أيضًا بتشغيل الوسائط في الخلفية.
  • MediaPlayer: توفّر هذه الفئة أبسط طريقة لتحميل الصوت المحيطي.
  • ‫AudioTrack: يوفّر هذا الخيار أكبر قدر من التحكّم في كيفية تحميل البيانات الصوتية. تسمح هذه الفئة بالكتابة مباشرةً في مخازن الصوت المؤقتة أو إذا كنت قد أنشأت أو فككت ترميز ملفاتك الصوتية.

التحقّق من توافق تنسيق الوسائط

بعض تنسيقات الوسائط متوافقة مع نظام Android الأساسي. ومع ذلك، قد يتوافق جهاز Android XR معيّن مع تنسيقات إضافية، مثل Dolby Atmos. للاستعلام عن توافق تنسيق الوسائط، استخدِم AudioCapabilities في ExoPlayer:

val audioCapabilities = AudioCapabilities.getCapabilities(
    context,
    androidx.media3.common.AudioAttributes.DEFAULT,
    null,
    emptyList()
)

if (audioCapabilities.supportsEncoding(C.ENCODING_AC3)) {
    // Device supports playback of the Dolby Digital media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3)) {
    // Device supports playback of the Dolby Digital Plus media format.
}
if (audioCapabilities.supportsEncoding(C.ENCODING_E_AC3_JOC)) {
    // Device supports playback of the Dolby Digital Plus with Dolby Atmos media format.
}

قد يتضمن التحقّق من هذه الإمكانات حظر المكالمات، ويجب عدم طلبها في سلسلة التعليمات الرئيسية.

إضافة صوت موضعي إلى تطبيقك

يتم تحديد مصادر الصوت الموضعية من خلال PointSourceParams وEntity المرتبط بها. يحدّد موضع Entity واتجاهه مكان عرض PointSourceParams في المساحة الثلاثية الأبعاد. استدعِ setPointSourceParams على SpatialMediaPlayer لضبط PointSourceParams وentity المرتبط به على مثيل MediaPlayer.

مثال على الصوت الموضعي

يحمّل المثال التالي ملفًا صوتيًا لمؤثر صوتي في مجموعة أصوات ويشغّله في موضع Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.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()

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

إضافة صوت ستيريو وصوت محيطي إلى تطبيقك

الطريقة المقترَحة لإضافة صوت الاستيريو والصوت المحيطي إلى تطبيقك هي استخدام Exoplayer. لمزيد من المعلومات حول كيفية استخدام ميزة "الصوت المكاني" مع "Exoplayer"، يُرجى الاطّلاع على دليل ميزة "الصوت المكاني".

موضع مكبّرات الصوت الاستيريو والصوت المحيطي

من خلال تحديد موضع مكبّرات الصوت المحيطي، يتم تحديد موضع مكبّرات الصوت المحيطي الافتراضية وتوجيهها بالنسبة إلى مكبّر الصوت المركزي، حول المستخدم في إعدادات ITU العادية.

يتم تلقائيًا وضع مكبّر الصوت الخاص بالقناة المركزية على mainPanelEntity في التطبيق. ويشمل ذلك التطبيقات المتوافقة مع الأجهزة الجوّالة التي يتم فيها تحويل الصوت إلى صوت مكاني تلقائيًا من خلال Android XR.

بالنسبة إلى الاستيريو، يكون موضع مكبّر الصوت مشابهًا للصوت المحيطي، باستثناء أنّه يتم وضع القنوات اليسرى واليمنى فقط على الجانبين الأيسر والأيمن من اللوحة على التوالي.

إذا كان لديك عدة لوحات وأردت اختيار اللوحة التي تصدر الصوت، أو إذا أردت عرض الصوت المجسّم أو المحيطي بالنسبة إلى Entity أخرى، يمكنك استخدام PointSourceAttributes لتحديد موقع القناة المركزية. وسيتم وضع القنوات المتبقية كما هو مذكور سابقًا. في هذه الحالات، يجب أيضًا استخدام MediaPlayer.

As the user moves around their space, the stereo and surround sound virtual speakers will move and adjust to ensure that the speakers are always in an optimal position.

إذا ضبطت MediaPlayer أو ExoPlayer لمواصلة تشغيل صوت الاستيريو أو الصوت المحيطي من الخلفية، سيتم تغيير موضع مكبّر الصوت الافتراضي عند تشغيل التطبيق في الخلفية. بما أنّه لا توجد لوحة أو نقطة أخرى في المساحة لتثبيت الصوت عليها، يتحرّك الصوت المكاني مع المستخدم (بعبارة أخرى، يكون "مثبّتًا على الرأس").

مثال على الصوت المحيطي

يحمّل المثال التالي ملف صوتي 5.1 باستخدام MediaPlayer ويضبط القناة المركزية للملف لتكون Entity.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceParams()

    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,
        entity = session.scene.mainPanelEntity,
    )

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()
} else {
    // The session does not have spatial audio capabilities
}

نقاط رئيسية حول الرمز

إضافة حقول صوتية محيطية إلى تطبيقك

أبسط طريقة لتشغيل حقول الصوت المحيطي هي تحميل الملف باستخدام MediaPlayer. بما أنّ الصوت المحيطي ينطبق على المشهد الصوتي بأكمله، ليس عليك تحديد Entity لتوفير موضع. بدلاً من ذلك، يمكنك إنشاء مثيل من SoundFieldAttributes باستخدام ترتيب الصوت المحيطي المناسب الذي يحدّد عدد القنوات.

مثال على Ambionics

يشغّل المثال التالي مجال صوت محيطي باستخدام MediaPlayer.

// Check spatial capabilities before using spatial audio
if (session.scene.spatialCapabilities.contains(SpatialCapability.SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val soundFieldAttributes =
        SoundFieldAttributes(SpatializerConstants.AmbisonicsOrder.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
}

نقاط رئيسية حول الرمز

  • كما هو الحال مع المقتطفات السابقة، تتمثّل الخطوة الأولى في التحقّق من توفّر إمكانات "الصوت المكاني" باستخدام spatialCapabilities.
  • إنّ contentType واستخدامها هما لأغراض إعلامية بحتة.
  • تشير السمة SpatializerConstants.AmbisonicsOrder.FIRST_ORDER إلى SceneCore بأنّ ملف المجال الصوتي يحدّد أربع قنوات.