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