Element decodeCPE(BitStream inStream)
 {
     if (elements[curElem] == null)
     {
         elements[curElem] = new CPE(config.getFrameLength());
     }
     ((CPE)elements[curElem]).decode(inStream, config);
     curElem++;
     return(elements[curElem - 1]);
 }
        //private int processSingle(SCE_LFE scelfe, FilterBank filterBank, int channel, Profile profile, SampleFrequency sf) throws AACException {
        //ICStream ics = scelfe.getICStream();
        //ICSInfo info = ics.getInfo();
        //LTPrediction ltp = info.getLTPrediction1();
        //int elementID = scelfe.getElementInstanceTag();

        ////inverse quantization
        //float[] iqData = ics.getInvQuantData();

        ////prediction
        //if(profile.equals(Profile.AAC_MAIN)&&info.isICPredictionPresent()) info.getICPrediction().process(ics, iqData, sf);
        //if(LTPrediction.isLTPProfile(profile)&&info.isLTPrediction1Present()) ltp.process(ics, iqData, filterBank, sf);

        ////dependent coupling
        //processDependentCoupling(false, elementID, CCE.BEFORE_TNS, iqData, null);

        ////TNS
        //if(ics.isTNSDataPresent()) ics.getTNS().process(ics, iqData, sf, false);

        ////dependent coupling
        //processDependentCoupling(false, elementID, CCE.AFTER_TNS, iqData, null);

        ////filterbank
        //filterBank.process(info.getWindowSequence(), info.getWindowShape(ICSInfo.CURRENT), info.getWindowShape(ICSInfo.PREVIOUS), iqData, data[channel], channel);

        //if(LTPrediction.isLTPProfile(profile)) ltp.updateState(data[channel], filterBank.getOverlap(channel), profile);

        ////dependent coupling
        //processIndependentCoupling(false, elementID, data[channel], null);

        ////gain control
        //if(ics.isGainControlPresent()) ics.getGainControl().process(iqData, info.getWindowShape(ICSInfo.CURRENT), info.getWindowShape(ICSInfo.PREVIOUS), info.getWindowSequence());

        ////SBR
        //int chs = 1;
        //if(sbrPresent&&config.isSBREnabled()) {
        //if(data[channel].Length==config.getFrameLength()) LOGGER.log(Level.WARNING, "SBR data present, but buffer has normal size!");
        //SBR sbr = scelfe.getSBR();
        //if(sbr.isPSUsed()) {
        //chs = 2;
        //scelfe.getSBR().process(data[channel], data[channel+1], false);
        //}
        //else scelfe.getSBR().process(data[channel], false);
        //}
        //return chs;
        //}

        void processPair(CPE cpe, FilterBank filterBank, int channel, Profile profile, SampleFrequency sf)
        {
            var ics1      = cpe.getLeftChannel();
            var ics2      = cpe.getRightChannel();
            var info1     = ics1.getInfo();
            var info2     = ics2.getInfo();
            var ltp1      = info1.getLTPrediction1();
            var ltp2      = cpe.isCommonWindow() ? info1.getLTPrediction2() : info2.getLTPrediction1();
            int elementID = cpe.getElementInstanceTag();

            // inverse quantization
            var iqData1 = ics1.getInvQuantData();
            var iqData2 = ics2.getInvQuantData();

            // MS
            if (cpe.isCommonWindow() && cpe.isMSMaskPresent())
            {
                MS.process(cpe, iqData1, iqData2);
            }
            // main prediction
            if (profile.type == Profile.ProfileType.AAC_MAIN)
            {
                if (info1.isICPredictionPresent())
                {
                    throw new NotImplementedException();
                    // info1.getICPrediction().process(ics1, iqData1, sf);
                }
                if (info2.isICPredictionPresent())
                {
                    throw new NotImplementedException();
                    // info2.getICPrediction().process(ics2, iqData2, sf);
                }
            }
            // IS
            IS.process(cpe, iqData1, iqData2);

            // LTP
            if (LTPrediction.isLTPProfile(profile))
            {
                if (info1.isLTPrediction1Present())
                {
                    ltp1.process(ics1, iqData1, filterBank, sf);
                }
                if (cpe.isCommonWindow() && info1.isLTPrediction2Present())
                {
                    ltp2.process(ics2, iqData2, filterBank, sf);
                }
                else if (info2.isLTPrediction1Present())
                {
                    ltp2.process(ics2, iqData2, filterBank, sf);
                }
            }

            // dependent coupling
            processDependentCoupling(true, elementID, CCE.BEFORE_TNS, iqData1, iqData2);

            // TNS
            if (ics1.isTNSDataPresent())
            {
                ics1.getTNS().process(ics1, iqData1, sf, false);
            }
            if (ics2.isTNSDataPresent())
            {
                ics2.getTNS().process(ics2, iqData2, sf, false);
            }

            // dependent coupling
            processDependentCoupling(true, elementID, CCE.AFTER_TNS, iqData1, iqData2);

            // filterbank
            filterBank.process(info1.getWindowSequence(), info1.getWindowShape(ICSInfo.CURRENT), info1.getWindowShape(ICSInfo.PREVIOUS), iqData1, data[channel], channel);
            filterBank.process(info2.getWindowSequence(), info2.getWindowShape(ICSInfo.CURRENT), info2.getWindowShape(ICSInfo.PREVIOUS), iqData2, data[channel + 1], channel + 1);

            if (LTPrediction.isLTPProfile(profile))
            {
                ltp1.updateState(data[channel], filterBank.getOverlap(channel), profile);
                ltp2.updateState(data[channel + 1], filterBank.getOverlap(channel + 1), profile);
            }

            // independent coupling
            processIndependentCoupling(true, elementID, data[channel], data[channel + 1]);

            // gain control
            if (ics1.isGainControlPresent())
            {
                ics1.getGainControl().process(iqData1, info1.getWindowShape(ICSInfo.CURRENT), info1.getWindowShape(ICSInfo.PREVIOUS), info1.getWindowSequence());
            }
            if (ics2.isGainControlPresent())
            {
                ics2.getGainControl().process(iqData2, info2.getWindowShape(ICSInfo.CURRENT), info2.getWindowShape(ICSInfo.PREVIOUS), info2.getWindowSequence());
            }

            //SBR
            if (sbrPresent && config.isSBREnabled())
            {
                if (data[channel].Length == config.getFrameLength())
                {
                    Logger.LogServe("SBR data present, but buffer has normal size!");
                }
                cpe.getSBR().process(data[channel], data[channel + 1], false);
            }
        }