private bool DecodeHuffmanCode(int ch, int gr, int endpos)
        {
            int idx = 0;
            // Reading and decoding BigValue.
            int         Region1Start, Region2Start;
            GranuleInfo f_granule = frame.granule[ch, gr];

            if (f_granule.BlockType == 0)
            {
                Region1Start = ScfBandIndex[frame.FrequencyIndex].
                               LongBlock[f_granule.Region0Count + 1];
                Region2Start = ScfBandIndex[frame.FrequencyIndex].
                               LongBlock[f_granule.Region0Count + f_granule.Region1Count + 2];
            }
            else
            {
                Region1Start = 36;
                Region2Start = 576;
            }

            for (; idx <= 576 - 2 && idx < f_granule.BigValues * 2
                 ; idx += 2)
            {
                int tbl;
                // Region0
                if (idx < Region1Start)
                {
                    tbl = f_granule.GetTableSelect(0);
                }
                // Region1
                else if (idx < Region2Start)
                {
                    tbl = f_granule.GetTableSelect(1);
                }
                // Region2
                else
                {
                    tbl = f_granule.GetTableSelect(2);
                }
                LookupHuffman(ch, tbl, idx);
            }

            // Reading and decoding Count1
            for ( ; (idx <= 576 - 4) && (bs.PositionBit < endpos); idx += 4)
            {
                LookupHuffmanQ(ch, f_granule.Count1TableSelect, idx);
            }

            for (; idx < 576; idx++)
            {
                _is[ch, idx] = 0;
            }
            return(true);
        }
Beispiel #2
0
        public ToyMP3Frame()
        {
            // initialize
            CRC_check = 0;

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    granule[i, j] = new GranuleInfo();
                }
            }
        }
        private void Dequantize(int ch, int gr)
        {
            GranuleInfo _gr  = frame.granule[ch, gr];
            double      Gain = 0.25 * (_gr.GlobalGain - 210.0);

            for (int i = 0; i < 576; i++)
            {
                if (SampleMap[ch, i].BlockType == BLOCK_SHORT)
                {
                    Gain -= -2.0 * _gr.GetSubblockGain(SampleMap[ch, i].Subblock);
                }

                xr[ch, SampleMap[ch, i].OrderIndex] = _is[ch, i] *
                                                      Math.Pow(Math.Abs(_is[ch, i]), 1.0 / 3.0) *
                                                      Math.Pow(2.0, Gain - SampleMap[ch, i].Scale);
            }
        }
        private void Antialias(int ch, int gr)
        {
            if (!AntialiasInitializedFlag)
            {
                InitAntialias();
                AntialiasInitializedFlag = true;
            }

            GranuleInfo _gr = frame.granule[ch, gr];

            if (_gr.IsShortBlock)
            {
                return;
            }
            int nl;

            if (_gr.IsLongBlock)
            {
                nl = 31;
            }
            else
            {
                nl = 1;
            }

            for (int k = 0; k < nl; k++)
            {
                for (int i = 0; i < 8; i++)
                {
                    double a0 = xr[ch, (k * 18) + 18 + i];
                    double b0 = xr[ch, (k * 18) + 17 - i];
                    xr[ch, (k * 18) + 18 + i] = a0 * g_cs[i] + b0 * g_ca[i];
                    xr[ch, (k * 18) + 17 - i] = b0 * g_cs[i] - a0 * g_ca[i];
                }
            }
        }
        private void InverseMDCTSynthesys(int ch, int gr)
        {
            // Initialize
            if (!InversedMDCTInitializedFlag)
            {
                InitIMDCT();
                InversedMDCTInitializedFlag = true;
            }

            GranuleInfo _gr            = frame.granule[ch, gr];
            int         LongSubbandNum = 0;
            int         WindowTypeLong = 0;

            if (_gr.IsLongBlock)
            {
                LongSubbandNum = 32;
                WindowTypeLong = _gr.BlockType;
            }
            else if (_gr.IsShortBlock)
            {
                LongSubbandNum = 0;
                WindowTypeLong = -1;
            }
            else if (_gr.IsMixedBlock)
            {
                LongSubbandNum = 2;
                WindowTypeLong = 0;
            }

            int _Subband = 0;
            int _Index   = 0;

            // Long (and mixed) Block
            for (_Subband = 0; _Subband < LongSubbandNum; _Subband++)
            {
                double[] Rawout = new double[36];
                for (int i = 0; i < 36; i++)
                {
                    double _Sum = 0.0;
                    for (int j = 0; j < 18; j++)
                    {
                        _Sum += xr[ch, j + _Subband * 18] * Math.Cos
                                (
                            Math.PI / 72.0 * (2.0 * i + 19.0) * (2.0 * j + 1.0)
                                );
                    }
                    Rawout[i] = _Sum * SineWindow[WindowTypeLong, i];
                }

                // Combine width last granule and saving;
                for (int ss = 0; ss < 18; ss++)
                {
                    // First half of data + Second half of prev data.
                    pfb[ch, _Index] = Rawout[ss] + ImdctPrevRawout[ch, _Index];
                    // Keep second half of data for next granule.
                    ImdctPrevRawout[ch, _Index] = Rawout[ss + 18];
                    _Index++;
                }
            }

            // ShortBlock
            for (; _Subband < 32; _Subband++)
            {
                double[] Rawout = new double[36];
                for (int _Subblock = 0; _Subblock < 3; _Subblock++)
                {
                    double[] RawoutTmp = new double[12];

                    for (int i = 0; i < 12; i++)
                    {
                        double _Sum = 0;
                        for (int j = 0; j < 6; j++)
                        {
                            _Sum += xr[ch, _Subband *18 + j * 3 + _Subblock] *
                                    Math.Cos(Math.PI / 24.0 * (2.0 * i + 7.0) * (2.0 * j + 1.0));
                        }
                        RawoutTmp[i] = _Sum * SineWindow[2, i];
                    }

                    for (int i = 0; i < 12; i++)
                    {
                        Rawout[6 * _Subblock + i + 6] += RawoutTmp[i];
                    }
                }

                for (int ss = 0; ss < 18; ss++)
                {
                    pfb[ch, _Index]             = Rawout[ss] + ImdctPrevRawout[ch, _Index];
                    ImdctPrevRawout[ch, _Index] = Rawout[ss + 18];

                    _Index++;
                }
            }
        }
        private void CreateSampleMap(int ch, int gr)
        {
            int         idx = 0;
            GranuleInfo _gr = frame.granule[ch, gr];

            // Short Block
            if (_gr.IsShortBlock)
            {
                int[] ScfbIdx = ScfBandIndex[frame.FrequencyIndex].ShortBlock;

                for (int _sbi = 0; _sbi < 13; _sbi++)
                {
                    int idx_s = idx;
                    for (int _sub = 0; _sub < 3; _sub++)
                    {
                        int CriticalBandWidth = ScfbIdx[_sbi + 1] - ScfbIdx[_sbi];
                        for (int i = 0; i < CriticalBandWidth; i++)
                        {
                            SampleMap[ch, idx]           = new Sample();
                            SampleMap[ch, idx].BlockType = BLOCK_SHORT;
                            SampleMap[ch, idx].Subblock  = _sub;
                            SampleMap[ch, idx].Scale     =
                                0.5 * (_gr.ScalefacScale + 1.0) *
                                Scf[ch, gr].ShortBlock[_sub, _sbi];
                            SampleMap[ch, idx].OrderIndex =
                                3 * ((idx - idx_s) % CriticalBandWidth) +
                                (idx - idx_s) / CriticalBandWidth + idx_s;
                            idx++;
                        }
                    }
                }
            }
            // Long Block
            else if (_gr.IsLongBlock)
            {
                int[] ScfbIdx = ScfBandIndex[frame.FrequencyIndex].LongBlock;
                int   Scfb    = 0;

                for (int i = 0; i < 576; i++)
                {
                    SampleMap[ch, idx]            = new Sample();
                    SampleMap[ch, idx].BlockType  = BLOCK_LONG;
                    SampleMap[ch, idx].Subblock   = 0;
                    SampleMap[ch, idx].OrderIndex = idx;
                    if (idx >= ScfbIdx[Scfb + 1])
                    {
                        Scfb++;
                    }

                    int _Scf = Scf[ch, gr].LongBlock[Scfb];
                    if (_gr.PreFlag == 1)
                    {
                        _Scf += PreemphasisTable[Scfb];
                    }
                    SampleMap[ch, idx].Scale =
                        0.5 * (_gr.ScalefacScale + 1.0) * _Scf;
                    idx++;
                }
            }
            // MixedBlock
            else
            {
                // LongBlock sample
                int[] ScfbIdx = ScfBandIndex[frame.FrequencyIndex].LongBlock;
                int   Scfb    = 0;
                for (int i = 0; i < 36; i++)
                {
                    SampleMap[ch, idx]            = new Sample();
                    SampleMap[ch, idx].BlockType  = BLOCK_LONG;
                    SampleMap[ch, idx].Subblock   = 0;
                    SampleMap[ch, idx].OrderIndex = idx;
                    if (idx >= ScfbIdx[Scfb + 1])
                    {
                        Scfb++;
                    }

                    int _Scf = Scf[ch, gr].LongBlock[Scfb];
                    if (_gr.PreFlag == 1)
                    {
                        _Scf += PreemphasisTable[Scfb];
                    }
                    SampleMap[ch, idx].Scale =
                        0.5 * (_gr.ScalefacScale + 1.0) * _Scf;
                    idx++;
                }

                // Short Block Samples
                ScfbIdx = ScfBandIndex[frame.FrequencyIndex].ShortBlock;

                for (Scfb = 3; Scfb < 13; Scfb++)
                {
                    int idx_s = idx;
                    for (int _sub = 0; _sub < 3; _sub++)
                    {
                        int CriticalBandWidth =
                            ScfbIdx[Scfb + 1] - ScfbIdx[Scfb];
                        for (int i = 0; i < CriticalBandWidth; i++)
                        {
                            SampleMap[ch, idx].BlockType = BLOCK_SHORT;
                            SampleMap[ch, idx].Subblock  = _sub;
                            int _Scf = Scf[ch, gr].ShortBlock[_sub, Scfb];
                            SampleMap[ch, idx].Scale =
                                0.5 * (_gr.ScalefacScale + 1.0) * _Scf;
                            SampleMap[ch, idx].OrderIndex =
                                3 * ((idx - idx_s) % CriticalBandWidth) +
                                (idx - idx_s) / CriticalBandWidth + idx_s;
                            idx++;
                        }
                    }
                }
            }
        }
        private void DecodeScalefactor(GranuleInfo granule, int ch, int gr)
        {
            int Slen1 = granule.Slen[0];
            int Slen2 = granule.Slen[1];

            // Mixed Block
            if (granule.IsMixedBlock)
            {
                for (int sfb = 0; sfb < 8; sfb++)
                {
                    Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen1);
                }

                for (int sfb = 3; sfb < 6; sfb++)
                {
                    for (int w = 0; w < 3; w++)
                    {
                        Scf[ch, gr].ShortBlock[w, sfb] = bs.GetByInt(Slen1);
                    }
                }

                for (int sfb = 6; sfb < 12; sfb++)
                {
                    for (int w = 0; w < 3; w++)
                    {
                        Scf[ch, gr].ShortBlock[w, sfb] = bs.GetByInt(Slen2);
                    }
                }
            }
            // Short Block
            else if (granule.IsShortBlock)
            {
                for (int sfb = 0; sfb < 6; sfb++)
                {
                    for (int w = 0; w < 3; w++)
                    {
                        Scf[ch, gr].ShortBlock[w, sfb] = bs.GetByInt(Slen1);
                    }
                }

                for (int sfb = 6; sfb < 12; sfb++)
                {
                    for (int w = 0; w < 3; w++)
                    {
                        Scf[ch, gr].ShortBlock[w, sfb] = bs.GetByInt(Slen2);
                    }
                }
            }
            // Long Block
            else if (granule.IsLongBlock)
            {
                // In case granule0,
                // without exception, data should be taken from bitstream.
                if (gr == 0)
                {
                    for (int sfb = 0; sfb < 11; sfb++)
                    {
                        Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen1);
                    }
                    for (int sfb = 11; sfb < 21; sfb++)
                    {
                        Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen2);
                    }
                }
                else
                {
                    // When processing granule1 and SCFSI is 1,
                    // sdalefactor will shared with granule0.
                    // Else, scalefactor should be got from bitstream.
                    if (frame.GetScfsi(ch, 0) == 1)
                    {
                        for (int sfb = 0; sfb < 6; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = Scf[ch, 0].LongBlock[sfb];
                        }
                    }
                    else
                    {
                        for (int sfb = 0; sfb < 6; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen1);
                        }
                    }

                    if (frame.GetScfsi(ch, 1) == 1)
                    {
                        for (int sfb = 6; sfb < 11; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = Scf[ch, 0].LongBlock[sfb];
                        }
                    }
                    else
                    {
                        for (int sfb = 6; sfb < 11; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen1);
                        }
                    }

                    if (frame.GetScfsi(ch, 2) == 1)
                    {
                        for (int sfb = 11; sfb < 16; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = Scf[ch, 0].LongBlock[sfb];
                        }
                    }
                    else
                    {
                        for (int sfb = 11; sfb < 16; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen2);
                        }
                    }

                    if (frame.GetScfsi(ch, 3) == 1)
                    {
                        for (int sfb = 16; sfb < 21; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = Scf[ch, 0].LongBlock[sfb];
                        }
                    }
                    else
                    {
                        for (int sfb = 16; sfb < 21; sfb++)
                        {
                            Scf[ch, gr].LongBlock[sfb] = bs.GetByInt(Slen2);
                        }
                    }
                }
            }
        }