xHE-AAC की मदद से, अच्छी क्वालिटी और कम बिटरेट वाला ऑडियो रिकॉर्ड करना

Android 17 QPR1 (एपीआई लेवल 37.1 या Build.VERSION_CODES_FULL.CINNAMON_BUN_1) से, Android ने एक्सटेंडेड हाई एफ़िशिएंसी अडवांस ऑडियो कोडिंग (xHE-AAC) कोडिंग के लिए प्लैटफ़ॉर्म सपोर्ट लॉन्च किया है.

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 encoder (c2.android.xheaac.encoder और ओईएम हार्डवेयर लागू करने की सुविधा) को जोड़ने से, कम बिटरेट वाले वॉइस और ऑडियो मैसेज, लाइव ऑडियो स्ट्रीम, और कम्यूनिकेशन पेलोड रिकॉर्ड किए जा सकते हैं. इनमें आवाज़ साफ़ होती है और सभी डिवाइसों पर वॉल्यूम एक जैसा होता है.

xHE-AAC के फ़ायदे

Android के मैसेजिंग ऐप्लिकेशन में, आवाज़ रिकॉर्ड करने के लिए आम तौर पर 28 केबीपीएस पर AAC-LC (AAC Low Complexity) का पुराना वर्शन इस्तेमाल किया जाता है. कम बिटरेट (<32 केबीपीएस) पर, AAC-LC में बैंड-लिमिटिंग आर्टफ़ैक्ट, आवाज़ की खराब क्वालिटी, और कंप्रेशन की खराब क्षमता दिखती है. इससे, सुनने वालों को ऑडियो ठीक से सुनाई नहीं देता. साथ ही, व्यंजन शब्दों को समझने में मुश्किल होती है. इसलिए, उन्हें मैसेज को फिर से सुनना पड़ता है या शोरगुल वाली जगहों पर बातचीत को समझने के लिए ज़्यादा ध्यान लगाना पड़ता है. इसके अलावा, आवाज़ की अलग-अलग क्लिप में वॉल्यूम का लेवल अलग-अलग होने की वजह से, लोगों को डिवाइस का वॉल्यूम बार-बार अडजस्ट करना पड़ता है.

xHE-AAC, इन सीमाओं को दूर करता है. इसके लिए, यह ज़्यादा बेहतर ऑडियो कोडिंग एल्गोरिदम का इस्तेमाल करता है. उदाहरण के लिए, यह खास तौर पर स्पीच कोडिंग और सामान्य ऑडियो कोडिंग टूल के बीच डाइनैमिक तौर पर स्विच करता है. साथ ही, यह बेहतर स्पेक्ट्रल बैंड रेप्लिकेशन (ईएसबीआर) की मदद से फ़्रीक्वेंसी रेंज को बढ़ाता है. इसके अलावा, यह पैरामीट्रिक स्टीरियो कोडिंग की सुविधा देता है. इसमें कोडिंग का बहुत कम ओवरहेड होता है.

xHE-AAC के लिए, MPEG-D DRC में वॉल्यूम कंट्रोल करने की सुविधा पहले से मौजूद होती है. इससे कॉन्टेंट को एक ही वॉल्यूम पर चलाया जा सकता है. साथ ही, यह डाइनैमिक रेंज कंट्रोल प्रोसेसिंग की सुविधा देता है, ताकि किसी भी प्लैटफ़ॉर्म और किसी भी माहौल में सुनने के लिए, उपयोगकर्ता को सबसे अच्छा अनुभव मिल सके.

इस्तेमाल के टारगेट किए गए उदाहरण

  • रिच कम्यूनिकेशन सेवाएं (आरसीएस) और वॉइस मैसेजिंग: यह GSMA RCC.71 यूनिवर्सल प्रोफ़ाइल वर्शन 3.1 और इसके बाद के वर्शन के मुताबिक है. इसमें कम बिटरेट वाले ऑडियो मैसेज के लिए xHE-AAC का इस्तेमाल करना ज़रूरी है.
  • लाइव ऑडियो स्ट्रीमिंग और पॉडकास्ट: मोबाइल या सैटलाइट नेटवर्क कनेक्शन की क्वालिटी खराब होने पर भी, अच्छी ऑडियो क्वालिटी मिलती है.

प्लैटफ़ॉर्म की उपलब्धता (एपीआई लेवल 37.1+)

xHE-AAC एन्कोडिंग के लिए, प्लैटफ़ॉर्म को एपीआई लेवल 37.1 (Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.CINNAMON_BUN_1 / SDK 3700001 या इसके बाद के वर्शन) की ज़रूरत होती है.

xHE-AAC एनकोडर के साथ काम करने की सुविधा के बारे में क्वेरी करना

आपको यह नहीं मान लेना चाहिए कि "c2.android.xheaac.encoder" के साथ MediaCodec.createByCodecName(...) को कॉल करके, हर डिवाइस पर xHE-AAC एन्कोडिंग उपलब्ध है.

  • कुछ डिवाइसों में, प्लैटफ़ॉर्म सॉफ़्टवेयर एन्कोडर के बजाय, चिपसेट बनाने वाली कंपनी का हार्डवेयर-ऐक्सलरेटेड xHE-AAC एन्कोडर उपलब्ध हो सकता है.
  • ओएस के पुराने वर्शन या कस्टम रोम में, xHE-AAC एन्कोडिंग की सुविधा नहीं होती.
  • पीयर-टू-पीयर मैसेजिंग (जैसे, आरसीएस या चैट) के लिए अटैचमेंट को एन्कोड करने से पहले, ऐप्लिकेशन को यह भी देखना चाहिए कि मैसेज पाने वाला क्लाइंट, 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 केबीपीएस – 400 केबीपीएस).
  • कंटेनर मल्टीप्लेक्सिंग: यह रॉ MP4A एलिमेंट्री स्ट्रीम और प्लैटफ़ॉर्म MP4/M4A कंटेनर मल्टीप्लेक्सिंग (MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) के साथ काम करता है.