/// <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()));
        }
        void decode(SampleBuffer buffer)
        {
            if (ADIFHeader.isPresent(inStream))
            {
                adifHeader = ADIFHeader.readHeader(inStream);
                var pce = adifHeader.getFirstPCE();
                config.setProfile(pce.getProfile());
                config.setSampleFrequency(pce.getSampleFrequency());
                config.setChannelConfiguration((ChannelConfiguration)pce.getChannelCount());
            }

            if (!canDecode(config.getProfile()))
            {
                throw new AACException("unsupported profile: " + config.getProfile());
            }

            syntacticElements.startNewFrame();

            //try
            {
                // 1: bitstream parsing and noiseless coding
                syntacticElements.decode(inStream);
                // 2: spectral processing
                syntacticElements.process(filterBank);
                // 3: send to output buffer
                syntacticElements.sendToOutput(buffer);
            }
            //catch (AACException e)
            //{
            //  buffer.setData(new byte[0], 0, 0, 0, 0);
            //  throw e;
            //}
            //catch (Exception e)
            //{
            //  buffer.setData(new byte[0], 0, 0, 0, 0);
            //  throw new AACException(e);
            //}
            // throw new NotImplementedException();
        }
        // --- ========== decoding ========== ---
        public void decode(BitStream inStream, DecoderConfig conf, bool commonWindow)
        {
            var sf = conf.getSampleFrequency();

            if (sf.getIndex() == -1)
            {
                throw new AACException("invalid sample frequency");
            }

            inStream.skipBit(); //reserved
            windowSequence        = (WindowSequence)inStream.readBits(2);
            windowShape[PREVIOUS] = windowShape[CURRENT];
            windowShape[CURRENT]  = inStream.readBit();

            windowGroupCount     = 1;
            windowGroupLength[0] = 1;
            if (windowSequence == WindowSequence.EIGHT_SHORT_SEQUENCE)
            {
                maxSFB = inStream.readBits(4);
                int i;
                for (i = 0; i < 7; i++)
                {
                    if (inStream.readBool())
                    {
                        windowGroupLength[windowGroupCount - 1]++;
                    }
                    else
                    {
                        windowGroupCount++;
                        windowGroupLength[windowGroupCount - 1] = 1;
                    }
                }
                windowCount           = 8;
                swbOffsets            = SWB_OFFSET_SHORT_WINDOW[sf.getIndex()];
                swbCount              = SWB_SHORT_WINDOW_COUNT[sf.getIndex()];
                predictionDataPresent = false;
            }
            else
            {
                maxSFB                = inStream.readBits(6);
                windowCount           = 1;
                swbOffsets            = SWB_OFFSET_LONG_WINDOW[sf.getIndex()];
                swbCount              = SWB_LONG_WINDOW_COUNT[sf.getIndex()];
                predictionDataPresent = inStream.readBool();
                if (predictionDataPresent)
                {
                    readPredictionData(inStream, conf.getProfile(), sf, commonWindow);
                }
            }
        }
        public void decode(BitStream inStream)
        {
            int start = inStream.getPosition(); // should be 0

            bool content = true;

            if (!config.getProfile().isErrorResilientProfile())
            {
                Element prev = null;
                int     type;
                while (content && (type = inStream.readBits(3)) != ELEMENT_END)
                {
                    switch (type)
                    {
                    case ELEMENT_SCE:
                    case ELEMENT_LFE:
                    {
                        Logger.LogInfo("SCE");
                        prev = decodeSCE_LFE(inStream);
                    } break;

                    case ELEMENT_CPE:
                    {
                        Logger.LogVerbose("CPE");
                        prev = decodeCPE(inStream);
                    } break;

                    case ELEMENT_CCE:
                    {
                        Logger.LogInfo("CCE");
                        throw new NotImplementedException();
                        //decodeCCE(inStream);
                        prev = null;
                    } break;

                    case ELEMENT_DSE:
                    {
                        Logger.LogInfo("DSE");
                        throw new NotImplementedException();
                        //decodeDSE(inStream);
                        prev = null;
                    } break;

                    case ELEMENT_PCE:
                    {
                        Logger.LogInfo("PCE");
                        throw new NotImplementedException();
                        //decodePCE(inStream);
                        prev = null;
                    } break;

                    case ELEMENT_FIL:
                    {
                        Logger.LogInfo("FIL");
                        throw new NotImplementedException();
                        //decodeFIL(inStream, prev);
                        prev = null;
                    } break;
                    }
                }
                Logger.LogVerbose("END");
                content = false;
                prev    = null;
            }
            else
            {
                // error resilient raw data block
                throw new NotImplementedException();
                //switch (config.getChannelConfiguration())
                //{
                //  case CHANNEL_CONFIG_MONO: decodeSCE_LFE(inStream); break;
                //  case CHANNEL_CONFIG_STEREO: decodeCPE(inStream); break;
                //  case CHANNEL_CONFIG_STEREO_PLUS_CENTER: decodeSCE_LFE(inStream); decodeCPE(inStream); break;
                //  case CHANNEL_CONFIG_STEREO_PLUS_CENTER_PLUS_REAR_MONO: decodeSCE_LFE(inStream); decodeCPE(inStream); decodeSCE_LFE(inStream); break;
                //  case CHANNEL_CONFIG_FIVE: decodeSCE_LFE(inStream); decodeCPE(inStream); decodeCPE(inStream); break;
                //  case CHANNEL_CONFIG_FIVE_PLUS_ONE: decodeSCE_LFE(inStream); decodeCPE(inStream); decodeCPE(inStream); decodeSCE_LFE(inStream); break;
                //  case CHANNEL_CONFIG_SEVEN_PLUS_ONE: decodeSCE_LFE(inStream); decodeCPE(inStream); decodeCPE(inStream); decodeCPE(inStream); decodeSCE_LFE(inStream); break;
                //  default: throw new AACException("unsupported channel configuration for error resilience: " + config.getChannelConfiguration());
                //}
            }
            inStream.byteAlign();

            bitsRead = inStream.getPosition() - start;
        }
        public void decode(BitStream inStream, DecoderConfig conf)
        {
            var profile = conf.getProfile();
            var sf      = conf.getSampleFrequency();

            if (sf.getIndex() == -1)
            {
                throw new AACException("invalid sample frequency");
            }

            readElementInstanceTag(inStream);

            commonWindow = inStream.readBool();

            var info = icsL.getInfo();

            if (commonWindow)
            {
                info.decode(inStream, conf, commonWindow);
                icsR.getInfo().setData(info);

                msMask = (MSMask)inStream.readBits(2);
                if (msMask == MSMask.TYPE_USED)
                {
                    int maxSFB           = info.getMaxSFB();
                    int windowGroupCount = info.getWindowGroupCount();

                    for (int idx = 0; idx < windowGroupCount * maxSFB; idx++)
                    {
                        msUsed[idx] = inStream.readBool();
                    }
                }
                else if (msMask == MSMask.TYPE_ALL_1)
                {
                    for (int i = 0; i < msUsed.Length; i++)
                    {
                        msUsed[i] = true;
                    }
                }
                else if (msMask == MSMask.TYPE_ALL_0)
                {
                    for (int i = 0; i < msUsed.Length; i++)
                    {
                        msUsed[i] = false;
                    }
                }
                else
                {
                    throw new AACException("reserved MS mask type used");
                }
            }
            else
            {
                msMask = MSMask.TYPE_ALL_0;
                for (int i = 0; i < msUsed.Length; i++)
                {
                    msUsed[i] = false;
                }
            }

            if (profile.isErrorResilientProfile() && (info.isLTPrediction1Present()))
            {
                if (info.ltpData2Present = inStream.readBool())
                {
                    info.getLTPrediction2().decode(inStream, info, profile);
                }
            }

            icsL.decode(inStream, commonWindow, conf);
            icsR.decode(inStream, commonWindow, conf);
        }
Beispiel #6
0
        //  /* ========= 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);
            }
        }