ระบบเสียงตามตำแหน่งเป็นประสบการณ์ด้านเสียงที่สมจริงซึ่งจะทำให้ผู้ใช้เป็นศูนย์กลางของทุกสิ่ง ทำให้เนื้อหาของคุณฟังดูสมจริงยิ่งขึ้น ระบบจะ "ปรับเสียงให้เป็นเสียงรอบทิศทาง" เพื่อสร้างเอฟเฟกต์จากลำโพงหลายตัว คล้ายกับการตั้งค่าเสียงเซอร์ราวด์ แต่จะใช้หูฟังแทน
ตัวอย่างเช่น ในภาพยนตร์ เสียงจากรถยนต์อาจเริ่มจากด้านหลังผู้ใช้ เคลื่อนที่ ไปข้างหน้า และค่อยๆ จางหายไปในระยะไกล ในวิดีโอแชท ระบบจะ แยกเสียงและวางไว้รอบๆ ผู้ใช้ ทำให้ระบุผู้พูดได้ง่ายขึ้น
หากเนื้อหาใช้รูปแบบเสียงที่รองรับ คุณจะเพิ่มระบบเสียงเชิงพื้นที่ลงในแอปได้ตั้งแต่ Android 13 (API ระดับ 33) เป็นต้นไป
ค้นหาความสามารถ
ใช้คลาส Spatializer
เพื่อ
ค้นหาความสามารถและลักษณะการทำงานของระบบเสียง 3 มิติของอุปกรณ์ เริ่มต้นด้วยการเรียกข้อมูล
อินสแตนซ์ของ 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()
ระบุว่าเสียงที่มีพร็อพเพอร์ตี้ที่ระบุจะสามารถสร้างเสียงแบบ 3 มิติด้วย
การกำหนดเส้นทางอุปกรณ์เอาต์พุตปัจจุบันได้หรือไม่ วิธีนี้ต้องใช้ AudioAttributes
และ AudioFormat
ซึ่งเราจะอธิบายรายละเอียดเพิ่มเติมไว้ด้านล่าง
AudioAttributes
ออบเจ็กต์ AudioAttributes
อธิบายการใช้งานของ
สตรีมเสียง (เช่น เสียงเกม
หรือสื่อมาตรฐาน)
พร้อมกับลักษณะการทำงานของการเล่นและประเภทเนื้อหา
เมื่อโทรหา canBeSpatialized()
ให้ใช้อินสแตนซ์ AudioAttributes
เดียวกันกับที่ตั้งค่าไว้สำหรับ Player
เช่น หากคุณใช้ไลบรารี Jetpack Media3 และไม่ได้ปรับแต่ง
AudioAttributes
ให้ใช้ AudioAttributes.DEFAULT
การปิดใช้เสียงรอบทิศทาง
หากต้องการระบุว่าเนื้อหาของคุณมีการปรับเสียงตามพื้นที่แล้ว ให้เรียกใช้
setIsContentSpatialized(true)
เพื่อไม่ให้ระบบประมวลผลเสียงซ้ำ หรือปรับลักษณะการทำงานของ
การทำให้เสียงเป็นระบบ 3 มิติเพื่อปิดใช้การทำให้เสียงเป็นระบบ 3 มิติทั้งหมดโดยการเรียกใช้
setSpatializationBehavior(AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER)
AudioFormat
ออบเจ็กต์ AudioFormat
จะอธิบาย
รายละเอียดเกี่ยวกับรูปแบบและการกำหนดค่าช่องของแทร็กเสียง
เมื่อสร้างอินสแตนซ์ของ AudioFormat
เพื่อส่งไปยัง canBeSpatialized()
ให้ตั้งค่าการเข้ารหัส
ให้เหมือนกับรูปแบบเอาต์พุตที่คาดหวังจากตัวถอดรหัส นอกจากนี้ คุณควรตั้งค่ามาสก์ช่อง
ให้ตรงกับการกำหนดค่าช่องของเนื้อหาด้วย โปรดดูคำแนะนำเกี่ยวกับค่าที่เฉพาะเจาะจงที่จะใช้ในส่วนลักษณะการทำงานเริ่มต้นของการกำหนดตำแหน่งเสียง
คอยติดตามการเปลี่ยนแปลงใน Spatializer
หากต้องการฟังการเปลี่ยนแปลงในสถานะของ Spatializer
คุณสามารถเพิ่ม Listener
ด้วย Spatializer.addOnSpatializerStateChangedListener()
ในทำนองเดียวกัน หากต้องการฟังการเปลี่ยนแปลงความพร้อมใช้งานของเครื่องมือติดตามศีรษะ ให้เรียกใช้ Spatializer.addOnHeadTrackerAvailableListener()
ซึ่งจะเป็นประโยชน์หากคุณต้องการปรับการเลือกแทร็กระหว่างการเล่น
โดยใช้การเรียกกลับของผู้ฟัง เช่น เมื่อผู้ใช้เชื่อมต่อหรือยกเลิกการเชื่อมต่อชุดหูฟังกับอุปกรณ์
แฮนเดิลการเรียกกลับ onSpatializerAvailableChanged
จะระบุว่าเอฟเฟกต์ Spatializer พร้อมใช้งานสำหรับการกำหนดเส้นทางเอาต์พุตเสียงใหม่หรือไม่ ในตอนนี้ คุณอาจพิจารณาอัปเดตตรรกะการเลือกแทร็กของเพลเยอร์
ให้ตรงกับความสามารถใหม่ของอุปกรณ์ ดูรายละเอียดเกี่ยวกับลักษณะการทำงานของการเลือกแทร็กของ ExoPlayer ได้ที่ส่วนExoPlayer และเสียงรอบทิศทาง
ExoPlayer และเสียงรอบทิศทาง
ExoPlayer เวอร์ชันล่าสุดช่วยให้ใช้เสียงรอบทิศทางได้ง่ายขึ้น หากคุณใช้ไลบรารี ExoPlayer แบบสแตนด์อโลน (ชื่อแพ็กเกจ com.google.android.exoplayer2
)
เวอร์ชัน 2.17 จะกำหนดค่าแพลตฟอร์มให้ออกเสียงเชิงพื้นที่ และเวอร์ชัน
2.18 จะมีข้อจำกัดเกี่ยวกับจำนวนช่องเสียง
หากคุณใช้โมดูล ExoPlayer จากไลบรารี Media3 (ชื่อแพ็กเกจ
androidx.media3
) เวอร์ชัน 1.0.0-beta01
และใหม่กว่าจะมีการอัปเดตเดียวกันนี้
หลังจากอัปเดตการอ้างอิง 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_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)