ตั้งแต่ Android 17 QPR1 (ระดับ API 37.1 หรือ
Build.VERSION_CODES_FULL.CINNAMON_BUN_1) เป็นต้นไป Android จะเปิดตัวการรองรับแพลตฟอร์ม
สำหรับการเข้ารหัส Extended High Efficiency Advanced Audio Coding (xHE-AAC)
xHE-AAC ซึ่งกำหนดไว้ใน ISO/IEC 23003-3 (MPEG-D USAC) และ
ISO/IEC 23003-4 (MPEG-D DRC) ผสานรวมการเข้ารหัสเสียงและคำพูดแบบรวมเข้ากับการปรับระดับเสียงตามข้อกำหนดและการควบคุมช่วงไดนามิกในตัว
แม้ว่าเอกสารนิยามความเข้ากันได้ของ Android (CDD) จะรองรับและกำหนดให้ใช้การถอดรหัส xHE-AAC ในแพลตฟอร์มหลายเวอร์ชัน แต่การเพิ่มตัวเข้ารหัส xHE-AAC
(c2.android.xheaac.encoder และการติดตั้งใช้งานฮาร์ดแวร์ OEM) จะช่วยให้คุณบันทึกข้อความเสียงและเสียงที่มีอัตราบิตต่ำ สตรีมเสียงสด และเพย์โหลดการสื่อสารด้วยความชัดเจนของเสียงพูดที่ยอดเยี่ยมและระดับเสียงที่สม่ำเสมอในอุปกรณ์ต่างๆ
ประโยชน์ของ xHE-AAC
โดยปกติแล้ว การบันทึกเสียงแบบเดิมในแอปส่งข้อความ Android จะใช้ AAC-LC (AAC Low Complexity) เวอร์ชันเก่าที่ 28 kbps ที่บิตเรตต่ำ (<32 kbps) AAC-LC แสดงให้เห็นถึงอาร์ติแฟกต์การจำกัดแถบความถี่ที่สังเกตได้ คุณภาพเสียงพูดที่ไม่ชัด และ ประสิทธิภาพการบีบอัดที่ไม่เหมาะสม สำหรับผู้ใช้ปลายทาง เสียงที่ได้จะอู้อี้ แหลมเล็ก และแยกพยัญชนะได้ยาก ทำให้ผู้ฟังต้อง เล่นข้อความซ้ำหรือตั้งใจฟังเป็นพิเศษเพื่อทำความเข้าใจคำพูดในสภาพแวดล้อมที่มีเสียงดัง นอกจากนี้ ระดับเสียงที่ไม่สอดคล้องกันในคลิปเสียงยังบังคับให้ผู้ใช้ต้อง ปรับระดับเสียงของอุปกรณ์บ่อยๆ
xHE-AAC ขจัดข้อจำกัดเหล่านี้ด้วยการใช้อัลกอริทึมการเข้ารหัสเสียงที่ซับซ้อนยิ่งขึ้น เช่น การสลับระหว่างเครื่องมือการเข้ารหัสเสียงพูดโดยเฉพาะ และเครื่องมือการเข้ารหัสเสียงทั่วไปแบบไดนามิก พร้อมทั้งขยายช่วงความถี่ด้วย Spectral Band Replication (eSBR) ที่ได้รับการปรับปรุง และมอบความสามารถในการเข้ารหัสสเตอริโอแบบพารามิเตอร์ โดยมีค่าใช้จ่ายในการเข้ารหัสเพิ่มเติมเพียงเล็กน้อย
MPEG-D DRC ในตัวจะให้การควบคุมระดับเสียงที่จำเป็นสำหรับ xHE-AAC เพื่อเล่นเนื้อหา ที่ระดับเสียงที่สม่ำเสมอ และมีการประมวลผลการควบคุมช่วงไดนามิก เพื่อมอบประสบการณ์การใช้งานที่ดีที่สุดเท่าที่จะเป็นไปได้สำหรับการฟังบนแพลตฟอร์มใดก็ตามและ ในทุกสภาพแวดล้อม
กรณีการใช้งานเป้าหมาย
- Rich Communication Services (RCS) และการรับส่งข้อความเสียง: เป็นไปตาม GSMA RCC.71 Universal Profile เวอร์ชัน 3.1 ขึ้นไป ซึ่งกำหนดให้ใช้ xHE-AAC สำหรับการรับส่งข้อความเสียงที่มีบิตเรตต่ำ
- การสตรีมเสียงสดและพอดแคสต์: ให้คุณภาพเสียงที่เสถียร ผ่านการเชื่อมต่อเครือข่ายมือถือหรือดาวเทียมที่เสื่อมสภาพ
ความพร้อมให้บริการของแพลตฟอร์ม (ระดับ API 37.1 ขึ้นไป)
การรองรับการเข้ารหัส xHE-AAC ของแพลตฟอร์มต้องใช้ API ระดับ 37.1
(Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.CINNAMON_BUN_1 /
SDK 3700001 ขึ้นไป)
สอบถามเกี่ยวกับการรองรับตัวเข้ารหัส xHE-AAC
คุณต้องไม่ถือว่าการเข้ารหัส xHE-AAC พร้อมใช้งานในทุกอุปกรณ์
โดยการเรียกใช้ MediaCodec.createByCodecName(...)
ด้วย "c2.android.xheaac.encoder"
- อุปกรณ์บางเครื่องอาจมีตัวเข้ารหัส xHE-AAC ที่เร่งด้วยฮาร์ดแวร์จากผู้จำหน่ายชิปเซ็ตแทนที่จะเป็นตัวเข้ารหัสซอฟต์แวร์ของแพลตฟอร์ม
- ระบบปฏิบัติการเวอร์ชันเก่าหรือ ROM ที่ปรับแต่งเองไม่รองรับการเข้ารหัส xHE-AAC
- ก่อนเข้ารหัสไฟล์แนบสำหรับการรับส่งข้อความแบบเพียร์ทูเพียร์ (เช่น RCS หรือ
แชท) แอปควรตรวจสอบด้วยว่าไคลเอ็นต์ฝั่งผู้รับประกาศ
การรองรับการถอดรหัส USAC/xHE-AAC หรือไม่ (เช่น ใช้การค้นพบความสามารถของ SDP
profile-level-id=55/object=42) เพื่อป้องกันไม่ให้เกิดความล้มเหลวในการทำงานร่วมกัน ในเครื่องรับรุ่นเดิม
ตรวจสอบความสามารถของ MediaCodecList
หากต้องการตรวจสอบว่าอุปกรณ์ปัจจุบันรองรับการเข้ารหัส xHE-AAC หรือไม่ ให้ตรวจสอบ profileLevels ของตัวเข้ารหัสที่รองรับ
MediaFormat.MIMETYPE_AUDIO_AAC
Kotlin
import android.media.MediaCodecInfo.CodecProfileLevel import android.media.MediaCodecList import android.media.MediaFormat import android.os.Build /** * Checks if the current device supports xHE-AAC audio encoding. */ fun isXheAacEncodingSupported(): Boolean { // Verify API Level >= 37.1 (CINNAMON_BUN_1 / SDK 3700001) if (Build.VERSION.SDK_INT_FULL < Build.VERSION_CODES_FULL.CINNAMON_BUN_1) { return false } val codecList = MediaCodecList(MediaCodecList.REGULAR_CODECS) for (codecInfo in codecList.codecInfos) { if (!codecInfo.isEncoder) continue if (MediaFormat.MIMETYPE_AUDIO_AAC in codecInfo.supportedTypes) { val capabilities = codecInfo.getCapabilitiesForType(MediaFormat.MIMETYPE_AUDIO_AAC) // Check if AACObjectXHE (42) is present in profileLevels val supportsXhe = capabilities.profileLevels.any { profileLevel -> profileLevel.profile == CodecProfileLevel.AACObjectXHE } if (supportsXhe) { return true } } } return false }
Java
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecList; import android.media.MediaFormat; import android.os.Build; /** * Checks if the current device supports xHE-AAC audio encoding. */ public boolean isXheAacEncodingSupported() { // Verify API Level >= 37.1 (CINNAMON_BUN_1 / SDK 3700001) if (Build.VERSION.SDK_INT_FULL < Build.VERSION_CODES_FULL.CINNAMON_BUN_1) { return false; } MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); for (MediaCodecInfo codecInfo : codecList.getCodecInfos()) { if (!codecInfo.isEncoder()) continue; for (String type : codecInfo.getSupportedTypes()) { if (MediaFormat.MIMETYPE_AUDIO_AAC.equals(type)) { MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(MediaFormat.MIMETYPE_AUDIO_AAC); for (CodecProfileLevel profileLevel : capabilities.profileLevels) { if (profileLevel.profile == CodecProfileLevel.AACObjectXHE) { return true; } } } } } return false; }
กำหนดค่าและสร้างอินสแตนซ์ของตัวเข้ารหัส xHE-AAC
หลังจากยืนยันการรองรับ xHE-AAC แล้ว ให้กำหนดค่า MediaFormat โดยตั้งค่า KEY_AAC_PROFILE เป็น MediaCodecInfo.CodecProfileLevel.AACObjectXHE
(ค่า 42)
Kotlin
fun setupXheAacEncoder(): MediaCodec? { if (!isXheAacEncodingSupported()) { return null } val mimeType = MediaFormat.MIMETYPE_AUDIO_AAC val sampleRate = 48000 val channelCount = 1 // Mono voice recording val bitRate = 20000 // 20 kbps delivers superior speech clarity val format = MediaFormat.createAudioFormat(mimeType, sampleRate, channelCount).apply { setInteger(MediaFormat.KEY_BIT_RATE, bitRate) setInteger(MediaFormat.KEY_AAC_PROFILE, CodecProfileLevel.AACObjectXHE) } // Find the hardware or software encoder supporting this format and profile val codecList = MediaCodecList(MediaCodecList.REGULAR_CODECS) val encoderName = codecList.findEncoderForFormat(format) ?: return null val encoder = MediaCodec.createByCodecName(encoderName) encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE) return encoder }
Java
public MediaCodec setupXheAacEncoder() throws IOException { if (!isXheAacEncodingSupported()) { return null; } String mimeType = MediaFormat.MIMETYPE_AUDIO_AAC; int sampleRate = 48000; int channelCount = 1; // Mono voice recording int bitRate = 20000; // 20 kbps delivers superior speech clarity MediaFormat format = MediaFormat.createAudioFormat(mimeType, sampleRate, channelCount); format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate); format.setInteger(MediaFormat.KEY_AAC_PROFILE, CodecProfileLevel.AACObjectXHE); // Find the hardware or software encoder supporting this format and profile MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); String encoderName = codecList.findEncoderForFormat(format); if (encoderName == null) { return null; } MediaCodec encoder = MediaCodec.createByCodecName(encoderName); encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); return encoder; }
ขีดจำกัดของซอฟต์แวร์เปลี่ยนไฟล์ที่รองรับ (c2.android.xheaac.encoder)
เมื่อใช้ตัวเข้ารหัส xHE-AAC ของซอฟต์แวร์ที่ระบบมีให้
(c2.android.xheaac.encoder) คอมโพเนนต์จะโฆษณาขีดจำกัดความสามารถต่อไปนี้
- จำนวนช่อง: สูงสุด
2ช่อง (โมโน / สเตอริโอ) - อัตราการสุ่มตัวอย่าง:
44100 Hz,48000 Hz - ช่วงอัตราบิต:
12,000 bpsถึง400,000 bps(12 kbps – 400 kbps) - การมัลติเพล็กซ์คอนเทนเนอร์: ใช้งานร่วมกับสตรีมพื้นฐาน MP4A ดิบและการมัลติเพล็กซ์คอนเทนเนอร์ MP4/M4A ของแพลตฟอร์ม
(
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)