เสียงรอบทิศทางเป็นประสบการณ์เสียงสมจริงที่ช่วยให้ผู้ใช้รู้สึกเหมือนอยู่ในเหตุการณ์จริง ทำให้เนื้อหาของคุณมีเสียงสมจริงยิ่งขึ้น ระบบจะ "จัดเสียงให้รอบทิศทาง" เพื่อสร้างเอฟเฟกต์จากลำโพงหลายตัว ซึ่งคล้ายกับการตั้งค่าเสียงเซอร์ราวด์ แต่ฟังผ่านหูฟังแทน
เช่น ในภาพยนตร์ เสียงจากรถอาจดังขึ้นด้านหลังผู้ใช้ ไปข้างหน้า และพุ่งออกสู่ระยะไกล ในวิดีโอคอล ระบบจะแยกเสียงและวางเสียงรอบๆ ผู้ใช้ได้ ซึ่งช่วยให้ระบุผู้พูดได้ง่ายขึ้น
หากเนื้อหาใช้รูปแบบเสียงที่รองรับ คุณจะเพิ่มเสียงรอบทิศทางลงในแอปได้ตั้งแต่ 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 |
มีการเปิดใช้งานระบบเชิงพื้นที่หรือไม่ | isEnabled() คือ true |
แทร็กเสียงที่มีพารามิเตอร์ที่ระบุสามารถเปลี่ยนเป็นเสียงรอบทิศทางได้ไหม | canBeSpatialized() คือ true |
และอาจไม่เป็นไปตามเงื่อนไขเหล่านี้ เช่น ในกรณีที่ระบบเสียงไม่พร้อมใช้งานสำหรับแทร็กเสียงปัจจุบันหรือปิดการใช้งานบนอุปกรณ์เอาต์พุตเสียงโดยสิ้นเชิง
การติดตามการเคลื่อนไหวของศีรษะ
ด้วยชุดหูฟังที่รองรับ แพลตฟอร์มจะปรับระยะห่างของเสียงโดยอิงตามตำแหน่งศีรษะของผู้ใช้ได้ หากต้องการตรวจสอบว่าอุปกรณ์ติดตามการเคลื่อนไหวของศีรษะพร้อมใช้งานสำหรับการกำหนดเส้นทางเอาต์พุตเสียงปัจจุบันหรือไม่ ให้เรียกใช้ isHeadTrackerAvailable()
เนื้อหาที่เข้ากันได้
Spatializer.canBeSpatialized()
ระบุว่าเสียงที่มีพร็อพเพอร์ตี้ที่ระบุสามารถจัดวางเสียงตามตำแหน่งด้วยการกำหนดเส้นทางอุปกรณ์เอาต์พุตปัจจุบันได้หรือไม่ วิธีนี้ใช้ AudioAttributes
และ AudioFormat
ซึ่งอธิบายไว้อย่างละเอียดด้านล่าง
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()
วิธีนี้มีประโยชน์หากคุณต้องการปรับการเลือกแทร็กระหว่างการเล่นโดยใช้การเรียกกลับของผู้ฟัง เช่น เมื่อผู้ใช้เชื่อมต่อหรือยกเลิกการเชื่อมต่อชุดหูฟังกับอุปกรณ์ การเรียกกลับของ onSpatializerAvailableChanged
จะระบุว่าเอฟเฟกต์กระจายแสงพร้อมใช้งานสำหรับการกำหนดเส้นทางเอาต์พุตเสียงใหม่หรือไม่ เมื่อถึงจุดนี้ คุณอาจพิจารณาอัปเดตตรรกะการเลือกแทร็กของเครื่องเล่นให้ตรงกับความสามารถใหม่ของอุปกรณ์ ดูรายละเอียดเกี่ยวกับลักษณะการเลือกแทร็กใน 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 จะไม่เลือกแทร็กเสียงโดยอัตโนมัติซึ่งตรงกับพร็อพเพอร์ตี้ของโปรแกรมจำลองเสียง 3 มิติของอุปกรณ์ แต่คุณสามารถปรับแต่งตรรกะการเลือกแทร็กได้โดยใช้การตั้งค่าพารามิเตอร์การเลือกแทร็กก่อนหรือระหว่างการเล่น โดยค่าเริ่มต้น 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_GAME
AudioFormat
: ใช้มาสก์แชแนลที่มีแชแนลอย่างน้อย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)