/// <summary> /// Initializes the decoder with a MP4 decoder specific info. /// /// After this the MP4 frames can be passed to the /// <code>decodeFrame(byte[], SampleBuffer)</code> method to decode them. /// </summary> /// <param name="decoderSpecificInfo">decoderSpecificInfo a byte array containing the decoder specific info from an MP4 container</param> public Decoder(byte[] decoderSpecificInfo) { config = DecoderConfig.parseMP4DecoderSpecificInfo(decoderSpecificInfo); if (config == null) { throw new ArgumentException("illegal MP4 decoder specific info"); } if (!canDecode(config.getProfile())) { throw new AACException("unsupported profile: " + config.getProfile()); } syntacticElements = new SyntacticElements(config); filterBank = new FilterBank(config.isSmallFrameUsed(), (int)config.getChannelConfiguration()); Logger.LogInfo(string.Format("profile: {0}", config.getProfile())); Logger.LogInfo(string.Format("sf: {0}", config.getSampleFrequency().getFrequency())); Logger.LogInfo(string.Format("channels: {0}", config.getChannelConfiguration())); }
//private void decodeCCE(BitStream in) throws AACException { //if(curCCE==MAX_ELEMENTS) throw new AACException("too much CCE elements"); //if(cces[curCCE]==null) cces[curCCE] = new CCE(config.getFrameLength()); //cces[curCCE].decode(in, config); //curCCE++; //} //private void decodeDSE(BitStream in) throws AACException { //if(curDSE==MAX_ELEMENTS) throw new AACException("too much CCE elements"); //if(dses[curDSE]==null) dses[curDSE] = new DSE(); //dses[curDSE].decode(in); //curDSE++; //} //private void decodePCE(BitStream in) throws AACException { //pce.decode(in); //config.setProfile(pce.getProfile()); //config.setSampleFrequency(pce.getSampleFrequency()); //config.setChannelConfiguration(ChannelConfiguration.forInt(pce.getChannelCount())); //} //private void decodeFIL(BitStream in, Element prev) throws AACException { //if(curFIL==MAX_ELEMENTS) throw new AACException("too much FIL elements"); //if(fils[curFIL]==null) fils[curFIL] = new FIL(config.isSBRDownSampled()); //fils[curFIL].decode(in, prev, config.getSampleFrequency(), config.isSBREnabled(), config.isSmallFrameUsed()); //curFIL++; //if(prev!=null&&prev.isSBRPresent()) { //sbrPresent = true; //if(!psPresent&&prev.getSBR().isPSUsed()) psPresent = true; //} //} public void process(FilterBank filterBank) { Profile profile = config.getProfile(); SampleFrequency sf = config.getSampleFrequency(); //ChannelConfiguration channels = config.getChannelConfiguration(); int chs = (int)config.getChannelConfiguration(); if (chs == 1 && psPresent) { chs++; } int mult = sbrPresent ? 2 : 1; //only reallocate if needed if (data == null || chs != data.Length || (mult * config.getFrameLength()) != data[0].Length) { data = Enumerable.Range(0, chs).Select(x => new float[mult * config.getFrameLength()]).ToArray(); } int channel = 0; Element e; SCE_LFE scelfe; CPE cpe; for (int i = 0; i < elements.Length && channel < chs; i++) { e = elements[i]; if (e == null) { continue; } if (e is SCE_LFE) { scelfe = (SCE_LFE)e; throw new NotImplementedException(); // channel += processSingle(scelfe, filterBank, channel, profile, sf); } else if (e is CPE) { cpe = (CPE)e; processPair(cpe, filterBank, channel, profile, sf); channel += 2; } else if (e is CCE) { //applies invquant and save the result in the CCE throw new NotImplementedException(); // ((CCE)e).process(); channel++; } } }
// /* ========= decoding ========== */ public void decode(BitStream inStream, bool commonWindow, DecoderConfig conf) { if (conf.isScalefactorResilienceUsed() && rvlc == null) { rvlc = new RVLC(); } bool er = conf.getProfile().isErrorResilientProfile(); globalGain = inStream.readBits(8); if (!commonWindow) { info.decode(inStream, conf, commonWindow); } decodeSectionData(inStream, conf.isSectionDataResilienceUsed()); //if(conf.isScalefactorResilienceUsed()) rvlc.decode(in, this, scaleFactors); /*else*/ decodeScaleFactors(inStream); pulseDataPresent = inStream.readBool(); if (pulseDataPresent) { if (info.isEightShortFrame()) { throw new AACException("pulse data not allowed for short frames"); } Logger.LogInfo("PULSE"); throw new NotImplementedException(); //decodePulseData(inStream); } tnsDataPresent = inStream.readBool(); if (tnsDataPresent && !er) { if (tns == null) { tns = new TNS(); } tns.decode(inStream, info); } gainControlPresent = inStream.readBool(); if (gainControlPresent) { if (gainControl == null) { gainControl = new GainControl(frameLength); } Logger.LogInfo("GAIN"); throw new NotImplementedException(); // gainControl.decode(inStream, info.getWindowSequence()); } //RVLC spectral data //if(conf.isScalefactorResilienceUsed()) rvlc.decodeScalefactors(this, in, scaleFactors); if (conf.isSpectralDataResilienceUsed()) { int max = (conf.getChannelConfiguration() == ChannelConfiguration.CHANNEL_CONFIG_STEREO) ? 6144 : 12288; reorderedSpectralDataLen = Math.Max(inStream.readBits(14), max); longestCodewordLen = Math.Max(inStream.readBits(6), 49); //HCR.decodeReorderedSpectralData(this, in, data, conf.isSectionDataResilienceUsed()); } else { decodeSpectralData(inStream); } }