เสียงรอบทิศทางเป็นประสบการณ์เสียงที่สมจริงซึ่งจะทำให้ผู้ใช้รู้สึกเหมือนอยู่ท่ามกลางเหตุการณ์นั้นๆ และทำให้เนื้อหาของคุณมีเสียงที่สมจริงยิ่งขึ้น เสียงจะได้รับการ "ปรับให้เป็นเสียงรอบทิศทาง" เพื่อสร้างเอฟเฟกต์จากลำโพงหลายตัวคล้ายกับการตั้งค่าเสียงเซอร์ราวด์ แต่จะเล่นผ่านหูฟังแทน
ตัวอย่างเช่น ในภาพยนตร์ เสียงจากรถยนต์อาจเริ่มจากด้านหลังของผู้ใช้ เคลื่อนไปข้างหน้า และค่อยๆ เบาลงเมื่อเคลื่อนห่างออกไป ในวิดีโอแชท ระบบจะแยกเสียงและวางไว้รอบๆ ตัวผู้ใช้ ทำให้ระบุผู้พูดได้ง่ายขึ้น
หากเนื้อหาใช้รูปแบบเสียงที่รองรับ คุณสามารถเพิ่มเสียงรอบทิศทางลงในแอปได้ตั้งแต่ Android 13 (ระดับ API 33) เป็นต้นไป
ค้นหาความสามารถ
ใช้คลาส Spatializer เพื่อค้นหาความสามารถและลักษณะการทำงานของระบบเสียงรอบทิศทางของอุปกรณ์ เริ่มต้นด้วยการดึงข้อมูลอินสแตนซ์ของ Spatializer จาก AudioManager:
Kotlin
val spatializer = audioManager.spatializer
Java
Spatializer spatializer = AudioManager.getSpatializer();
หลังจากได้รับ Spatializer แล้ว ให้ตรวจสอบเงื่อนไข 4 ข้อที่ต้องเป็นจริงเพื่อให้อุปกรณ์ส่งออกเสียงรอบทิศทางได้ ดังนี้
| เกณฑ์ | ตรวจสอบ |
|---|---|
| อุปกรณ์รองรับการสร้างเสียงรอบทิศทางไหม |
getImmersiveAudioLevel() ไม่เท่ากับ SPATIALIZER_IMMERSIVE_LEVEL_NONE
|
| มีฟีเจอร์การสร้างเสียงรอบทิศทางไหม ความพร้อมใช้งานขึ้นอยู่กับความเข้ากันได้กับการกำหนดเส้นทางเอาต์พุตเสียงปัจจุบัน |
isAvailable() คือ true |
| เปิดใช้การแปลงเป็น 3 มิติอยู่ใช่ไหม | isEnabled() คือ true |
| แทร็กเสียงที่มีพารามิเตอร์ที่ระบุสามารถทำให้เป็นเสียงรอบทิศทางได้ไหม | canBeSpatialized() คือ true |
เงื่อนไขเหล่านี้อาจไม่เป็นไปตามที่กำหนด เช่น หากการสร้างเสียงรอบทิศทางไม่พร้อมใช้งานสำหรับแทร็กเสียงปัจจุบันหรือปิดใช้ในอุปกรณ์เอาต์พุตเสียงทั้งหมด
การติดตามการเคลื่อนไหวของศีรษะ
เมื่อใช้ชุดหูฟังที่รองรับ แพลตฟอร์มจะปรับการสร้างเสียงรอบทิศทางตามตำแหน่งศีรษะของผู้ใช้ได้ หากต้องการตรวจสอบว่ามีเครื่องติดตามการเคลื่อนไหวของศีรษะสำหรับการกำหนดเส้นทางเอาต์พุตเสียงปัจจุบันหรือไม่ ให้เรียกใช้ isHeadTrackerAvailable()
เนื้อหาที่เข้ากันได้
Spatializer.canBeSpatialized()
ระบุว่าเสียงที่มีพร็อพเพอร์ตี้ที่ระบุสามารถสร้างเสียงรอบทิศทางด้วยการกำหนดเส้นทางอุปกรณ์เอาต์พุตปัจจุบันได้หรือไม่ เมธอดนี้ใช้ AudioAttributes และ AudioFormat ซึ่งทั้ง 2 รายการมีคำอธิบายโดยละเอียดที่ด้านล่าง
AudioAttributes
ออบเจ็กต์ AudioAttributes อธิบายการใช้งานสตรีมเสียง (เช่น เสียงเกมหรือสื่อมาตรฐาน) พร้อมกับลักษณะการเล่นและประเภทเนื้อหา
เมื่อเรียกใช้ canBeSpatialized() ให้ใช้อินสแตนซ์ AudioAttributes เดียวกันกับที่ตั้งค่าไว้สำหรับ Player ตัวอย่างเช่น หากคุณใช้ไลบรารี Jetpack Media3 และยังไม่ได้ปรับแต่ง AudioAttributes ให้ใช้ AudioAttributes.DEFAULT
กำลังปิดใช้เสียงรอบทิศทาง
หากต้องการระบุว่าเนื้อหาของคุณได้รับการปรับแต่งเสียงรอบทิศทางแล้ว ให้เรียกใช้
setIsContentSpatialized(true)
เพื่อไม่ให้ระบบประมวลผลเสียงซ้ำ หรือปรับลักษณะการทำงานของระบบเสียงรอบทิศทางเพื่อปิดใช้ระบบเสียงรอบทิศทางทั้งหมดโดยเรียกใช้ setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
AudioFormat
ออบเจ็กต์ AudioFormat อธิบายรายละเอียดเกี่ยวกับรูปแบบและการกำหนดค่าช่องของแทร็กเสียง
เมื่อสร้างอินสแตนซ์ AudioFormat เพื่อส่งไปยัง canBeSpatialized() ให้ตั้งค่าการเข้ารหัสให้เหมือนกับรูปแบบเอาต์พุตที่คาดไว้จากตัวถอดรหัส นอกจากนี้ คุณควรตั้งค่ามาสก์ช่องที่ตรงกับการกำหนดค่าช่องของเนื้อหาด้วย ดูคำแนะนำเกี่ยวกับค่าที่เฉพาะเจาะจงที่จะใช้ได้ที่ส่วนลักษณะการทำงานเชิงพื้นที่เริ่มต้น
คอยฟังการเปลี่ยนแปลงใน Spatializer
หากต้องการฟังการเปลี่ยนแปลงในสถานะของ Spatializer คุณสามารถเพิ่ม Listener ด้วย Spatializer.addOnSpatializerStateChangedListener()
ในทำนองเดียวกัน หากต้องการฟังการเปลี่ยนแปลงความพร้อมใช้งานของอุปกรณ์ติดตามการเคลื่อนไหวของศีรษะ ให้เรียกใช้ Spatializer.addOnHeadTrackerAvailableListener()
ซึ่งจะเป็นประโยชน์หากคุณต้องการปรับการเลือกแทร็กระหว่างการเล่นโดยใช้ Callback ของ Listener ตัวอย่างเช่น เมื่อผู้ใช้เชื่อมต่อหรือยกเลิกการเชื่อมต่อชุดหูฟังจากอุปกรณ์ Callback onSpatializerAvailableChanged จะระบุว่าเอฟเฟกต์ Spatializer พร้อมใช้งานสำหรับการกำหนดเส้นทางเอาต์พุตเสียงใหม่หรือไม่ ณ จุดนี้ คุณอาจพิจารณาอัปเดตตรรกะการเลือกแทร็กของเพลเยอร์ให้ตรงกับความสามารถใหม่ของอุปกรณ์ ดูรายละเอียดเกี่ยวกับลักษณะการเลือกแทร็กของ ExoPlayer ได้ที่ส่วน ExoPlayer และเสียงรอบทิศทาง
ExoPlayer และเสียงรอบทิศทาง
ExoPlayer เวอร์ชันล่าสุดช่วยให้ใช้เสียงรอบทิศทางได้ง่ายขึ้น หากคุณใช้ไลบรารี ExoPlayer แบบสแตนด์อโลน (ชื่อแพ็กเกจ com.google.android.exoplayer2) เวอร์ชัน 2.17 จะกำหนดค่าแพลตฟอร์มให้แสดงผลเสียงรอบทิศทาง และเวอร์ชัน 2.18 จะเปิดตัวข้อจำกัดจำนวนช่องเสียง
หากคุณใช้โมดูล ExoPlayer จากคลัง Media3 (ชื่อแพ็กเกจ androidx.media3) เวอร์ชัน 1.0.0-beta01 และใหม่กว่าจะมีการอัปเดตแบบเดียวกันนี้
หลังจากอัปเดตทรัพยากร Dependency ของ ExoPlayer เป็นรุ่นล่าสุดแล้ว แอปของคุณเพียงแค่ต้องมีเนื้อหาที่สามารถปรับเสียงตามตำแหน่งได้
ข้อจำกัดจำนวนช่องเสียง
เมื่อเป็นไปตามเงื่อนไขทั้ง 4 ข้อสำหรับเสียงรอบทิศทาง ExoPlayer จะเลือกแทร็กเสียงแบบหลายช่องทาง หากไม่ ExoPlayer จะเลือกแทร็กสเตอริโอแทน
หากพร็อพเพอร์ตี้ Spatializer เปลี่ยนแปลง ExoPlayer จะทริกเกอร์การเลือกแทร็กใหม่เพื่อเลือกแทร็กเสียงที่ตรงกับพร็อพเพอร์ตี้ปัจจุบัน โปรดทราบว่าการเลือกแทร็กใหม่นี้อาจทำให้เกิดการบัฟเฟอร์ซ้ำเป็นระยะเวลาสั้นๆ
หากต้องการปิดใช้ข้อจำกัดจำนวนช่องเสียง ให้ตั้งค่าพารามิเตอร์การเลือกแทร็กในเพลเยอร์ดังที่แสดงด้านล่าง
Kotlin
exoPlayer.trackSelectionParameters = DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
exoPlayer.setTrackSelectionParameters( new DefaultTrackSelector.Parameters.Builder(context) .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
ในทำนองเดียวกัน คุณสามารถอัปเดตพารามิเตอร์ของตัวเลือกแทร็กที่มีอยู่เพื่อปิดใช้ข้อจำกัดจำนวนช่องเสียงได้ดังนี้
Kotlin
val trackSelector = DefaultTrackSelector(context) ... trackSelector.parameters = trackSelector.buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build()
Java
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); ... trackSelector.setParameters( trackSelector .buildUponParameters() .setConstrainAudioChannelCountToDeviceCapabilities(false) .build() );
เมื่อปิดใช้ข้อจำกัดจำนวนช่องเสียง หากเนื้อหามีแทร็กเสียงหลายแทร็ก ExoPlayer จะเลือกแทร็กที่มีจำนวนช่องสูงสุดและเล่นได้จากอุปกรณ์ในตอนแรก เช่น หากเนื้อหามีแทร็กเสียงแบบหลายช่องทางและแทร็กเสียงแบบสเตอริโอ และอุปกรณ์รองรับการเล่นทั้ง 2 แบบ ExoPlayer จะเลือกแทร็กแบบหลายช่องทาง ดูรายละเอียดเกี่ยวกับวิธีปรับแต่งลักษณะการทำงานนี้ได้ที่การเลือกแทร็กเสียง
การเลือกแทร็กเสียง
เมื่อปิดใช้ลักษณะการทำงานข้อจำกัดจำนวนช่องเสียงของ ExoPlayer แล้ว ExoPlayer จะไม่เลือกแทร็กเสียงที่ตรงกับพร็อพเพอร์ตี้ของ Spatializer ของอุปกรณ์โดยอัตโนมัติ แต่คุณสามารถปรับแต่งตรรกะการเลือกแทร็กของ ExoPlayer ได้โดยตั้งค่าพารามิเตอร์การเลือกแทร็กก่อนหรือระหว่างการเล่น โดยค่าเริ่มต้น ExoPlayer จะเลือกแทร็กเสียงที่เหมือนกับแทร็กเริ่มต้นในแง่ของประเภท MIME (การเข้ารหัส) จำนวนช่อง และอัตราการสุ่มตัวอย่าง
การเปลี่ยนพารามิเตอร์การเลือกแทร็ก
หากต้องการเปลี่ยนพารามิเตอร์การเลือกแทร็กของ ExoPlayer ให้ใช้ Player.setTrackSelectionParameters()
ในทำนองเดียวกัน คุณสามารถดูพารามิเตอร์ปัจจุบันของ ExoPlayer ได้ด้วย Player.getTrackSelectionParameters()
ตัวอย่างเช่น หากต้องการเลือกแทร็กเสียงสเตอริโอระหว่างการเล่น ให้ทำดังนี้
Kotlin
exoPlayer.trackSelectionParameters = exoPlayer.trackSelectionParameters .buildUpon() .setMaxAudioChannelCount(2) .build()
Java
exoPlayer.setTrackSelectionParameters( exoPlayer.getTrackSelectionParameters() .buildUpon() .setMaxAudioChannelCount(2) .build() );
โปรดทราบว่าการเปลี่ยนพารามิเตอร์การเลือกแทร็กระหว่างการเล่นอาจทำให้การเล่นหยุดชะงัก ดูข้อมูลเพิ่มเติมเกี่ยวกับการปรับพารามิเตอร์การเลือกแทร็กของเพลเยอร์ได้ในส่วนการเลือกแทร็กของเอกสาร ExoPlayer
ลักษณะการทำงานของระบบเสียงรอบทิศทางเริ่มต้น
ลักษณะการทำงานเชิงมิติสัมพันธ์เริ่มต้นใน Android มีลักษณะการทำงานต่อไปนี้ที่ OEM อาจปรับแต่งได้
ระบบจะปรับเฉพาะเนื้อหาแบบหลายช่องให้เป็นเสียงรอบทิศทาง ไม่ใช่เนื้อหาแบบสเตอริโอ หากไม่ได้ใช้ ExoPlayer คุณอาจต้องกำหนดค่าจำนวนช่องสูงสุดที่ตัวถอดรหัสเสียงสามารถส่งออกเป็นจำนวนมาก ทั้งนี้ขึ้นอยู่กับรูปแบบของเนื้อหาเสียงแบบหลายช่องทาง ซึ่งจะช่วยให้มั่นใจว่าตัวถอดรหัสเสียงจะส่งออก PCM แบบหลายช่องทางเพื่อให้แพลตฟอร์มสร้างเสียงรอบทิศทางได้
Kotlin
val mediaFormat = MediaFormat() mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99)
Java
MediaFormat mediaFormat = new MediaFormat(); mediaFormat.setInteger(MediaFormat.KEY_MAX_OUTPUT_CHANNEL_COUNT, 99);
ดูตัวอย่างการใช้งานจริงได้ที่
MediaCodecAudioRenderer.javaของ ExoPlayer หากต้องการปิดการแปลงเป็นเสียงรอบทิศทางด้วยตนเอง ไม่ว่า OEM จะปรับแต่งอย่างไร โปรดดูหัวข้อการปิดใช้เสียงรอบทิศทางAudioAttributes: เสียงมีสิทธิ์ใช้การประมวลผลเสียงรอบทิศทางหากตั้งค่าusageเป็นUSAGE_MEDIAหรือUSAGE_GAMEAudioFormat: ใช้มาสก์ช่องที่มีช่องAudioFormat.CHANNEL_OUT_QUAD(หน้าซ้าย หน้าขวา หลังซ้าย และหลังขวา) เป็นอย่างน้อยเพื่อให้เสียงมีสิทธิ์ใช้ระบบเสียงรอบทิศทาง ในตัวอย่างด้านล่าง เราใช้AudioFormat.CHANNEL_OUT_5POINT1สำหรับแทร็กเสียง 5.1 สำหรับแทร็กเสียงสเตอริโอ ให้ใช้AudioFormat.CHANNEL_OUT_STEREOหากใช้ Media3 คุณสามารถใช้
Util.getAudioTrackChannelConfig(int channelCount)เพื่อแปลงจำนวนช่องเป็นมาสก์ช่องได้นอกจากนี้ ให้ตั้งค่าการเข้ารหัสเป็น
AudioFormat.ENCODING_PCM_16BITหากคุณกำหนดค่าตัวถอดรหัสให้ส่งออก PCM แบบหลายช่องทางKotlin
val audioFormat = AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build()
Java
AudioFormat audioFormat = new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1) .build();
ทดสอบเสียงรอบทิศทาง
ตรวจสอบว่าได้เปิดใช้เสียงรอบทิศทางในอุปกรณ์ทดสอบแล้ว โดยทำดังนี้
- สำหรับชุดหูฟังแบบมีสาย ให้ไปที่การตั้งค่าระบบ > เสียงและการสั่น > เสียงรอบทิศทาง
- สำหรับชุดหูฟังไร้สาย ให้ไปที่การตั้งค่าระบบ > อุปกรณ์ที่เชื่อมต่อ > ไอคอนรูปเฟืองสำหรับอุปกรณ์ไร้สาย > เสียงรอบทิศทาง
หากต้องการตรวจสอบความพร้อมใช้งานของเสียงรอบทิศทางสำหรับการกำหนดเส้นทางปัจจุบัน ให้เรียกใช้คำสั่ง adb shell dumpsys audio ในอุปกรณ์ คุณควรเห็นพารามิเตอร์ต่อไปนี้ในเอาต์พุตขณะที่การเล่นทำงานอยู่
Spatial audio:
mHasSpatializerEffect:true (effect present)
isSpatializerEnabled:true (routing dependent)