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