ฟีเจอร์เสียงรอบทิศทางใน 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 ทั้งหมดสำหรับเสียงตามตำแหน่ง เสียงสเตอริโอ และเสียงเซอร์ราวด์ นอกจากรูปแบบเหล่านี้แล้ว อุปกรณ์ Android XR อาจรองรับรูปแบบเสียง Dolby Atmos, Dolby Digital และ Dolby Digital+ ด้วย
เสียงสเตอริโอหมายถึงรูปแบบเสียงที่มี 2 ช่องสัญญาณ และเสียงเซอร์ราวด์หมายถึงรูปแบบเสียงที่มีมากกว่า 2 ช่องสัญญาณ เช่น การกำหนดค่าเสียงเซอร์ราวด์ 5.1 หรือเสียงเซอร์ราวด์ 7.1 ข้อมูลเสียงของแต่ละช่องจะเชื่อมโยงกับลำโพง 1 ตัว ตัวอย่างเช่น เมื่อเล่นเพลงในระบบสเตอริโอ ช่องลำโพงด้านซ้ายอาจส่งเสียงเครื่องดนตรีที่แตกต่างจากด้านขวา
เสียงเซอร์ราวด์มักใช้ในภาพยนตร์และรายการทีวีเพื่อเพิ่มความสมจริงและความดื่มด่ำผ่านการใช้ช่องลำโพงหลายช่อง ตัวอย่างเช่น บทสนทนามักจะเล่นจากช่องลำโพงกลาง ขณะที่เสียงเฮลิคอปเตอร์บินอาจใช้ช่องต่างๆ ตามลำดับเพื่อให้รู้สึกว่าเฮลิคอปเตอร์กำลังบินอยู่รอบๆ พื้นที่ 3 มิติของคุณ
เสียง Ambisonic
เสียง Ambisonic (หรือ Ambisonics) เป็นเหมือนสกายบ็อกซ์สำหรับเสียง ซึ่งมอบภูมิทัศน์เสียงที่สมจริงให้แก่ผู้ใช้ ใช้ Ambisonics สำหรับเสียงสภาพแวดล้อมในพื้นหลังหรือสถานการณ์อื่นๆ ที่คุณต้องการจำลองสนามเสียงแบบทรงกลมเต็มรูปแบบที่ล้อมรอบผู้ฟัง Android XR รองรับรูปแบบเสียง Ambisonic AmbiX ใน Ambisonic ลำดับที่ 1, 2 และ 3 เราขอแนะนำให้ใช้ประเภทไฟล์ Opus (.ogg) และ PCM/Wave (.wav)
ใช้เสียงรอบทิศทางกับ Jetpack SceneCore
การใช้เสียงรอบทิศทางกับ Jetpack SceneCore เกี่ยวข้องกับการตรวจสอบความสามารถเชิงพื้นที่และการเลือก API สำหรับโหลดเสียงรอบทิศทาง
ตรวจสอบความสามารถเชิงพื้นที่
ก่อนใช้ฟีเจอร์เสียงรอบทิศทาง ให้ตรวจสอบว่า Session รองรับเสียงรอบทิศทาง ในข้อมูลโค้ดทั้งหมดในส่วนต่อไปนี้ ระบบจะตรวจสอบความสามารถก่อนพยายามเล่นเสียงรอบทิศทาง
โหลดเสียงรอบทิศทาง
คุณสามารถใช้ API ต่อไปนี้เพื่อโหลดเสียงรอบทิศทางเพื่อใช้ใน Jetpack SceneCore
SoundPool: เหมาะสำหรับเอฟเฟกต์เสียงสั้นๆ ที่มีขนาดไม่เกิน 1 MB โดยจะโหลดไว้ล่วงหน้าและใช้เสียงซ้ำได้ วิธีนี้เป็นวิธีที่ยอดเยี่ยมในการโหลดเสียงสำหรับเสียงตามตำแหน่งExoPlayer: เหมาะสำหรับการโหลดเนื้อหาเสียงสเตอริโอและเสียงเซอร์ราวด์ เช่น เพลงและวิดีโอ นอกจากนี้ยังอนุญาตให้เล่นสื่อขณะล็อกหน้าจอหรือขณะใช้แอปอื่นด้วยMediaPlayer: วิธีที่ง่ายที่สุดในการโหลดเสียง AmbisonicAudioTrack: ให้การควบคุมวิธีโหลดข้อมูลเสียงได้มากที่สุด ช่วยให้เขียนบัฟเฟอร์ของเสียงได้โดยตรง หรือหากคุณสังเคราะห์หรือถอดรหัสไฟล์เสียงของคุณเอง
ตรวจสอบการรองรับรูปแบบสื่อ
แพลตฟอร์ม 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 แสดงผลในพื้นที่ 3 มิติ เรียกใช้ 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_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.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 }
ประเด็นสำคัญเกี่ยวกับโค้ด
- เช่นเดียวกับในตัวอย่างเสียงตามตำแหน่ง ขั้นตอนแรกคือการตรวจสอบว่าความสามารถของเสียงรอบทิศทางพร้อมใช้งานหรือไม่โดยใช้
spatialCapabilities - การตั้งค่า
contentTypeเป็นAudioAttributes.CONTENT_TYPE_MUSICและการใช้งานเป็นAudioAttributes.USAGE_MEDIAจะช่วยให้ระบบถือว่าไฟล์เสียงนี้เป็นเสียงเซอร์ราวด์
เพิ่มสนามเสียง Ambisonic ลงในแอป
วิธีที่ง่ายที่สุดในการเล่นสนามเสียง Ambisonic คือการโหลดไฟล์ด้วย MediaPlayer เนื่องจากเสียง Ambisonic มีผลกับภาพรวมของเสียงทั้งหมด คุณจึงไม่จำเป็นต้องระบุ Entity เพื่อระบุตำแหน่ง แต่คุณจะสร้างอินสแตนซ์ของ SoundFieldAttributes ที่มีลำดับ Ambisonic ที่เหมาะสมซึ่งระบุจำนวนช่องแทน
ตัวอย่าง Ambionics
ตัวอย่างต่อไปนี้จะเล่นสนามเสียง Ambisonic โดยใช้ 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 ว่าไฟล์สนามเสียงกำหนดช่องสัญญาณไว้ 4 ช่อง