איך מוסיפים אודיו מרחבי לאפליקציית XR

התכונות של האודיו המרחבי ב-Jetpack SceneCore מאפשרות לכם ליצור חוויות אודיו immersive באפליקציות ל-Android XR.

אודיו מרחבי מדמה את האופן שבו משתמשים תופסים צלילים בסביבה תלת-ממדית. הוא יוצר תחושה של צליל שמגיע מכל הכיוונים, כולל מעל ומטה מהמשתמש. המערכת עושה זאת באמצעות סימולציה של "דוברים וירטואליים" אחד או יותר במיקומים ספציפיים במרחב תלת-ממדי.

באפליקציות קיימות שלא תוכננו או שונו עבור Android XR, האודיו מקבל מיקום אוטומטי במרחב ב-Android XR. כשהמשתמש נע במרחב המשותף, כל האודיו מהאפליקציה יושמע מהלוח שבו מוצג ממשק המשתמש של האפליקציה. לדוגמה, אם טיימר מצלצל באפליקציית שעון, הקול נשמע כאילו הוא מגיע ממיקום לוח האפליקציות. Android XR ישנה את הצליל באופן אוטומטי כדי לשפר את תחושת המיקום. לדוגמה, המרחק המשוער בין חלונית האפליקציה למשתמש ישפיע באופן עדין על עוצמת האודיו כדי ליצור תחושה ריאליסטית יותר.

מידע נוסף על האופן שבו אפליקציות קיימות מייצרות אודיו מרחבי זמין בקטע הוספת צליל סטריאו וצליל סראונד לאפליקציה שבדף הזה.

אם אתם מבצעים אופטימיזציה של האפליקציה ל-XR, Jetpack SceneCore מספק כלים להתאמה אישית מתקדמת של אודיו מרחבי. אתם יכולים למקם צלילים בסביבת ה-3D בצורה מדויקת, להשתמש באודיו אמביסוניק כדי ליצור שדות קול ריאליסטיים וליהנות משילוב מובנה של צליל סראונד.

סוגי האודיו המרחבי שזמינים ב-Android XR

ב-Android XR יש תמיכה באודיו מיקומי, אודיו סטריאופוני, אודיו סראונד ואודיו אמביסוני.

אודיו מיקומי

אפשר למקם אודיו מיקומי כך שיופעל מנקודה ספציפית במרחב תלת-ממדי. לדוגמה, אפשר להציג מודל תלת-ממד של כלב נובח בפינה של הסביבה הווירטואלית. אפשר להגדיר כמה ישויות שיפיקו קול מכל אחת מהמיקומים שלהן. כדי להציג אודיו מיקומי, הקובצים צריכים להיות מונו או סטריאו.

צליל סטריאופוני וצליל סראונד מרחבי

יש תמיכה בכל פורמטי המדיה של Android לצליל מיקומי, סטריאופוני וסראונד.

אודיו סטריאופוני מתייחס לפורמטים של אודיו עם שני ערוצים, וצליל סראונד מתייחס לפורמטים של אודיו עם יותר משני ערוצים, כמו הגדרות של צליל סראונד 5.1 או צליל סראונד 7.1. נתוני האודיו של כל ערוץ משויכים לרמקול אחד. לדוגמה, כשמפעילים מוזיקה בסטריאו, ייתכן שערוצי הרמקול השמאלי והימני ישמיעו טראקים שונים של כלי נגינה.

לעיתים קרובות משתמשים בצליל סראונד בסרטים ובתוכניות טלוויזיה כדי לשפר את תחושת הריאליזם וההתמקדות באמצעות שימוש בכמה ערוצי רמקולים. לדוגמה, לעיתים קרובות הדיאלוג מושמע בערוץ של הרמקול המרכזי, בעוד שצליל של מסוק שטס עשוי להשתמש בערוצים שונים ברצף כדי ליצור תחושה שהמסוק טס במרחב התלת-ממדי.

אודיו אמביסוני

אודיו Ambisonic (או אמביסוניק) הוא כמו תא טלוויזיה לאירועים מיוחדים לאודיו, שמספק למשתמשים סאונד סביבה (soundscape) עשיר. כדאי להשתמש ב-Ambisonics לצלילים סביבתיים ברקע או בתרחישים אחרים שבהם רוצים ליצור שדה קול סגלילי מלא שמקיף את המאזין. ב-Android XR יש תמיכה בפורמט האודיו האמביסוניק AmbiX באמביסוניקס מסדר ראשון, שני ושלישי. מומלץ להשתמש בסוגי הקבצים Opus (.ogg) ו-PCM/Wave (.wav).

שימוש באודיו מרחבי באמצעות Jetpack SceneCore

כדי להטמיע אודיו מרחבי באמצעות Jetpack SceneCore, צריך לבדוק אם יש יכולות אודיו מרחבי ולבחור ממשק API לטעינה של אודיו מרחבי.

בדיקת היכולות המרחביות

לפני שמשתמשים בתכונות של אודיו מרחבי, צריך לבדוק אם Session תומך באודיו מרחבי. בכל קטעי הקוד שבקטעים הבאים, היכולות נבדקות לפני שמנסים להשמיע אודיו מרחבי.

טעינת אודיו מרחבי

אפשר להשתמש בכל אחד מממשקי ה-API הבאים כדי לטעון אודיו מרחבי לשימוש ב-Jetpack SceneCore.

  • SoundPool: אידיאלי לאפקטי צליל קצרים בגודל של פחות מ-1MB. הם נטענים מראש וניתן להשתמש בהם שוב ושוב. זו דרך מצוינת לטעון אודיו עבור אודיו מיקומי.
  • ExoPlayer: אידיאלי לטעינה של תוכן בסטריאו ובסראונד, כמו מוזיקה וסרטונים. היא מאפשרת גם הפעלת מדיה ברקע.
  • MediaPlayer: הדרך הפשוטה ביותר לטעון אודיו אמביסוני.
  • AudioTrack: האפשרות שמספקת את מידת השליטה הרבה ביותר על אופן טעינת נתוני האודיו. מאפשרת לכתוב ישירות מאגרי אודיו, או אם יצרתם או דקודתם קובצי אודיו משלכם.

הוספת אודיו מיקומי לאפליקציה

מקורות אודיו מיקומיים מוגדרים לפי PointSourceAttributes ו-Entity משויך. המיקום והכיוון של Entity קובעים איפה PointSourceAttribute יומר במרחב תלת-ממדי.

דוגמה לאודיו מיקומי

בדוגמה הבאה נטען קובץ אודיו של אפקט קול למאגר אודיו ומפעילים אותו במיקום של Entity.

// Check spatial capabilities before using spatial audio
if (xrSession.getSpatialCapabilities().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 = PointSourceAttributes(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 = xrSession,
                soundPool = soundPool,
                soundID = pointSoundId,
                attributes = pointSource,
                volume = maxVolume,
                priority = lowPriority,
                loop = infiniteLoop,
                rate = normalSpeed
            )
        }
    }
} else {
    // The session does not have spatial audio capabilities
}

נקודות חשובות לגבי הקוד

  • בשלב הראשון, צריך לבדוק אם התכונות של האודיו המרחבי זמינות כרגע באמצעות getSpatialCapabilities().
  • הגדרת contentType ל-CONTENT_TYPE_SONIFICATION והגדרת usage ל-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 (xrSession.getSpatialCapabilities().hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_SPATIAL_AUDIO)) {
    // The session has spatial audio capabilities

    val pointSourceAttributes = PointSourceAttributes(xrSession.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.setPointSourceAttributes(
        xrSession,
        mediaPlayer,
        pointSourceAttributes)

    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 (xrSession.getSpatialCapabilities().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(
        xrSession,
        mediaPlayer,
        soundFieldAttributes)

    mediaPlayer.setAudioAttributes(audioAttributes)
    mediaPlayer.prepare()
    mediaPlayer.start()

} else {
    // The session does not have spatial audio capabilities
}

נקודות חשובות לגבי הקוד

  • בדומה לקטע הקוד הקודם, השלב הראשון הוא לבדוק אם יכולות האודיו המרחבי זמינות כרגע באמצעות getSpatialCapabilities().
  • השדות contentType ו-usage הם למטרות מידע בלבד.
  • הערך AMBISONICS_ORDER_FIRST_ORDER מאותת ל-SceneCore שקובץ שדה האודיו מגדיר ארבעה ערוצים.