เพิ่มเสียงรอบทิศทางลงในแอป XR

ฟีเจอร์เสียงรอบทิศทางใน Jetpack SceneCore ช่วยให้คุณสร้างประสบการณ์เสียงสมจริงภายในแอปพลิเคชัน Android XR ได้

เสียงรอบทิศทางจะจำลองวิธีที่ผู้ใช้รับรู้เสียงในสภาพแวดล้อม 3 มิติ ซึ่งจะสร้างความรู้สึกว่าเสียงมาจากทุกทิศทาง รวมถึงเหนือและใต้ผู้ใช้ โดยระบบจะจำลอง "ผู้พูดเสมือนจริง" อย่างน้อย 1 คนในตำแหน่งที่เจาะจงในพื้นที่ 3 มิติ

แอปที่มีอยู่ซึ่งไม่ได้ออกแบบหรือแก้ไขสำหรับ Android XR จะมีระบบจัดเสียงให้เป็นเสียงรอบทิศทางโดยอัตโนมัติใน Android XR เมื่อผู้ใช้ย้ายไปรอบๆ พื้นที่ทำงาน เสียงของแอปทั้งหมดจะส่งออกมาจากแผงที่มีการแสดงผล UI ของแอป เช่น หากตัวจับเวลาจากแอปนาฬิกาดังขึ้น เสียงจะดูเหมือนมาจากตำแหน่งของแผงแอป Android XR จะเปลี่ยนเสียงให้สมจริงตามตำแหน่งโดยอัตโนมัติ ตัวอย่างเช่น ระยะทางที่รับรู้ระหว่างแผงแอปกับผู้ใช้จะส่งผลต่อระดับเสียงเล็กน้อยเพื่อให้รู้สึกสมจริงยิ่งขึ้น

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่แอปที่มีอยู่แสดงผลเสียงเชิงพื้นที่ได้ที่เพิ่มเสียงสเตอริโอและเสียงเซอร์ราวด์ลงในแอปในหน้านี้

หากคุณเพิ่มประสิทธิภาพแอปสำหรับ XR อยู่ Jetpack SceneCore มีเครื่องมือสำหรับการปรับแต่งเสียงรอบทิศทางขั้นสูง คุณสามารถวางตำแหน่งเสียงในสภาพแวดล้อม 3 มิติได้อย่างแม่นยำ ใช้เสียงแอมบิโซนิกสสำหรับสนามเสียงสมจริง และใช้ประโยชน์จากการผสานรวมเสียงเซอร์ราวด์ในตัว

ประเภทเสียงรอบทิศทางที่ใช้ได้ใน Android XR

Android XR รองรับเสียงแบบตำแหน่ง สเตอริโอ เซอร์ราวด์ และแอมบิโซนิก

เสียงตามตำแหน่ง

เสียงตามตำแหน่งสามารถกำหนดตำแหน่งให้เล่นจากจุดใดจุดหนึ่งในพื้นที่ 3 มิติ เช่น คุณอาจมีโมเดล 3 มิติของสุนัขที่กำลังเห่าอยู่ที่มุมของสภาพแวดล้อมเสมือนจริง คุณสามารถสร้างเอนทิตีหลายรายการที่ส่งเสียงจากตำแหน่งต่างๆ ของเอนทิตีดนั้นๆ ได้ หากต้องการแสดงผลเสียงตามตำแหน่ง ไฟล์ต้องเป็นโมโนหรือสเตอริโอ

เสียงสเตอริโอและเสียงเซอร์ราวด์แบบสมจริง

รองรับรูปแบบสื่อ Android ทั้งหมดสำหรับเสียงตำแหน่ง สเตอริโอ และเซอร์ราวด์

เสียงสเตอริโอหมายถึงรูปแบบเสียงที่มี 2 ช่อง และเสียงเซอร์ราวด์หมายถึงรูปแบบเสียงที่มีมากกว่า 2 ช่อง เช่น การกำหนดค่าเสียงเซอร์ราวด์ 5.1 หรือเสียงเซอร์ราวด์ 7.1 ข้อมูลเสียงของช่องแต่ละช่องจะเชื่อมโยงกับลำโพง 1 ตัว เช่น เมื่อเล่นเพลงแบบสเตอริโอ ช่องลำโพงด้านซ้ายอาจส่งเสียงแทร็กเครื่องดนตรีที่แตกต่างจากด้านขวา

ระบบเสียงเซอร์ราวด์มักใช้ในภาพยนตร์และรายการทีวีเพื่อเพิ่มความสมจริงและประสบการณ์การรับชมด้วยการใช้ลำโพงหลายช่อง ตัวอย่างเช่น เสียงสนทนามักจะเล่นจากช่องลำโพงกลาง ส่วนเสียงเฮลิคอปเตอร์บินอาจใช้ช่องต่างๆ ตามลำดับเพื่อให้รู้สึกว่าเฮลิคอปเตอร์กำลังบินอยู่รอบๆ พื้นที่ 3 มิติ

เสียงแบบแอมบิโซนิก

เสียง Ambisonic (หรือ Ambisonics) เปรียบเสมือนสกายบ็อกซ์สำหรับเสียง ซึ่งจะสร้างบรรยากาศเสียงที่สมจริงให้แก่ผู้ใช้ ใช้แอมบิโซนิกส์สำหรับเสียงสภาพแวดล้อมในเบื้องหลังหรือสถานการณ์อื่นๆ ที่ต้องการจำลองสนามเสียงแบบทรงกลมรอบตัวผู้ฟัง Android XR รองรับรูปแบบเสียงแอมบิโซนิก AmbiX ในรูปแบบแอมบิโซนิกลำดับที่ 1, 2 และ 3 เราขอแนะนำให้ใช้ไฟล์ประเภท Opus (.ogg) และ PCM/Wave (.wav)

ใช้เสียงรอบทิศทางกับ Jetpack SceneCore

การใช้เสียงรอบทิศทางกับ Jetpack SceneCore เกี่ยวข้องกับการตรวจสอบความสามารถของเสียงรอบทิศทางและเลือก API สำหรับการโหลดเสียงรอบทิศทาง

ตรวจสอบความสามารถเชิงพื้นที่

ก่อนใช้ฟีเจอร์เสียงรอบทิศทาง ให้ตรวจสอบว่า Session รองรับเสียงรอบทิศทาง ข้อมูลโค้ดทั้งหมดในส่วนต่อไปนี้จะตรวจสอบความสามารถก่อนพยายามเล่นเสียงแบบเสียงรอบทิศทาง

โหลดเสียงรอบทิศทาง

คุณใช้ API ต่อไปนี้เพื่อโหลดเสียงรอบทิศทางเพื่อใช้ใน Jetpack SceneCore ได้

  • SoundPool: เหมาะสำหรับซาวด์เอฟเฟกต์สั้นๆ ที่มีขนาดน้อยกว่า 1 MB ระบบจะโหลดไว้ล่วงหน้าและสามารถใช้เสียงซ้ำได้ วิธีนี้เป็นวิธีที่ยอดเยี่ยมในการโหลดเสียงสำหรับเสียงตามตำแหน่ง
  • ExoPlayer: เหมาะสำหรับการโหลดเนื้อหาเสียงสเตอริโอและเสียงเซอร์ราวด์ เช่น เพลงและวิดีโอ รวมถึงอนุญาตให้เล่นสื่อในเบื้องหลังด้วย
  • MediaPlayer: แสดงวิธีที่ง่ายที่สุดในการโหลดเสียงแบบแอมบิโซนิก
  • AudioTrack: ให้การควบคุมมากที่สุดเกี่ยวกับวิธีโหลดข้อมูลเสียง อนุญาตให้เขียนบัฟเฟอร์เสียงโดยตรง หรือในกรณีที่คุณสังเคราะห์หรือถอดรหัสไฟล์เสียงของคุณเอง

เพิ่มเสียงตามตำแหน่งลงในแอป

แหล่งที่มาของเสียงตามตำแหน่งจะกำหนดโดย PointSourceParams และ Entity ที่เชื่อมโยง ตำแหน่งและการวางแนวของ Entity จะกำหนดตำแหน่งที่ระบบจะแสดงผล PointSourceParams ในเชิงพื้นที่ 3 มิติ

ตัวอย่างเสียงตามตำแหน่ง

ตัวอย่างต่อไปนี้จะโหลดไฟล์เสียงเอฟเฟกต์ลงในพูลเสียงและเล่นที่ตำแหน่ง 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][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 เป็น CONTENT_TYPE_MUSIC และการใช้งานเป็น USAGE_MEDIA จะช่วยให้ระบบถือว่าไฟล์เสียงนี้เป็นเสียงเซอร์ราวด์

เพิ่มฟิลด์เสียงแบบแอมบิโซนิกลงในแอป

วิธีที่ง่ายที่สุดในการเล่นเสียงแบบแอมบิโซนิกคือโหลดไฟล์ด้วย MediaPlayer เนื่องจากเสียงแอมบิโซนิกมีผลกับทั้งซาวด์สเปซ คุณจึงไม่จำเป็นต้องระบุ Entity เพื่อระบุตำแหน่ง แต่ให้สร้างอินสแตนซ์ของ SoundFieldAttributes ที่มีลําดับ Ambisonic ที่เหมาะสมซึ่งระบุจํานวนช่องแทน

ตัวอย่าง 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
}

ประเด็นสำคัญเกี่ยวกับรหัส

  • เช่นเดียวกับข้อมูลโค้ดก่อนหน้า ขั้นตอนแรกคือตรวจสอบว่าปัจจุบันมีความสามารถของเสียงรอบทิศทางหรือไม่โดยใช้ [getSpatialCapabilities()][getSpatialCapabilities()]
  • contentType และการใช้งานมีไว้เพื่อแจ้งข้อมูลเท่านั้น
  • AMBISONICS_ORDER_FIRST_ORDER จะส่งสัญญาณให้ SceneCore ทราบว่าไฟล์สนามเสียงกำหนดแชแนล 4 ช่อง