Starting in Android 17 QPR1 (API level 37.1 or Build.VERSION_CODES_FULL.CINNAMON_BUN_1 ), Android introduces platform support for Extended High Efficiency Advanced Audio Coding (xHE-AAC) encoding.
Определенный в стандартах ISO/IEC 23003-3 (MPEG-D USAC) и ISO/IEC 23003-4 (MPEG-D DRC) , xHE-AAC сочетает в себе унифицированное кодирование речи и звука с обязательной нормализацией громкости и встроенным управлением динамическим диапазоном. Хотя декодирование xHE-AAC поддерживается и предписывается документом Android Compatibility Definition Document (CDD) для нескольких версий платформы, добавление кодировщика xHE-AAC ( c2.android.xheaac.encoder и аппаратные реализации OEM) позволяет записывать голосовые и аудиосообщения с низким битрейтом, потоковое аудио в реальном времени и коммуникационные данные с превосходной четкостью речи и стабильной громкостью на разных устройствах.
Преимущества xHE-AAC
Традиционная запись голоса в мессенджерах Android обычно использует устаревший AAC-LC (AAC Low Complexity) с битрейтом 28 кбит/с. При низких битрейтах (<32 кбит/с) AAC-LC демонстрирует заметные артефакты ограничения полосы пропускания, нечеткое качество речи и неоптимальную эффективность сжатия. Для конечных пользователей это приводит к приглушенному, дребезжащему звуку, где согласные трудно различить, заставляя слушателей переслушивать сообщения или напрягать слух, чтобы понять речь в шумной обстановке. Кроме того, непостоянный уровень громкости в разных аудиозаписях вынуждает пользователей часто регулировать громкость устройства.
xHE-AAC overcomes these limitations by applying more advanced audio coding algorithms, for example dynamically switching between dedicated speech coding and general audio coding tools while extending frequency range with enhanced Spectral Band Replication (eSBR) and providing parametric stereo coding capability with very little additional coding overhead.
Built-in MPEG-D DRC provides mandatory loudness control for xHE-AAC to play back content at a consistent volume and offers dynamic range control processing to provide the best possible user experience for listening on any platform and in any environment.
Целевые сценарии использования
- Расширенные коммуникационные сервисы (RCS) и голосовая связь: соответствует универсальному профилю GSMA RCC.71 версии 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, предоставляемый производителем чипсета.
- В более старых версиях ОС или в модифицированных ПЗУ отсутствует поддержка кодировки xHE-AAC.
- Before encoding an attachment for peer-to-peer messaging (such as RCS or chat), apps should also check if the receiving client advertises USAC/xHE-AAC decoding support (for example, using SDP capability discovery
profile-level-id=55/object=42) to prevent interoperability failures on legacy receivers.
Проверьте возможности MediaCodecList.
Чтобы проверить, поддерживает ли текущее устройство кодирование xHE-AAC, проверьте profileLevels кодировщиков, поддерживающих MediaFormat.MIMETYPE_AUDIO_AAC :
Котлин
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 ).
Котлин
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–400 кбит/с). - Мультиплексирование контейнеров: Совместимо с необработанными элементарными потоками MP4A и мультиплексированием контейнеров MP4/M4A на платформе (
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4).