FileDocCategorySizeDatePackage
AudioSpecificConfig.javaAPI Docmp4parser 1.0-RC-1740856Wed Dec 19 20:10:37 GMT 2012com.googlecode.mp4parser.boxes.mp4.objectdescriptors

AudioSpecificConfig

public class AudioSpecificConfig extends BaseDescriptor

Fields Summary
byte[]
configBytes
public static Map
samplingFrequencyIndexMap
public static Map
audioObjectTypeMap
int
audioObjectType
int
samplingFrequencyIndex
int
samplingFrequency
int
channelConfiguration
int
extensionAudioObjectType
int
sbrPresentFlag
int
psPresentFlag
int
extensionSamplingFrequencyIndex
int
extensionSamplingFrequency
int
extensionChannelConfiguration
int
sacPayloadEmbedding
int
fillBits
int
epConfig
int
directMapping
int
syncExtensionType
int
frameLengthFlag
int
dependsOnCoreCoder
int
coreCoderDelay
int
extensionFlag
int
layerNr
int
numOfSubFrame
int
layer_length
int
aacSectionDataResilienceFlag
int
aacScalefactorDataResilienceFlag
int
aacSpectralDataResilienceFlag
int
extensionFlag3
boolean
gaSpecificConfig
int
isBaseLayer
int
paraMode
int
paraExtensionFlag
int
hvxcVarMode
int
hvxcRateMode
int
erHvxcExtensionFlag
int
var_ScalableFlag
int
hilnQuantMode
int
hilnMaxNumLine
int
hilnSampleRateCode
int
hilnFrameLength
int
hilnContMode
int
hilnEnhaLayer
int
hilnEnhaQuantMode
boolean
parametricSpecificConfig
Constructors Summary
Methods Summary
public booleanequals(java.lang.Object o)

        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        AudioSpecificConfig that = (AudioSpecificConfig) o;

        if (aacScalefactorDataResilienceFlag != that.aacScalefactorDataResilienceFlag) {
            return false;
        }
        if (aacSectionDataResilienceFlag != that.aacSectionDataResilienceFlag) {
            return false;
        }
        if (aacSpectralDataResilienceFlag != that.aacSpectralDataResilienceFlag) {
            return false;
        }
        if (audioObjectType != that.audioObjectType) {
            return false;
        }
        if (channelConfiguration != that.channelConfiguration) {
            return false;
        }
        if (coreCoderDelay != that.coreCoderDelay) {
            return false;
        }
        if (dependsOnCoreCoder != that.dependsOnCoreCoder) {
            return false;
        }
        if (directMapping != that.directMapping) {
            return false;
        }
        if (epConfig != that.epConfig) {
            return false;
        }
        if (erHvxcExtensionFlag != that.erHvxcExtensionFlag) {
            return false;
        }
        if (extensionAudioObjectType != that.extensionAudioObjectType) {
            return false;
        }
        if (extensionChannelConfiguration != that.extensionChannelConfiguration) {
            return false;
        }
        if (extensionFlag != that.extensionFlag) {
            return false;
        }
        if (extensionFlag3 != that.extensionFlag3) {
            return false;
        }
        if (extensionSamplingFrequency != that.extensionSamplingFrequency) {
            return false;
        }
        if (extensionSamplingFrequencyIndex != that.extensionSamplingFrequencyIndex) {
            return false;
        }
        if (fillBits != that.fillBits) {
            return false;
        }
        if (frameLengthFlag != that.frameLengthFlag) {
            return false;
        }
        if (gaSpecificConfig != that.gaSpecificConfig) {
            return false;
        }
        if (hilnContMode != that.hilnContMode) {
            return false;
        }
        if (hilnEnhaLayer != that.hilnEnhaLayer) {
            return false;
        }
        if (hilnEnhaQuantMode != that.hilnEnhaQuantMode) {
            return false;
        }
        if (hilnFrameLength != that.hilnFrameLength) {
            return false;
        }
        if (hilnMaxNumLine != that.hilnMaxNumLine) {
            return false;
        }
        if (hilnQuantMode != that.hilnQuantMode) {
            return false;
        }
        if (hilnSampleRateCode != that.hilnSampleRateCode) {
            return false;
        }
        if (hvxcRateMode != that.hvxcRateMode) {
            return false;
        }
        if (hvxcVarMode != that.hvxcVarMode) {
            return false;
        }
        if (isBaseLayer != that.isBaseLayer) {
            return false;
        }
        if (layerNr != that.layerNr) {
            return false;
        }
        if (layer_length != that.layer_length) {
            return false;
        }
        if (numOfSubFrame != that.numOfSubFrame) {
            return false;
        }
        if (paraExtensionFlag != that.paraExtensionFlag) {
            return false;
        }
        if (paraMode != that.paraMode) {
            return false;
        }
        if (parametricSpecificConfig != that.parametricSpecificConfig) {
            return false;
        }
        if (psPresentFlag != that.psPresentFlag) {
            return false;
        }
        if (sacPayloadEmbedding != that.sacPayloadEmbedding) {
            return false;
        }
        if (samplingFrequency != that.samplingFrequency) {
            return false;
        }
        if (samplingFrequencyIndex != that.samplingFrequencyIndex) {
            return false;
        }
        if (sbrPresentFlag != that.sbrPresentFlag) {
            return false;
        }
        if (syncExtensionType != that.syncExtensionType) {
            return false;
        }
        if (var_ScalableFlag != that.var_ScalableFlag) {
            return false;
        }
        if (!Arrays.equals(configBytes, that.configBytes)) {
            return false;
        }

        return true;
    
private intgaSpecificConfigSize()

        return 0;
    
public intgetAudioObjectType()

        return audioObjectType;
    
private intgetAudioObjectType(BitReaderBuffer in)

        int audioObjectType = in.readBits(5);
        if (audioObjectType == 31) {
            audioObjectType = 32 + in.readBits(6);
        }
        return audioObjectType;
    
public intgetChannelConfiguration()

        return channelConfiguration;
    
public byte[]getConfigBytes()

        return configBytes;
    
public intgetExtensionAudioObjectType()

        return extensionAudioObjectType;
    
public intgetPsPresentFlag()

        return psPresentFlag;
    
public intgetSamplingFrequency()

        // sampling_frequency_index sampling frequeny
//0x0 96000
//0x1 88200
//0x2 64000
//0x3 48000
//0x4 44100
//0x5 32000
//0x6 24000
//0x7 22050
//0x8 16000
//0x9 12000
//0xa 11025
//0xb 8000
//0xc reserved
//0xd reserved
//0xe reserved
//0xf reserved
        samplingFrequencyIndexMap.put(0x0, 96000);
        samplingFrequencyIndexMap.put(0x1, 88200);
        samplingFrequencyIndexMap.put(0x2, 64000);
        samplingFrequencyIndexMap.put(0x3, 48000);
        samplingFrequencyIndexMap.put(0x4, 44100);
        samplingFrequencyIndexMap.put(0x5, 32000);
        samplingFrequencyIndexMap.put(0x6, 24000);
        samplingFrequencyIndexMap.put(0x7, 22050);
        samplingFrequencyIndexMap.put(0x8, 16000);
        samplingFrequencyIndexMap.put(0x9, 12000);
        samplingFrequencyIndexMap.put(0xa, 11025);
        samplingFrequencyIndexMap.put(0xb, 8000);

        /* audioObjectType IDs
          0 Null
        1 AAC main X X
        2 AAC LC X X X X X X X
        3 AAC SSR X X
        4 AAC LTP X X X X
        5 SBR X X
        6 AAC Scalable X X X X
        7 TwinVQ X X X
        8 CELP X X X X X X
        9 HVXC X X X X X
        10 (reserved)
        11 (reserved)
        12 TTSI X X X X X X
        13 Main synthetic X X
        14 Wavetable synthesis X* X*
        15 General MIDI X* X*
        16 Algorithmic Synthesis and Audio FX X* X*
        17 ER AAC LC X X X
        18 (reserved)
        19 ER AAC LTP X X
        20 ER AAC Scalable X X X
        21 ER TwinVQ X X
        22 ER BSAC X X
        23 ER AAC LD X X X X
        24 ER CELP X X X
        25 ER HVXC X X
        26 ER HILN X
        27 ER Parametric X
        28 SSC
        29 PS X
        30 MPEG Surround
        31 (escape)
        32 Layer-1
        33 Layer-2
        34 Layer-3
        35 DST
        36 ALS
        37 SLS
        38 SLS non-core
        39 ER AAC ELD
        40 SMR Simple
        41 SMR Main
        */
        audioObjectTypeMap.put(1, "AAC main");
        audioObjectTypeMap.put(2, "AAC LC");
        audioObjectTypeMap.put(3, "AAC SSR");
        audioObjectTypeMap.put(4, "AAC LTP");
        audioObjectTypeMap.put(5, "SBR");
        audioObjectTypeMap.put(6, "AAC Scalable");
        audioObjectTypeMap.put(7, "TwinVQ");
        audioObjectTypeMap.put(8, "CELP");
        audioObjectTypeMap.put(9, "HVXC");
        audioObjectTypeMap.put(10, "(reserved)");
        audioObjectTypeMap.put(11, "(reserved)");
        audioObjectTypeMap.put(12, "TTSI");
        audioObjectTypeMap.put(13, "Main synthetic");
        audioObjectTypeMap.put(14, "Wavetable synthesis");
        audioObjectTypeMap.put(15, "General MIDI");
        audioObjectTypeMap.put(16, "Algorithmic Synthesis and Audio FX");
        audioObjectTypeMap.put(17, "ER AAC LC");
        audioObjectTypeMap.put(18, "(reserved)");
        audioObjectTypeMap.put(19, "ER AAC LTP");
        audioObjectTypeMap.put(20, "ER AAC Scalable");
        audioObjectTypeMap.put(21, "ER TwinVQ");
        audioObjectTypeMap.put(22, "ER BSAC");
        audioObjectTypeMap.put(23, "ER AAC LD");
        audioObjectTypeMap.put(24, "ER CELP");
        audioObjectTypeMap.put(25, "ER HVXC");
        audioObjectTypeMap.put(26, "ER HILN");
        audioObjectTypeMap.put(27, "ER Parametric");
        audioObjectTypeMap.put(28, "SSC");
        audioObjectTypeMap.put(29, "PS");
        audioObjectTypeMap.put(30, "MPEG Surround");
        audioObjectTypeMap.put(31, "(escape)");
        audioObjectTypeMap.put(32, "Layer-1");
        audioObjectTypeMap.put(33, "Layer-2");
        audioObjectTypeMap.put(34, "Layer-3");
        audioObjectTypeMap.put(35, "DST");
        audioObjectTypeMap.put(36, "ALS");
        audioObjectTypeMap.put(37, "SLS");
        audioObjectTypeMap.put(38, "SLS non-core");
        audioObjectTypeMap.put(39, "ER AAC ELD");
        audioObjectTypeMap.put(40, "SMR Simple");
        audioObjectTypeMap.put(41, "SMR Main");

        /* profileLevelIds
       0x00 Reserved for ISO use -
     0x01 Main Audio Profile L1
     0x02 Main Audio Profile L2
     0x03 Main Audio Profile L3
     0x04 Main Audio Profile L4
     0x05 Scalable Audio Profile L1
     0x06 Scalable Audio Profile L2
     0x07 Scalable Audio Profile L3
     0x08 Scalable Audio Profile L4
     0x09 Speech Audio Profile L1
     0x0A Speech Audio Profile L2
     0x0B Synthetic Audio Profile L1
     0x0C Synthetic Audio Profile L2
     0x0D Synthetic Audio Profile L3
     0x0E High Quality Audio Profile L1
     0x0F High Quality Audio Profile L2
     0x10 High Quality Audio Profile L3
     0x11 High Quality Audio Profile L4
     0x12 High Quality Audio Profile L5
     0x13 High Quality Audio Profile L6
     0x14 High Quality Audio Profile L7
     0x15 High Quality Audio Profile L8
     0x16 Low Delay Audio Profile L1
     0x17 Low Delay Audio Profile L2
     0x18 Low Delay Audio Profile L3
     0x19 Low Delay Audio Profile L4
     0x1A Low Delay Audio Profile L5
     0x1B Low Delay Audio Profile L6
     0x1C Low Delay Audio Profile L7
     0x1D Low Delay Audio Profile L8
     0x1E Natural Audio Profile L1
     0x1F Natural Audio Profile L2
     0x20 Natural Audio Profile L3
     0x21 Natural Audio Profile L4
     0x22 Mobile Audio Internetworking Profile L1
     0x23 Mobile Audio Internetworking Profile L2
     0x24 Mobile Audio Internetworking Profile L3
     0x25 Mobile Audio Internetworking Profile L4
     0x26 Mobile Audio Internetworking Profile L5
     0x27 Mobile Audio Internetworking Profile L6
     0x28 AAC Profile L1
     0x29 AAC Profile L2
     0x2A AAC Profile L4
     0x2B AAC Profile L5
     0x2C High Efficiency AAC Profile L2
     0x2D High Efficiency AAC Profile L3
     0x2E High Efficiency AAC Profile L4
     0x2F High Efficiency AAC Profile L5
     0x30 High Efficiency AAC v2 Profile L2
     0x31 High Efficiency AAC v2 Profile L3
     0x32 High Efficiency AAC v2 Profile L4
     0x33 High Efficiency AAC v2 Profile L5
     0x34 Low Delay AAC Profile L1
     0x35 Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L1
     0x36 Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L2
     0x37 Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L3
     0x38 Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L4
     0c39 Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L5
     0x3A Baseline MPEG Surround Profile (see ISO/IEC
     23003-1)
     L6
     0x3B - 0x7F reserved for ISO use -
     0x80 - 0xFD user private -
     0xFE no audio profile specified -
     0xFF no audio capability required -

        */
    
        return samplingFrequencyIndex == 0xf ? samplingFrequency : samplingFrequencyIndexMap.get(samplingFrequencyIndex);
    
public intgetSbrPresentFlag()

        return sbrPresentFlag;
    
public inthashCode()

        int result = configBytes != null ? Arrays.hashCode(configBytes) : 0;
        result = 31 * result + audioObjectType;
        result = 31 * result + samplingFrequencyIndex;
        result = 31 * result + samplingFrequency;
        result = 31 * result + channelConfiguration;
        result = 31 * result + extensionAudioObjectType;
        result = 31 * result + sbrPresentFlag;
        result = 31 * result + psPresentFlag;
        result = 31 * result + extensionSamplingFrequencyIndex;
        result = 31 * result + extensionSamplingFrequency;
        result = 31 * result + extensionChannelConfiguration;
        result = 31 * result + sacPayloadEmbedding;
        result = 31 * result + fillBits;
        result = 31 * result + epConfig;
        result = 31 * result + directMapping;
        result = 31 * result + syncExtensionType;
        result = 31 * result + frameLengthFlag;
        result = 31 * result + dependsOnCoreCoder;
        result = 31 * result + coreCoderDelay;
        result = 31 * result + extensionFlag;
        result = 31 * result + layerNr;
        result = 31 * result + numOfSubFrame;
        result = 31 * result + layer_length;
        result = 31 * result + aacSectionDataResilienceFlag;
        result = 31 * result + aacScalefactorDataResilienceFlag;
        result = 31 * result + aacSpectralDataResilienceFlag;
        result = 31 * result + extensionFlag3;
        result = 31 * result + (gaSpecificConfig ? 1 : 0);
        result = 31 * result + isBaseLayer;
        result = 31 * result + paraMode;
        result = 31 * result + paraExtensionFlag;
        result = 31 * result + hvxcVarMode;
        result = 31 * result + hvxcRateMode;
        result = 31 * result + erHvxcExtensionFlag;
        result = 31 * result + var_ScalableFlag;
        result = 31 * result + hilnQuantMode;
        result = 31 * result + hilnMaxNumLine;
        result = 31 * result + hilnSampleRateCode;
        result = 31 * result + hilnFrameLength;
        result = 31 * result + hilnContMode;
        result = 31 * result + hilnEnhaLayer;
        result = 31 * result + hilnEnhaQuantMode;
        result = 31 * result + (parametricSpecificConfig ? 1 : 0);
        return result;
    
public voidparseDetail(java.nio.ByteBuffer bb)


    
          
        ByteBuffer configBytes = bb.slice();
        configBytes.limit(sizeOfInstance);
        bb.position(bb.position() + sizeOfInstance);

        //copy original bytes to internal array for constructing codec config strings (todo until writing of the config is supported)
        this.configBytes = new byte[sizeOfInstance];
        configBytes.get(this.configBytes);
        configBytes.rewind();

        BitReaderBuffer bitReaderBuffer = new BitReaderBuffer(configBytes);
        audioObjectType = getAudioObjectType(bitReaderBuffer);
        samplingFrequencyIndex = bitReaderBuffer.readBits(4);

        if (samplingFrequencyIndex == 0xf) {
            samplingFrequency = bitReaderBuffer.readBits(24);
        }

        channelConfiguration = bitReaderBuffer.readBits(4);

        if (audioObjectType == 5 ||
                audioObjectType == 29) {
            extensionAudioObjectType = 5;
            sbrPresentFlag = 1;
            if (audioObjectType == 29) {
                psPresentFlag = 1;
            }
            extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
            if (extensionSamplingFrequencyIndex == 0xf)
                extensionSamplingFrequency = bitReaderBuffer.readBits(24);
            audioObjectType = getAudioObjectType(bitReaderBuffer);
            if (audioObjectType == 22)
                extensionChannelConfiguration = bitReaderBuffer.readBits(4);
        } else {
            extensionAudioObjectType = 0;
        }

        switch (audioObjectType) {
            case 1:
            case 2:
            case 3:
            case 4:
            case 6:
            case 7:
            case 17:
            case 19:
            case 20:
            case 21:
            case 22:
            case 23:
                parseGaSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
                //GASpecificConfig();
                break;
            case 8:
                throw new UnsupportedOperationException("can't parse CelpSpecificConfig yet");
                //CelpSpecificConfig();
                //break;
            case 9:
                throw new UnsupportedOperationException("can't parse HvxcSpecificConfig yet");
                //HvxcSpecificConfig();
                //break;
            case 12:
                throw new UnsupportedOperationException("can't parse TTSSpecificConfig yet");
                //TTSSpecificConfig();
                //break;
            case 13:
            case 14:
            case 15:
            case 16:
                throw new UnsupportedOperationException("can't parse StructuredAudioSpecificConfig yet");
                //StructuredAudioSpecificConfig();
                //break;
            case 24:
                throw new UnsupportedOperationException("can't parse ErrorResilientCelpSpecificConfig yet");
                //ErrorResilientCelpSpecificConfig();
                //break;
            case 25:
                throw new UnsupportedOperationException("can't parse ErrorResilientHvxcSpecificConfig yet");
                //ErrorResilientHvxcSpecificConfig();
                //break;
            case 26:
            case 27:
                parseParametricSpecificConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, bitReaderBuffer);
                //ParametricSpecificConfig();
                break;
            case 28:
                throw new UnsupportedOperationException("can't parse SSCSpecificConfig yet");
                //SSCSpecificConfig();
                //break;
            case 30:
                sacPayloadEmbedding = bitReaderBuffer.readBits(1);
                throw new UnsupportedOperationException("can't parse SpatialSpecificConfig yet");
                //SpatialSpecificConfig();
                //break;
            case 32:
            case 33:
            case 34:
                throw new UnsupportedOperationException("can't parse MPEG_1_2_SpecificConfig yet");
                //MPEG_1_2_SpecificConfig();
                //break;
            case 35:
                throw new UnsupportedOperationException("can't parse DSTSpecificConfig yet");
                //DSTSpecificConfig();
                //break;
            case 36:
                fillBits = bitReaderBuffer.readBits(5);
                throw new UnsupportedOperationException("can't parse ALSSpecificConfig yet");
                //ALSSpecificConfig();
                //break;
            case 37:
            case 38:
                throw new UnsupportedOperationException("can't parse SLSSpecificConfig yet");
                //SLSSpecificConfig();
                //break;
            case 39:
                throw new UnsupportedOperationException("can't parse ELDSpecificConfig yet");
                //ELDSpecificConfig(channelConfiguration);
                //break;
            case 40:
            case 41:
                throw new UnsupportedOperationException("can't parse SymbolicMusicSpecificConfig yet");
                //SymbolicMusicSpecificConfig();
                //break;
            default:
                /* reserved */
        }

        switch (audioObjectType) {
            case 17:
            case 19:
            case 20:
            case 21:
            case 22:
            case 23:
            case 24:
            case 25:
            case 26:
            case 27:
            case 39:
                epConfig = bitReaderBuffer.readBits(2);
                if (epConfig == 2 || epConfig == 3) {
                    throw new UnsupportedOperationException("can't parse ErrorProtectionSpecificConfig yet");
                    //ErrorProtectionSpecificConfig();
                }
                if (epConfig == 3) {
                    directMapping = bitReaderBuffer.readBits(1);
                    if (directMapping == 0) {
                        /* tbd */
                        throw new RuntimeException("not implemented");
                    }
                }
        }

        if (extensionAudioObjectType != 5 && bitReaderBuffer.remainingBits() >= 16) {
            syncExtensionType = bitReaderBuffer.readBits(11);
            if (syncExtensionType == 0x2b7) {
                extensionAudioObjectType = getAudioObjectType(bitReaderBuffer);
                if (extensionAudioObjectType == 5) {
                    sbrPresentFlag = bitReaderBuffer.readBits(1);
                    if (sbrPresentFlag == 1) {
                        extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
                        if (extensionSamplingFrequencyIndex == 0xf) {
                            extensionSamplingFrequency = bitReaderBuffer.readBits(24);
                        }
                        if (bitReaderBuffer.remainingBits() >= 12) {
                            syncExtensionType = bitReaderBuffer.readBits(11); //10101001000
                            if (syncExtensionType == 0x548) {
                                psPresentFlag = bitReaderBuffer.readBits(1);
                            }
                        }
                    }
                }
                if (extensionAudioObjectType == 22) {
                    sbrPresentFlag = bitReaderBuffer.readBits(1);
                    if (sbrPresentFlag == 1) {
                        extensionSamplingFrequencyIndex = bitReaderBuffer.readBits(4);
                        if (extensionSamplingFrequencyIndex == 0xf) {
                            extensionSamplingFrequency = bitReaderBuffer.readBits(24);
                        }
                    }
                    extensionChannelConfiguration = bitReaderBuffer.readBits(4);
                }
            }
        }
    
private voidparseErHvxcConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

        /*
        ErHVXCconfig()
        {
            HVXCvarMode; 1 uimsbf
                HVXCrateMode; 2 uimsbf
                extensionFlag; 1 uimsbf
            if (extensionFlag) {
                var_ScalableFlag; 1 uimsbf
            }
        }
        */
        hvxcVarMode = in.readBits(1);
        hvxcRateMode = in.readBits(2);
        erHvxcExtensionFlag = in.readBits(1);

        if (erHvxcExtensionFlag == 1) {
            var_ScalableFlag = in.readBits(1);
        }
    
private voidparseGaSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

//    GASpecificConfig (samplingFrequencyIndex,
//            channelConfiguration,
//            audioObjectType)
//    {
        frameLengthFlag = in.readBits(1);
        dependsOnCoreCoder = in.readBits(1);
        if (dependsOnCoreCoder == 1) {
            coreCoderDelay = in.readBits(14);
        }
        extensionFlag = in.readBits(1);
        if (channelConfiguration == 0) {
            throw new UnsupportedOperationException("can't parse program_config_element yet");
            //program_config_element ();
        }
        if ((audioObjectType == 6) || (audioObjectType == 20)) {
            layerNr = in.readBits(3);
        }
        if (extensionFlag == 1) {
            if (audioObjectType == 22) {
                numOfSubFrame = in.readBits(5);
                layer_length = in.readBits(11);
            }
            if (audioObjectType == 17 || audioObjectType == 19 ||
                    audioObjectType == 20 || audioObjectType == 23) {
                aacSectionDataResilienceFlag = in.readBits(1);
                aacScalefactorDataResilienceFlag = in.readBits(1);
                aacSpectralDataResilienceFlag = in.readBits(1);
            }
            extensionFlag3 = in.readBits(1);
            if (extensionFlag3 == 1) {
                /* tbd in version 3 */
            }
        }
//    }
        gaSpecificConfig = true;
    
private voidparseHilnConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

        /*
        HILNconfig()
        {
            HILNquantMode; 1 uimsbf
            HILNmaxNumLine; 8 uimsbf
            HILNsampleRateCode; 4 uimsbf
            HILNframeLength; 12 uimsbf
            HILNcontMode; 2 uimsbf
        }
        */
        hilnQuantMode = in.readBits(1);
        hilnMaxNumLine = in.readBits(8);
        hilnSampleRateCode = in.readBits(4);
        hilnFrameLength = in.readBits(12);
        hilnContMode = in.readBits(2);
    
private voidparseHilnEnexConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

        /*
        HILNenexConfig()
        {
            HILNenhaLayer; 1 uimsbf
            if (HILNenhaLayer) {
                HILNenhaQuantMode; 2 uimsbf
            }
        }
        */
        hilnEnhaLayer = in.readBits(1);
        if (hilnEnhaLayer == 1) {
            hilnEnhaQuantMode = in.readBits(2);
        }
    
private voidparseParaConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

        /*
        PARAconfig()
        {
            PARAmode; 2 uimsbf
            if (PARAmode != 1) {
                ErHVXCconfig();
            }
            if (PARAmode != 0) {
                HILNconfig();
            }
            PARAextensionFlag; 1 uimsbf
            if (PARAextensionFlag) {
                // to be defined in MPEG-4 Phase 3
            }
        }
        */
        paraMode = in.readBits(2);

        if (paraMode != 1) {
            parseErHvxcConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
        }
        if (paraMode != 0) {
            parseHilnConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
        }

        paraExtensionFlag = in.readBits(1);
        parametricSpecificConfig = true;
    
private voidparseParametricSpecificConfig(int samplingFrequencyIndex, int channelConfiguration, int audioObjectType, BitReaderBuffer in)

        /*
        ParametricSpecificConfig() {
            isBaseLayer; 1 uimsbf
            if (isBaseLayer) {
                PARAconfig();
            } else {
                HILNenexConfig();
            }
        }
        */
        isBaseLayer = in.readBits(1);
        if (isBaseLayer == 1) {
            parseParaConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
        } else {
            parseHilnEnexConfig(samplingFrequencyIndex, channelConfiguration, audioObjectType, in);
        }
    
public java.nio.ByteBufferserialize()

        ByteBuffer out = ByteBuffer.allocate(serializedSize());
        IsoTypeWriter.writeUInt8(out, 5);
        IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
        BitWriterBuffer bwb = new BitWriterBuffer(out);
        bwb.writeBits(audioObjectType, 5);
        bwb.writeBits(samplingFrequencyIndex, 4);
        if (samplingFrequencyIndex == 0xf) {
            throw new UnsupportedOperationException("can't serialize that yet");
        }
        bwb.writeBits(channelConfiguration, 4);

        // Don't support any extensions, unusual GASpecificConfig other than the default or anything...

        return out;
    
public intserializedSize()

        int out = 4;
        if (audioObjectType == 2) {
            out += gaSpecificConfigSize();
        } else {
            throw new UnsupportedOperationException("can't serialize that yet");
        }
        return out;
    
public voidsetAudioObjectType(int audioObjectType)

        this.audioObjectType = audioObjectType;
    
public voidsetChannelConfiguration(int channelConfiguration)

        this.channelConfiguration = channelConfiguration;
    
public voidsetSamplingFrequency(int samplingFrequency)

        this.samplingFrequency = samplingFrequency;
    
public voidsetSamplingFrequencyIndex(int samplingFrequencyIndex)

        this.samplingFrequencyIndex = samplingFrequencyIndex;
    
public java.lang.StringtoString()

        final StringBuilder sb = new StringBuilder();
        sb.append("AudioSpecificConfig");
        sb.append("{configBytes=").append(Hex.encodeHex(configBytes));
        sb.append(", audioObjectType=").append(audioObjectType).append(" (").append(audioObjectTypeMap.get(audioObjectType)).append(")");
        sb.append(", samplingFrequencyIndex=").append(samplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(samplingFrequencyIndex)).append(")");
        sb.append(", samplingFrequency=").append(samplingFrequency);
        sb.append(", channelConfiguration=").append(channelConfiguration);
        if (extensionAudioObjectType > 0) {
            sb.append(", extensionAudioObjectType=").append(extensionAudioObjectType).append(" (").append(audioObjectTypeMap.get(extensionAudioObjectType)).append(")");
            sb.append(", sbrPresentFlag=").append(sbrPresentFlag);
            sb.append(", psPresentFlag=").append(psPresentFlag);
            sb.append(", extensionSamplingFrequencyIndex=").append(extensionSamplingFrequencyIndex).append(" (").append(samplingFrequencyIndexMap.get(extensionSamplingFrequencyIndex)).append(")");
            sb.append(", extensionSamplingFrequency=").append(extensionSamplingFrequency);
            sb.append(", extensionChannelConfiguration=").append(extensionChannelConfiguration);
        }
//    sb.append(", sacPayloadEmbedding=").append(sacPayloadEmbedding);
//    sb.append(", fillBits=").append(fillBits);
//    sb.append(", epConfig=").append(epConfig);
//    sb.append(", directMapping=").append(directMapping);
        sb.append(", syncExtensionType=").append(syncExtensionType);
        if (gaSpecificConfig) {
            sb.append(", frameLengthFlag=").append(frameLengthFlag);
            sb.append(", dependsOnCoreCoder=").append(dependsOnCoreCoder);
            sb.append(", coreCoderDelay=").append(coreCoderDelay);
            sb.append(", extensionFlag=").append(extensionFlag);
            sb.append(", layerNr=").append(layerNr);
            sb.append(", numOfSubFrame=").append(numOfSubFrame);
            sb.append(", layer_length=").append(layer_length);
            sb.append(", aacSectionDataResilienceFlag=").append(aacSectionDataResilienceFlag);
            sb.append(", aacScalefactorDataResilienceFlag=").append(aacScalefactorDataResilienceFlag);
            sb.append(", aacSpectralDataResilienceFlag=").append(aacSpectralDataResilienceFlag);
            sb.append(", extensionFlag3=").append(extensionFlag3);
        }
        if (parametricSpecificConfig) {
            sb.append(", isBaseLayer=").append(isBaseLayer);
            sb.append(", paraMode=").append(paraMode);
            sb.append(", paraExtensionFlag=").append(paraExtensionFlag);
            sb.append(", hvxcVarMode=").append(hvxcVarMode);
            sb.append(", hvxcRateMode=").append(hvxcRateMode);
            sb.append(", erHvxcExtensionFlag=").append(erHvxcExtensionFlag);
            sb.append(", var_ScalableFlag=").append(var_ScalableFlag);
            sb.append(", hilnQuantMode=").append(hilnQuantMode);
            sb.append(", hilnMaxNumLine=").append(hilnMaxNumLine);
            sb.append(", hilnSampleRateCode=").append(hilnSampleRateCode);
            sb.append(", hilnFrameLength=").append(hilnFrameLength);
            sb.append(", hilnContMode=").append(hilnContMode);
            sb.append(", hilnEnhaLayer=").append(hilnEnhaLayer);
            sb.append(", hilnEnhaQuantMode=").append(hilnEnhaQuantMode);
        }
        sb.append('}");
        return sb.toString();