Beispiel #1
0
        private int LongHuffmancodebits(LameInternalFlags gfc, GrInfo gi)
        {
            int bigvalues, bits;
            int region1Start, region2Start;

            bigvalues = gi.big_values;
            Debug.Assert(0 <= bigvalues && bigvalues <= 576);

            var i = gi.region0_count + 1;

            Debug.Assert(0 <= i);
            Debug.Assert(i < gfc.scalefac_band.l.Length);
            region1Start = gfc.scalefac_band.l[i];
            i           += gi.region1_count + 1;
            Debug.Assert(0 <= i);
            Debug.Assert(i < gfc.scalefac_band.l.Length);
            region2Start = gfc.scalefac_band.l[i];

            if (region1Start > bigvalues)
            {
                region1Start = bigvalues;
            }

            if (region2Start > bigvalues)
            {
                region2Start = bigvalues;
            }

            bits  = Huffmancode(gfc, gi.table_select[0], 0, region1Start, gi);
            bits += Huffmancode(gfc, gi.table_select[1], region1Start, region2Start, gi);
            bits += Huffmancode(gfc, gi.table_select[2], region2Start, bigvalues, gi);
            return(bits);
        }
Beispiel #2
0
        private void inc_scalefac_scale(GrInfo cod_info, float[] xrpow)
        {
            const float ifqstep34 = 1.29683955465100964055f;
            var         j         = 0;

            for (var sfb = 0; sfb < cod_info.sfbmax; sfb++)
            {
                var width = cod_info.width[sfb];
                var s     = cod_info.scalefac[sfb];
                if (cod_info.preflag != 0)
                {
                    s += qupvt.pretab[sfb];
                }

                j += width;
                if ((s & 1) != 0)
                {
                    s++;
                    for (var l = -width; l < 0; l++)
                    {
                        xrpow[j + l] *= ifqstep34;
                        if (xrpow[j + l] > cod_info.xrpow_max)
                        {
                            cod_info.xrpow_max = xrpow[j + l];
                        }
                    }
                }

                cod_info.scalefac[sfb] = s >> 1;
            }

            cod_info.preflag        = 0;
            cod_info.scalefac_scale = 1;
        }
Beispiel #3
0
        internal bool init_xrpow(LameInternalFlags gfc, GrInfo cod_info, float[] xrpow)
        {
            float sum = 0;

            var upper = cod_info.max_nonzero_coeff;

            Debug.Assert(xrpow != null);
            cod_info.xrpow_max = 0;
            Debug.Assert(0 <= upper && upper <= 575);
            Arrays.Fill(xrpow, upper, 576, 0);
            sum = init_xrpow_core(cod_info, xrpow, upper, sum);
            if (sum > 1E-20f)
            {
                var j = 0;
                if ((gfc.substep_shaping & 2) != 0)
                {
                    j = 1;
                }

                for (var i = 0; i < cod_info.psymax; i++)
                {
                    gfc.pseudohalf[i] = j;
                }

                return(true);
            }

            Arrays.Fill(cod_info.l3_enc, 0, 576, 0);
            return(false);
        }
Beispiel #4
0
        private bool balance_noise(LameGlobalFlags gfp, GrInfo cod_info, float[] distort, float[] xrpow, bool bRefine)
        {
            var gfc = gfp.internal_flags;

            amp_scalefac_bands(gfp, cod_info, distort, xrpow, bRefine);
            var status = loop_break(cod_info);

            if (status)
            {
                return(false);
            }

            if (gfc.mode_gr == 2)
            {
                status = tk.scale_bitcount(cod_info);
            }
            else
            {
                status = tk.scale_bitcount_lsf(gfc, cod_info);
            }

            if (!status)
            {
                return(true);
            }

            if (gfc.noise_shaping > 1)
            {
                Arrays.Fill(gfc.pseudohalf, 0);
                if (0 == cod_info.scalefac_scale)
                {
                    inc_scalefac_scale(cod_info, xrpow);
                    status = false;
                }
                else
                {
                    if (cod_info.block_type == Encoder.SHORT_TYPE && gfc.subblock_gain > 0)
                    {
                        status = inc_subblock_gain(gfc, cod_info, xrpow) || loop_break(cod_info);
                    }
                }
            }

            if (!status)
            {
                if (gfc.mode_gr == 2)
                {
                    status = tk.scale_bitcount(cod_info);
                }
                else
                {
                    status = tk.scale_bitcount_lsf(gfc, cod_info);
                }
            }

            return(!status);
        }
Beispiel #5
0
 internal IIISideInfo()
 {
     for (var gr = 0; gr < 2; gr++)
     {
         for (var ch = 0; ch < 2; ch++)
         {
             tt[gr][ch] = new GrInfo();
         }
     }
 }
Beispiel #6
0
        private double get_klemm_noise(float[] distort, GrInfo gi)
        {
            var klemm_noise = 1E-37;

            for (var sfb = 0; sfb < gi.psymax; sfb++)
            {
                klemm_noise += penalties(distort[sfb]);
            }

            return(Math.Max(1e-20, klemm_noise));
        }
        protected internal virtual void set_scalefacs(GrInfo cod_info, int[] vbrsfmin, int[] sf, int[] max_range)
        {
            var ifqstep = cod_info.scalefac_scale == 0 ? 2 : 4;

            var ifqstepShift = cod_info.scalefac_scale == 0 ? 1 : 2;

            var scalefac = cod_info.scalefac;

            var sfbmax = cod_info.sfbmax;

            var sbg = cod_info.subblock_gain;

            var window = cod_info.window;

            var preflag = cod_info.preflag;

            if (preflag != 0)
            {
                for (var sfb = 11; sfb < sfbmax; ++sfb)
                {
                    sf[sfb] += qupvt.pretab[sfb] * ifqstep;
                }
            }

            for (var sfb = 0; sfb < sfbmax; ++sfb)
            {
                var gain = cod_info.global_gain - sbg[window[sfb]] * 8 -
                           (preflag != 0 ? qupvt.pretab[sfb] : 0) * ifqstep;
                if (sf[sfb] < 0)
                {
                    var m = gain - vbrsfmin[sfb];
                    /* ifqstep*scalefac >= -sf[sfb], so round UP */
                    scalefac[sfb] = (ifqstep - 1 - sf[sfb]) >> ifqstepShift;
                    if (scalefac[sfb] > max_range[sfb])
                    {
                        scalefac[sfb] = max_range[sfb];
                    }

                    if (scalefac[sfb] > 0 && scalefac[sfb] << ifqstepShift > m)
                    {
                        scalefac[sfb] = m >> ifqstepShift;
                    }
                }
                else
                {
                    scalefac[sfb] = 0;
                }
            }

            for (var sfb = sfbmax; sfb < L3Side.SFBMAX; ++sfb)
            {
                scalefac[sfb] = 0; // sfb21
            }
        }
Beispiel #8
0
        private bool loop_break(GrInfo cod_info)
        {
            for (var sfb = 0; sfb < cod_info.sfbmax; sfb++)
            {
                if (cod_info.scalefac[sfb] + cod_info.subblock_gain[cod_info.window[sfb]] == 0)
                {
                    return(false);
                }
            }

            return(true);
        }
        private float calc_noise_core(GrInfo cod_info, StartLine startline, int l, float step)
        {
            float noise = 0;
            var   j     = startline.s;

            var ix = cod_info.l3_enc;

            if (j > cod_info.count1)
            {
                while (l-- != 0)
                {
                    float temp;
                    temp = cod_info.xr[j];
                    j++;
                    noise += temp * temp;
                    temp   = cod_info.xr[j];
                    j++;
                    noise += temp * temp;
                }
            }
            else if (j > cod_info.big_values)
            {
                var ix01 = new float[2];
                ix01[0] = 0;
                ix01[1] = step;
                while (l-- != 0)
                {
                    float temp;
                    temp = Math.Abs(cod_info.xr[j]) - ix01[ix[j]];
                    j++;
                    noise += temp * temp;
                    temp   = Math.Abs(cod_info.xr[j]) - ix01[ix[j]];
                    j++;
                    noise += temp * temp;
                }
            }
            else
            {
                while (l-- != 0)
                {
                    float temp;
                    temp = Math.Abs(cod_info.xr[j]) - pow43[ix[j]] * step;
                    j++;
                    noise += temp * temp;
                    temp   = Math.Abs(cod_info.xr[j]) - pow43[ix[j]] * step;
                    j++;
                    noise += temp * temp;
                }
            }

            startline.s = j;
            return(noise);
        }
Beispiel #10
0
        /// <summary>
        ///     Note the discussion of huffmancodebits() on pages 28 and 29 of the IS, as
        ///     well as the definitions of the side information on pages 26 and 27.
        /// </summary>
        private int ShortHuffmancodebits(LameInternalFlags gfc, GrInfo gi)
        {
            var region1Start = 3 * gfc.scalefac_band.s[3];

            if (region1Start > gi.big_values)
            {
                region1Start = gi.big_values;
            }

            /* short blocks do not have a region2 */
            var bits = Huffmancode(gfc, gi.table_select[0], 0, region1Start, gi);

            bits += Huffmancode(gfc, gi.table_select[1], region1Start, gi.big_values, gi);
            return(bits);
        }
        protected internal virtual bool checkScalefactor(GrInfo cod_info, int[] vbrsfmin)
        {
            var ifqstep = cod_info.scalefac_scale == 0 ? 2 : 4;

            for (var sfb = 0; sfb < cod_info.psymax; ++sfb)
            {
                var s = (cod_info.scalefac[sfb] + (cod_info.preflag != 0 ? qupvt.pretab[sfb] : 0)) * ifqstep +
                        cod_info.subblock_gain[cod_info.window[sfb]] * 8;
                if (cod_info.global_gain - s < vbrsfmin[sfb])
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #12
0
        private float init_xrpow_core(GrInfo cod_info, float[] xrpow, int upper, float sum)
        {
            sum = 0;
            for (var i = 0; i <= upper; ++i)
            {
                var tmp = Math.Abs(cod_info.xr[i]);
                sum     += tmp;
                xrpow[i] = (float)Math.Sqrt(tmp * Math.Sqrt(tmp));
                if (xrpow[i] > cod_info.xrpow_max)
                {
                    cod_info.xrpow_max = xrpow[i];
                }
            }

            return(sum);
        }
Beispiel #13
0
        internal void assign(GrInfo other)
        {
            Array.Copy(other.xr, xr, other.xr.Length);
            Array.Copy(other.l3_enc, l3_enc, other.l3_enc.Length);
            Array.Copy(other.scalefac, scalefac, other.scalefac.Length);
            xrpow_max = other.xrpow_max;

            part2_3_length    = other.part2_3_length;
            big_values        = other.big_values;
            count1            = other.count1;
            global_gain       = other.global_gain;
            scalefac_compress = other.scalefac_compress;
            block_type        = other.block_type;
            mixed_block_flag  = other.mixed_block_flag;
            Array.Copy(other.table_select, table_select, other.table_select.Length);
            Array.Copy(other.subblock_gain, subblock_gain, other.subblock_gain.Length);
            region0_count      = other.region0_count;
            region1_count      = other.region1_count;
            preflag            = other.preflag;
            scalefac_scale     = other.scalefac_scale;
            count1table_select = other.count1table_select;

            part2_length = other.part2_length;
            sfb_lmax     = other.sfb_lmax;
            sfb_smin     = other.sfb_smin;
            psy_lmax     = other.psy_lmax;
            sfbmax       = other.sfbmax;
            psymax       = other.psymax;
            sfbdivide    = other.sfbdivide;
            Array.Copy(other.width, width, other.width.Length);
            Array.Copy(other.window, window, other.window.Length);
            count1bits = other.count1bits;

            sfb_partition_table = new int[other.sfb_partition_table.Length];
            Array.Copy(other.sfb_partition_table, sfb_partition_table, other.sfb_partition_table.Length);
            Array.Copy(other.slen, slen, other.slen.Length);
            max_nonzero_coeff = other.max_nonzero_coeff;
        }
Beispiel #14
0
        internal void trancate_smallspectrums(LameInternalFlags gfc, GrInfo gi, float[] l3_xmin, float[] work)
        {
            var distort = new float[L3Side.SFBMAX];

            if (0 == (gfc.substep_shaping & 4) && gi.block_type == Encoder.SHORT_TYPE ||
                (gfc.substep_shaping & 0x80) != 0)
            {
                return;
            }

            qupvt.calc_noise(gi, l3_xmin, distort, new CalcNoiseResult(), null);
            for (var jj = 0; jj < 576; jj++)
            {
                var xr = 0.0f;
                if (gi.l3_enc[jj] != 0)
                {
                    xr = Math.Abs(gi.xr[jj]);
                }

                work[jj] = xr;
            }

            var j   = 0;
            var sfb = 8;

            if (gi.block_type == Encoder.SHORT_TYPE)
            {
                sfb = 6;
            }

            do
            {
                float allowedNoise, trancateThreshold;
                int   nsame, start;
                var   width = gi.width[sfb];
                j += width;
                if (distort[sfb] >= 1.0)
                {
                    continue;
                }

                Arrays.Sort(work, j - width, width);
                if (BitStream.EQ(work[j - 1], 0.0f))
                {
                    continue;
                }

                allowedNoise      = (1.0f - distort[sfb]) * l3_xmin[sfb];
                trancateThreshold = 0.0f;
                start             = 0;
                do
                {
                    float noise;
                    for (nsame = 1; start + nsame < width; nsame++)
                    {
                        if (BitStream.NEQ(work[start + j - width], work[start + j + nsame - width]))
                        {
                            break;
                        }
                    }

                    noise = work[start + j - width] * work[start + j - width] * nsame;
                    if (allowedNoise < noise)
                    {
                        if (start != 0)
                        {
                            trancateThreshold = work[start + j - width - 1];
                        }

                        break;
                    }

                    allowedNoise -= noise;
                    start        += nsame;
                }while (start < width);

                if (BitStream.EQ(trancateThreshold, 0.0f))
                {
                    continue;
                }

                do
                {
                    if (Math.Abs(gi.xr[j - width]) <= trancateThreshold)
                    {
                        gi.l3_enc[j - width] = 0;
                    }
                }while (--width > 0);
            }while (++sfb < gi.psymax);

            gi.part2_3_length = tk.noquant_count_bits(gfc, gi, null);
        }
Beispiel #15
0
        private int bin_search_StepSize(LameInternalFlags gfc, GrInfo cod_info, int desired_rate, int ch, float[] xrpow)
        {
            int nBits;
            var CurrentStep  = gfc.CurrentStep[ch];
            var flagGoneOver = false;

            var start     = gfc.OldValue[ch];
            var Direction = BinSearchDirection.BINSEARCH_NONE;

            cod_info.global_gain = start;
            desired_rate        -= cod_info.part2_length;
            Debug.Assert(CurrentStep != 0);
            for (;;)
            {
                int step;
                nBits = tk.count_bits(gfc, xrpow, cod_info, null);
                if (CurrentStep == 1 || nBits == desired_rate)
                {
                    break;
                }

                if (nBits > desired_rate)
                {
                    if (Direction == BinSearchDirection.BINSEARCH_DOWN)
                    {
                        flagGoneOver = true;
                    }

                    if (flagGoneOver)
                    {
                        CurrentStep /= 2;
                    }

                    Direction = BinSearchDirection.BINSEARCH_UP;
                    step      = CurrentStep;
                }
                else
                {
                    if (Direction == BinSearchDirection.BINSEARCH_UP)
                    {
                        flagGoneOver = true;
                    }

                    if (flagGoneOver)
                    {
                        CurrentStep /= 2;
                    }

                    Direction = BinSearchDirection.BINSEARCH_DOWN;
                    step      = -CurrentStep;
                }

                cod_info.global_gain += step;
                if (cod_info.global_gain < 0)
                {
                    cod_info.global_gain = 0;
                    flagGoneOver         = true;
                }

                if (cod_info.global_gain > 255)
                {
                    cod_info.global_gain = 255;
                    flagGoneOver         = true;
                }
            }

            Debug.Assert(cod_info.global_gain >= 0);
            Debug.Assert(cod_info.global_gain < 256);
            while (nBits > desired_rate && cod_info.global_gain < 255)
            {
                cod_info.global_gain++;
                nBits = tk.count_bits(gfc, xrpow, cod_info, null);
            }

            gfc.CurrentStep[ch]     = start - cod_info.global_gain >= 4 ? 4 : 2;
            gfc.OldValue[ch]        = cod_info.global_gain;
            cod_info.part2_3_length = nBits;
            return(nBits);
        }
Beispiel #16
0
        private bool inc_subblock_gain(LameInternalFlags gfc, GrInfo cod_info, float[] xrpow)
        {
            int sfb;

            var scalefac = cod_info.scalefac;

            for (sfb = 0; sfb < cod_info.sfb_lmax; sfb++)
            {
                if (scalefac[sfb] >= 16)
                {
                    return(true);
                }
            }

            for (var window = 0; window < 3; window++)
            {
                var s1 = 0;
                var s2 = 0;
                for (sfb = cod_info.sfb_lmax + window; sfb < cod_info.sfbdivide; sfb += 3)
                {
                    if (s1 < scalefac[sfb])
                    {
                        s1 = scalefac[sfb];
                    }
                }

                for (; sfb < cod_info.sfbmax; sfb += 3)
                {
                    if (s2 < scalefac[sfb])
                    {
                        s2 = scalefac[sfb];
                    }
                }

                if (s1 < 16 && s2 < 8)
                {
                    continue;
                }

                if (cod_info.subblock_gain[window] >= 7)
                {
                    return(true);
                }

                cod_info.subblock_gain[window]++;
                var j = gfc.scalefac_band.l[cod_info.sfb_lmax];
                for (sfb = cod_info.sfb_lmax + window; sfb < cod_info.sfbmax; sfb += 3)
                {
                    float amp;

                    var width = cod_info.width[sfb];
                    var s     = scalefac[sfb];
                    Debug.Assert(s >= 0);
                    s = s - (4 >> cod_info.scalefac_scale);
                    if (s >= 0)
                    {
                        scalefac[sfb] = s;
                        j            += width * 3;
                        continue;
                    }

                    scalefac[sfb] = 0;
                    {
                        var gain = 210 + (s << (cod_info.scalefac_scale + 1));
                        amp = qupvt.IPOW20(gain);
                    }
                    j += width * (window + 1);
                    for (var l = -width; l < 0; l++)
                    {
                        xrpow[j + l] *= amp;
                        if (xrpow[j + l] > cod_info.xrpow_max)
                        {
                            cod_info.xrpow_max = xrpow[j + l];
                        }
                    }

                    j += width * (3 - window - 1);
                }

                {
                    var amp = qupvt.IPOW20(202);
                    j += cod_info.width[sfb] * (window + 1);
                    for (var l = -cod_info.width[sfb]; l < 0; l++)
                    {
                        xrpow[j + l] *= amp;
                        if (xrpow[j + l] > cod_info.xrpow_max)
                        {
                            cod_info.xrpow_max = xrpow[j + l];
                        }
                    }
                }
            }

            return(false);
        }
        private void set_pinfo(LameGlobalFlags gfp, GrInfo cod_info, III_psy_ratio ratio, int gr, int ch)
        {
            var   gfc = gfp.internal_flags;
            int   sfb, sfb2;
            int   l;
            float en0, en1;
            var   ifqstep  = cod_info.scalefac_scale == 0 ? .5f : 1.0f;
            var   scalefac = cod_info.scalefac;
            var   l3_xmin  = new float[L3Side.SFBMAX];
            var   xfsf     = new float[L3Side.SFBMAX];
            var   noise    = new CalcNoiseResult();

            calc_xmin(gfp, ratio, cod_info, l3_xmin);
            calc_noise(cod_info, l3_xmin, xfsf, noise, null);
            var j = 0;

            sfb2 = cod_info.sfb_lmax;
            if (cod_info.block_type != Encoder.SHORT_TYPE && 0 == cod_info.mixed_block_flag)
            {
                sfb2 = 22;
            }

            for (sfb = 0; sfb < sfb2; sfb++)
            {
                var start = gfc.scalefac_band.l[sfb];
                var end   = gfc.scalefac_band.l[sfb + 1];
                var bw    = end - start;
                for (en0 = 0.0f; j < end; j++)
                {
                    en0 += cod_info.xr[j] * cod_info.xr[j];
                }

                en0 /= bw;
                en1  = 1e15f;
                gfc.pinfo.en[gr][ch][sfb]   = en1 * en0;
                gfc.pinfo.xfsf[gr][ch][sfb] = en1 * l3_xmin[sfb] * xfsf[sfb] / bw;
                if (ratio.en.l[sfb] > 0 && !gfp.ATHonly)
                {
                    en0 = en0 / ratio.en.l[sfb];
                }
                else
                {
                    en0 = 0.0f;
                }

                gfc.pinfo.thr[gr][ch][sfb]     = en1 * Math.Max(en0 * ratio.thm.l[sfb], gfc.ATH.l[sfb]);
                gfc.pinfo.LAMEsfb[gr][ch][sfb] = 0;
                if (cod_info.preflag != 0 && sfb >= 11)
                {
                    gfc.pinfo.LAMEsfb[gr][ch][sfb] = -ifqstep * pretab[sfb];
                }

                if (sfb < Encoder.SBPSY_l)
                {
                    Debug.Assert(scalefac[sfb] >= 0);
                    gfc.pinfo.LAMEsfb[gr][ch][sfb] -= ifqstep * scalefac[sfb];
                }
            }

            if (cod_info.block_type == Encoder.SHORT_TYPE)
            {
                sfb2 = sfb;
                for (sfb = cod_info.sfb_smin; sfb < Encoder.SBMAX_s; sfb++)
                {
                    var start = gfc.scalefac_band.s[sfb];
                    var end   = gfc.scalefac_band.s[sfb + 1];
                    var bw    = end - start;
                    for (var i = 0; i < 3; i++)
                    {
                        for (en0 = 0.0f, l = start; l < end; l++)
                        {
                            en0 += cod_info.xr[j] * cod_info.xr[j];
                            j++;
                        }

                        en0 = (float)Math.Max(en0 / bw, 1e-20);
                        en1 = 1e15f;
                        gfc.pinfo.en_s[gr][ch][3 * sfb + i]   = en1 * en0;
                        gfc.pinfo.xfsf_s[gr][ch][3 * sfb + i] = en1 * l3_xmin[sfb2] * xfsf[sfb2] / bw;
                        if (ratio.en.s[sfb][i] > 0)
                        {
                            en0 = en0 / ratio.en.s[sfb][i];
                        }
                        else
                        {
                            en0 = 0.0f;
                        }

                        if (gfp.ATHonly || gfp.ATHshort)
                        {
                            en0 = 0;
                        }

                        gfc.pinfo.thr_s[gr][ch][3 * sfb + i] =
                            en1 * Math.Max(en0 * ratio.thm.s[sfb][i], gfc.ATH.s[sfb]);
                        gfc.pinfo.LAMEsfb_s[gr][ch][3 * sfb + i] = -2.0 * cod_info.subblock_gain[i];
                        if (sfb < Encoder.SBPSY_s)
                        {
                            gfc.pinfo.LAMEsfb_s[gr][ch][3 * sfb + i] -= ifqstep * scalefac[sfb2];
                        }

                        sfb2++;
                    }
                }
            }

            gfc.pinfo.LAMEqss[gr][ch]      = cod_info.global_gain;
            gfc.pinfo.LAMEmainbits[gr][ch] = cod_info.part2_3_length + cod_info.part2_length;
            gfc.pinfo.LAMEsfbits[gr][ch]   = cod_info.part2_length;
            gfc.pinfo.over[gr][ch]         = noise.over_count;
            gfc.pinfo.max_noise[gr][ch]    = noise.max_noise * 10.0;
            gfc.pinfo.over_noise[gr][ch]   = noise.over_noise * 10.0;
            gfc.pinfo.tot_noise[gr][ch]    = noise.tot_noise * 10.0;
            gfc.pinfo.over_SSD[gr][ch]     = noise.over_SSD;
        }
        internal int calc_noise(
            GrInfo cod_info,
            float[] l3_xmin,
            float[] distort,
            CalcNoiseResult res,
            CalcNoiseData prev_noise)
        {
            var   distortPos = 0;
            var   l3_xminPos = 0;
            int   sfb, l, over = 0;
            float over_noise_db = 0;
            float tot_noise_db  = 0;
            var   max_noise     = -20.0f;
            var   j             = 0;

            var scalefac    = cod_info.scalefac;
            var scalefacPos = 0;

            res.over_SSD = 0;
            for (sfb = 0; sfb < cod_info.psymax; sfb++)
            {
                var s = cod_info.global_gain -
                        ((scalefac[scalefacPos++] + (cod_info.preflag != 0 ? pretab[sfb] : 0)) <<
                         (cod_info.scalefac_scale + 1)) - cod_info.subblock_gain[cod_info.window[sfb]] * 8;
                var noise = 0.0f;
                if (prev_noise != null && prev_noise.step[sfb] == s)
                {
                    noise = prev_noise.noise[sfb];
                    j    += cod_info.width[sfb];
                    distort[distortPos++] = noise / l3_xmin[l3_xminPos++];
                    noise = prev_noise.noise_log[sfb];
                }
                else
                {
                    var step = POW20(s);
                    l = cod_info.width[sfb] >> 1;
                    if (j + cod_info.width[sfb] > cod_info.max_nonzero_coeff)
                    {
                        int usefullsize;
                        usefullsize = cod_info.max_nonzero_coeff - j + 1;
                        if (usefullsize > 0)
                        {
                            l = usefullsize >> 1;
                        }
                        else
                        {
                            l = 0;
                        }
                    }

                    var sl = new StartLine(j);
                    noise = calc_noise_core(cod_info, sl, l, step);
                    j     = sl.s;
                    if (prev_noise != null)
                    {
                        prev_noise.step[sfb]  = s;
                        prev_noise.noise[sfb] = noise;
                    }

                    noise = distort[distortPos++] = noise / l3_xmin[l3_xminPos++];
                    noise = Util.FAST_LOG10((float)Math.Max(noise, 1E-20));
                    if (prev_noise != null)
                    {
                        prev_noise.noise_log[sfb] = noise;
                    }
                }

                if (prev_noise != null)
                {
                    prev_noise.global_gain = cod_info.global_gain;
                }

                tot_noise_db += noise;
                if (noise > 0.0)
                {
                    int tmp;
                    tmp           = Math.Max((int)(noise * 10 + .5), 1);
                    res.over_SSD += tmp * tmp;
                    over++;
                    over_noise_db += noise;
                }

                max_noise = Math.Max(max_noise, noise);
            }

            res.over_count = over;
            res.tot_noise  = tot_noise_db;
            res.over_noise = over_noise_db;
            res.max_noise  = max_noise;
            return(over);
        }
        internal int calc_xmin(LameGlobalFlags gfp, III_psy_ratio ratio, GrInfo cod_info, float[] pxmin)
        {
            var pxminPos = 0;

            var gfc = gfp.internal_flags;
            int gsfb, j = 0, ath_over = 0;

            var ATH = gfc.ATH;

            var xr = cod_info.xr;

            var enable_athaa_fix = gfp.VBR == VbrMode.vbr_mtrh ? 1 : 0;
            var masking_lower    = gfc.masking_lower;

            if (gfp.VBR == VbrMode.vbr_mtrh || gfp.VBR == VbrMode.vbr_mt)
            {
                masking_lower = 1.0f;
            }

            for (gsfb = 0; gsfb < cod_info.psy_lmax; gsfb++)
            {
                float en0, xmin;
                float rh1, rh2;
                int   width, l;
                if (gfp.VBR == VbrMode.vbr_rh || gfp.VBR == VbrMode.vbr_mtrh)
                {
                    xmin = athAdjust(ATH.adjust, ATH.l[gsfb], ATH.floor);
                }
                else
                {
                    xmin = ATH.adjust * ATH.l[gsfb];
                }

                width = cod_info.width[gsfb];
                rh1   = xmin / width;
                rh2   = DBL_EPSILON;
                l     = width >> 1;
                en0   = 0.0f;
                do
                {
                    float xa, xb;
                    xa   = xr[j] * xr[j];
                    en0 += xa;
                    rh2 += xa < rh1 ? xa : rh1;
                    j++;
                    xb   = xr[j] * xr[j];
                    en0 += xb;
                    rh2 += xb < rh1 ? xb : rh1;
                    j++;
                }while (--l > 0);

                if (en0 > xmin)
                {
                    ath_over++;
                }

                if (gsfb == Encoder.SBPSY_l)
                {
                    var x = xmin * gfc.nsPsy.longfact[gsfb];
                    if (rh2 < x)
                    {
                        rh2 = x;
                    }
                }

                if (enable_athaa_fix != 0)
                {
                    xmin = rh2;
                }

                if (!gfp.ATHonly)
                {
                    var e = ratio.en.l[gsfb];
                    if (e > 0.0f)
                    {
                        float x;
                        x = en0 * ratio.thm.l[gsfb] * masking_lower / e;
                        if (enable_athaa_fix != 0)
                        {
                            x *= gfc.nsPsy.longfact[gsfb];
                        }

                        if (xmin < x)
                        {
                            xmin = x;
                        }
                    }
                }

                if (enable_athaa_fix != 0)
                {
                    pxmin[pxminPos++] = xmin;
                }
                else
                {
                    pxmin[pxminPos++] = xmin * gfc.nsPsy.longfact[gsfb];
                }
            }

            var max_nonzero = 575;

            if (cod_info.block_type != Encoder.SHORT_TYPE)
            {
                var k = 576;
                while (k-- != 0 && BitStream.EQ(xr[k], 0))
                {
                    max_nonzero = k;
                }
            }

            cod_info.max_nonzero_coeff = max_nonzero;
            for (var sfb = cod_info.sfb_smin; gsfb < cod_info.psymax; sfb++, gsfb += 3)
            {
                int   width, b;
                float tmpATH;
                if (gfp.VBR == VbrMode.vbr_rh || gfp.VBR == VbrMode.vbr_mtrh)
                {
                    tmpATH = athAdjust(ATH.adjust, ATH.s[sfb], ATH.floor);
                }
                else
                {
                    tmpATH = ATH.adjust * ATH.s[sfb];
                }

                width = cod_info.width[gsfb];
                for (b = 0; b < 3; b++)
                {
                    float en0 = 0.0f, xmin;
                    float rh1, rh2;
                    var   l = width >> 1;
                    rh1 = tmpATH / width;
                    rh2 = DBL_EPSILON;
                    do
                    {
                        float xa, xb;
                        xa   = xr[j] * xr[j];
                        en0 += xa;
                        rh2 += xa < rh1 ? xa : rh1;
                        j++;
                        xb   = xr[j] * xr[j];
                        en0 += xb;
                        rh2 += xb < rh1 ? xb : rh1;
                        j++;
                    }while (--l > 0);

                    if (en0 > tmpATH)
                    {
                        ath_over++;
                    }

                    if (sfb == Encoder.SBPSY_s)
                    {
                        var x = tmpATH * gfc.nsPsy.shortfact[sfb];
                        if (rh2 < x)
                        {
                            rh2 = x;
                        }
                    }

                    if (enable_athaa_fix != 0)
                    {
                        xmin = rh2;
                    }
                    else
                    {
                        xmin = tmpATH;
                    }

                    if (!gfp.ATHonly && !gfp.ATHshort)
                    {
                        var e = ratio.en.s[sfb][b];
                        if (e > 0.0f)
                        {
                            float x;
                            x = en0 * ratio.thm.s[sfb][b] * masking_lower / e;
                            if (enable_athaa_fix != 0)
                            {
                                x *= gfc.nsPsy.shortfact[sfb];
                            }

                            if (xmin < x)
                            {
                                xmin = x;
                            }
                        }
                    }

                    if (enable_athaa_fix != 0)
                    {
                        pxmin[pxminPos++] = xmin;
                    }
                    else
                    {
                        pxmin[pxminPos++] = xmin * gfc.nsPsy.shortfact[sfb];
                    }
                }

                if (gfp.useTemporal == true)
                {
                    if (pxmin[pxminPos - 3] > pxmin[pxminPos - 3 + 1])
                    {
                        pxmin[pxminPos - 3 + 1] += (pxmin[pxminPos - 3] - pxmin[pxminPos - 3 + 1]) * gfc.decay;
                    }

                    if (pxmin[pxminPos - 3 + 1] > pxmin[pxminPos - 3 + 2])
                    {
                        pxmin[pxminPos - 3 + 2] += (pxmin[pxminPos - 3 + 1] - pxmin[pxminPos - 3 + 2]) * gfc.decay;
                    }
                }
            }

            return(ath_over);
        }
Beispiel #20
0
        private bool quant_compare(
            int quant_comp,
            CalcNoiseResult best,
            CalcNoiseResult calc,
            GrInfo gi,
            float[] distort)
        {
            bool better;

            switch (quant_comp)
            {
            default:
                goto case 9;

            case 9:
            {
                if (best.over_count > 0)
                {
                    better = calc.over_SSD <= best.over_SSD;
                    if (calc.over_SSD == best.over_SSD)
                    {
                        better = calc.bits < best.bits;
                    }
                }
                else
                {
                    better = calc.max_noise < 0 &&
                             calc.max_noise * 10 + calc.bits <= best.max_noise * 10 + best.bits;
                }

                break;
            }

            case 0:
                better = calc.over_count < best.over_count ||
                         calc.over_count == best.over_count && calc.over_noise < best.over_noise ||
                         calc.over_count == best.over_count && BitStream.EQ(calc.over_noise, best.over_noise) &&
                         calc.tot_noise < best.tot_noise;
                break;

            case 8:
                calc.max_noise = (float)get_klemm_noise(distort, gi);
                goto case 1;

            case 1:
                better = calc.max_noise < best.max_noise;
                break;

            case 2:
                better = calc.tot_noise < best.tot_noise;
                break;

            case 3:
                better = calc.tot_noise < best.tot_noise && calc.max_noise < best.max_noise;
                break;

            case 4:
                better = calc.max_noise <= 0.0 && best.max_noise > 0.2 ||
                         calc.max_noise <= 0.0 && best.max_noise <0.0 && best.max_noise> calc.max_noise - 0.2 &&
                         calc.tot_noise <best.tot_noise ||
                                         calc.max_noise <= 0.0 && best.max_noise> 0.0 && best.max_noise > calc.max_noise - 0.2 &&
                         calc.tot_noise <best.tot_noise + best.over_noise ||
                                         calc.max_noise> 0.0 && best.max_noise > -0.05 && best.max_noise > calc.max_noise - 0.1 &&
                         calc.tot_noise + calc.over_noise <best.tot_noise + best.over_noise ||
                                                           calc.max_noise> 0.0 && best.max_noise > -0.1 && best.max_noise > calc.max_noise - 0.15 &&
                         calc.tot_noise + calc.over_noise + calc.over_noise <
                         best.tot_noise + best.over_noise + best.over_noise;
                break;

            case 5:
                better = calc.over_noise < best.over_noise ||
                         BitStream.EQ(calc.over_noise, best.over_noise) && calc.tot_noise < best.tot_noise;
                break;

            case 6:
                better = calc.over_noise < best.over_noise ||
                         BitStream.EQ(calc.over_noise, best.over_noise) &&
                         (calc.max_noise < best.max_noise ||
                          BitStream.EQ(calc.max_noise, best.max_noise) && calc.tot_noise <= best.tot_noise);
                break;

            case 7:
                better = calc.over_count < best.over_count || calc.over_noise < best.over_noise;
                break;
            }

            if (best.over_count == 0)
            {
                better = better && calc.bits < best.bits;
            }

            return(better);
        }
Beispiel #21
0
        private void amp_scalefac_bands(
            LameGlobalFlags gfp,
            GrInfo cod_info,
            float[] distort,
            float[] xrpow,
            bool bRefine)
        {
            var   gfc = gfp.internal_flags;
            float ifqstep34;

            if (cod_info.scalefac_scale == 0)
            {
                ifqstep34 = 1.29683955465100964055f;
            }
            else
            {
                ifqstep34 = 1.68179283050742922612f;
            }

            float trigger = 0;

            for (var sfb = 0; sfb < cod_info.sfbmax; sfb++)
            {
                if (trigger < distort[sfb])
                {
                    trigger = distort[sfb];
                }
            }

            var noise_shaping_amp = gfc.noise_shaping_amp;

            if (noise_shaping_amp == 3)
            {
                if (bRefine)
                {
                    noise_shaping_amp = 2;
                }
                else
                {
                    noise_shaping_amp = 1;
                }
            }

            switch (noise_shaping_amp)
            {
            case 2:
                break;

            case 1:
                if (trigger > 1.0)
                {
                    trigger = (float)Math.Pow(trigger, .5);
                }
                else
                {
                    trigger = (float)(trigger * .95);
                }

                break;

            case 0:
            default:
                if (trigger > 1.0)
                {
                    trigger = 1.0f;
                }
                else
                {
                    trigger = (float)(trigger * .95);
                }

                break;
            }

            var j = 0;

            for (var sfb = 0; sfb < cod_info.sfbmax; sfb++)
            {
                var width = cod_info.width[sfb];
                int l;
                j += width;
                if (distort[sfb] < trigger)
                {
                    continue;
                }

                if ((gfc.substep_shaping & 2) != 0)
                {
                    gfc.pseudohalf[sfb] = 0 == gfc.pseudohalf[sfb] ? 1 : 0;
                    if (0 == gfc.pseudohalf[sfb] && gfc.noise_shaping_amp == 2)
                    {
                        return;
                    }
                }

                cod_info.scalefac[sfb]++;
                for (l = -width; l < 0; l++)
                {
                    xrpow[j + l] *= ifqstep34;
                    if (xrpow[j + l] > cod_info.xrpow_max)
                    {
                        cod_info.xrpow_max = xrpow[j + l];
                    }
                }

                if (gfc.noise_shaping_amp == 2)
                {
                    return;
                }
            }
        }
Beispiel #22
0
        internal int outer_loop(
            LameGlobalFlags gfp,
            GrInfo cod_info,
            float[] l3_xmin,
            float[] xrpow,
            int ch,
            int targ_bits)
        {
            var gfc             = gfp.internal_flags;
            var cod_info_w      = new GrInfo();
            var save_xrpow      = new float[576];
            var distort         = new float[L3Side.SFBMAX];
            var best_noise_info = new CalcNoiseResult();
            int better;
            var prev_noise          = new CalcNoiseData();
            var best_part2_3_length = 9999999;
            var bEndOfSearch        = false;
            var bRefine             = false;
            var best_ggain_pass1    = 0;

            bin_search_StepSize(gfc, cod_info, targ_bits, ch, xrpow);
            if (0 == gfc.noise_shaping)
            {
                return(100);
            }

            qupvt.calc_noise(cod_info, l3_xmin, distort, best_noise_info, prev_noise);
            best_noise_info.bits = cod_info.part2_3_length;
            cod_info_w.assign(cod_info);
            var age = 0;

            Array.Copy(xrpow, 0, save_xrpow, 0, 576);
            while (!bEndOfSearch)
            {
                do
                {
                    var noise_info = new CalcNoiseResult();
                    int search_limit;
                    var maxggain = 255;
                    if ((gfc.substep_shaping & 2) != 0)
                    {
                        search_limit = 20;
                    }
                    else
                    {
                        search_limit = 3;
                    }

                    if (gfc.sfb21_extra)
                    {
                        if (distort[cod_info_w.sfbmax] > 1.0)
                        {
                            break;
                        }

                        if (cod_info_w.block_type == Encoder.SHORT_TYPE &&
                            (distort[cod_info_w.sfbmax + 1] > 1.0 || distort[cod_info_w.sfbmax + 2] > 1.0))
                        {
                            break;
                        }
                    }

                    if (!balance_noise(gfp, cod_info_w, distort, xrpow, bRefine))
                    {
                        break;
                    }

                    if (cod_info_w.scalefac_scale != 0)
                    {
                        maxggain = 254;
                    }

                    var huff_bits = targ_bits - cod_info_w.part2_length;
                    if (huff_bits <= 0)
                    {
                        break;
                    }

                    while ((cod_info_w.part2_3_length = tk.count_bits(gfc, xrpow, cod_info_w, prev_noise)) >
                           huff_bits && cod_info_w.global_gain <= maxggain)
                    {
                        cod_info_w.global_gain++;
                    }

                    if (cod_info_w.global_gain > maxggain)
                    {
                        break;
                    }

                    if (best_noise_info.over_count == 0)
                    {
                        while ((cod_info_w.part2_3_length = tk.count_bits(gfc, xrpow, cod_info_w, prev_noise)) >
                               best_part2_3_length && cod_info_w.global_gain <= maxggain)
                        {
                            cod_info_w.global_gain++;
                        }

                        if (cod_info_w.global_gain > maxggain)
                        {
                            break;
                        }
                    }

                    qupvt.calc_noise(cod_info_w, l3_xmin, distort, noise_info, prev_noise);
                    noise_info.bits = cod_info_w.part2_3_length;
                    if (cod_info.block_type != Encoder.SHORT_TYPE)
                    {
                        better = gfp.quant_comp;
                    }
                    else
                    {
                        better = gfp.quant_comp_short;
                    }

                    better = quant_compare(better, best_noise_info, noise_info, cod_info_w, distort) ? 1 : 0;
                    if (better != 0)
                    {
                        best_part2_3_length = cod_info.part2_3_length;
                        best_noise_info     = noise_info;
                        cod_info.assign(cod_info_w);
                        age = 0;
                        Array.Copy(xrpow, 0, save_xrpow, 0, 576);
                    }
                    else
                    {
                        if (gfc.full_outer_loop == 0)
                        {
                            if (++age > search_limit && best_noise_info.over_count == 0)
                            {
                                break;
                            }

                            if (gfc.noise_shaping_amp == 3 && bRefine && age > 30)
                            {
                                break;
                            }

                            if (gfc.noise_shaping_amp == 3 && bRefine &&
                                cod_info_w.global_gain - best_ggain_pass1 > 15)
                            {
                                break;
                            }
                        }
                    }
                }while (cod_info_w.global_gain + cod_info_w.scalefac_scale < 255);

                if (gfc.noise_shaping_amp == 3)
                {
                    if (!bRefine)
                    {
                        cod_info_w.assign(cod_info);
                        Array.Copy(save_xrpow, 0, xrpow, 0, 576);
                        age = 0;
                        best_ggain_pass1 = cod_info_w.global_gain;
                        bRefine          = true;
                    }
                    else
                    {
                        bEndOfSearch = true;
                    }
                }
                else
                {
                    bEndOfSearch = true;
                }
            }

            Debug.Assert(cod_info.global_gain + cod_info.scalefac_scale <= 255);
            if (gfp.VBR == VbrMode.vbr_rh || gfp.VBR == VbrMode.vbr_mtrh)
            {
                Array.Copy(save_xrpow, 0, xrpow, 0, 576);
            }
            else if ((gfc.substep_shaping & 1) != 0)
            {
                trancate_smallspectrums(gfc, cod_info, l3_xmin, xrpow);
            }

            return(best_noise_info.over_count);
        }
Beispiel #23
0
        /// <summary>
        ///     Implements the pseudocode of page 98 of the IS
        /// </summary>
        private int Huffmancode(LameInternalFlags gfc, int tableindex, int start, int end, GrInfo gi)
        {
            var h    = Tables.ht[tableindex];
            var bits = 0;

            Debug.Assert(tableindex < 32);
            if (0 == tableindex)
            {
                return(bits);
            }

            for (var i = start; i < end; i += 2)
            {
                var cbits = 0;
                var xbits = 0;

                var linbits = h.xlen;
                var xlen    = h.xlen;
                var ext     = 0;
                var x1      = gi.l3_enc[i];
                var x2      = gi.l3_enc[i + 1];

                if (x1 != 0)
                {
                    if (gi.xr[i] < 0)
                    {
                        ext++;
                    }

                    cbits--;
                }

                if (tableindex > 15)
                {
                    /* use ESC-words */
                    if (x1 > 14)
                    {
                        var linbits_x1 = x1 - 15;
                        Debug.Assert(linbits_x1 <= h.linmax);
                        ext  |= linbits_x1 << 1;
                        xbits = linbits;
                        x1    = 15;
                    }

                    if (x2 > 14)
                    {
                        var linbits_x2 = x2 - 15;
                        Debug.Assert(linbits_x2 <= h.linmax);
                        ext  <<= linbits;
                        ext   |= linbits_x2;
                        xbits += linbits;
                        x2     = 15;
                    }

                    xlen = 16;
                }

                if (x2 != 0)
                {
                    ext <<= 1;
                    if (gi.xr[i + 1] < 0)
                    {
                        ext++;
                    }

                    cbits--;
                }

                Debug.Assert((x1 | x2) < 16);

                x1     = x1 * xlen + x2;
                xbits -= cbits;
                cbits += h.hlen[x1];

                Debug.Assert(cbits <= MAX_LENGTH);
                Debug.Assert(xbits <= MAX_LENGTH);

                putbits2(gfc, h.table[x1], cbits);
                putbits2(gfc, ext, xbits);
                bits += cbits + xbits;
            }

            return(bits);
        }
Beispiel #24
0
        internal void init_outer_loop(LameInternalFlags gfc, GrInfo cod_info)
        {
            cod_info.part2_3_length     = 0;
            cod_info.big_values         = 0;
            cod_info.count1             = 0;
            cod_info.global_gain        = 210;
            cod_info.scalefac_compress  = 0;
            cod_info.table_select[0]    = 0;
            cod_info.table_select[1]    = 0;
            cod_info.table_select[2]    = 0;
            cod_info.subblock_gain[0]   = 0;
            cod_info.subblock_gain[1]   = 0;
            cod_info.subblock_gain[2]   = 0;
            cod_info.subblock_gain[3]   = 0;
            cod_info.region0_count      = 0;
            cod_info.region1_count      = 0;
            cod_info.preflag            = 0;
            cod_info.scalefac_scale     = 0;
            cod_info.count1table_select = 0;
            cod_info.part2_length       = 0;
            cod_info.sfb_lmax           = Encoder.SBPSY_l;
            cod_info.sfb_smin           = Encoder.SBPSY_s;
            cod_info.psy_lmax           = gfc.sfb21_extra ? Encoder.SBMAX_l : Encoder.SBPSY_l;
            cod_info.psymax             = cod_info.psy_lmax;
            cod_info.sfbmax             = cod_info.sfb_lmax;
            cod_info.sfbdivide          = 11;
            for (var sfb = 0; sfb < Encoder.SBMAX_l; sfb++)
            {
                cod_info.width[sfb]  = gfc.scalefac_band.l[sfb + 1] - gfc.scalefac_band.l[sfb];
                cod_info.window[sfb] = 3;
            }

            if (cod_info.block_type == Encoder.SHORT_TYPE)
            {
                var ixwork = new float[576];
                cod_info.sfb_smin = 0;
                cod_info.sfb_lmax = 0;
                if (cod_info.mixed_block_flag != 0)
                {
                    cod_info.sfb_smin = 3;
                    cod_info.sfb_lmax = gfc.mode_gr * 2 + 4;
                }

                cod_info.psymax = cod_info.sfb_lmax +
                                  3 * ((gfc.sfb21_extra ? Encoder.SBMAX_s : Encoder.SBPSY_s) - cod_info.sfb_smin);
                cod_info.sfbmax    = cod_info.sfb_lmax + 3 * (Encoder.SBPSY_s - cod_info.sfb_smin);
                cod_info.sfbdivide = cod_info.sfbmax - 18;
                cod_info.psy_lmax  = cod_info.sfb_lmax;
                var ix = gfc.scalefac_band.l[cod_info.sfb_lmax];
                Array.Copy(cod_info.xr, 0, ixwork, 0, 576);
                for (var sfb = cod_info.sfb_smin; sfb < Encoder.SBMAX_s; sfb++)
                {
                    var start = gfc.scalefac_band.s[sfb];

                    var end = gfc.scalefac_band.s[sfb + 1];
                    for (var window = 0; window < 3; window++)
                    {
                        for (var l = start; l < end; l++)
                        {
                            cod_info.xr[ix++] = ixwork[3 * l + window];
                        }
                    }
                }

                var j = cod_info.sfb_lmax;
                for (var sfb = cod_info.sfb_smin; sfb < Encoder.SBMAX_s; sfb++)
                {
                    cod_info.width[j]         = cod_info.width[j + 1] =
                        cod_info.width[j + 2] = gfc.scalefac_band.s[sfb + 1] - gfc.scalefac_band.s[sfb];
                    cod_info.window[j]        = 0;
                    cod_info.window[j + 1]    = 1;
                    cod_info.window[j + 2]    = 2;
                    j += 3;
                }
            }

            cod_info.count1bits          = 0;
            cod_info.sfb_partition_table = qupvt.nr_of_sfb_block[0][0];
            cod_info.slen[0]             = 0;
            cod_info.slen[1]             = 0;
            cod_info.slen[2]             = 0;
            cod_info.slen[3]             = 0;
            cod_info.max_nonzero_coeff   = 575;
            Arrays.Fill(cod_info.scalefac, 0);
            psfb21_analogsilence(gfc, cod_info);
        }
Beispiel #25
0
        internal void VBR_encode_granule(
            LameGlobalFlags gfp,
            GrInfo cod_info,
            float[] l3_xmin,
            float[] xrpow,
            int ch,
            int min_bits,
            int max_bits)
        {
            var gfc          = gfp.internal_flags;
            var bst_cod_info = new GrInfo();
            var bst_xrpow    = new float[576];

            var Max_bits = max_bits;
            var real_bits = max_bits + 1;
            var this_bits = (max_bits + min_bits) / 2;
            int dbits, over, found = 0;

            var sfb21_extra = gfc.sfb21_extra;

            Debug.Assert(Max_bits <= LameInternalFlags.MAX_BITS_PER_CHANNEL);
            Arrays.Fill(bst_cod_info.l3_enc, 0);
            do
            {
                Debug.Assert(this_bits >= min_bits);
                Debug.Assert(this_bits <= max_bits);
                Debug.Assert(min_bits <= max_bits);
                if (this_bits > Max_bits - 42)
                {
                    gfc.sfb21_extra = false;
                }
                else
                {
                    gfc.sfb21_extra = sfb21_extra;
                }

                over = outer_loop(gfp, cod_info, l3_xmin, xrpow, ch, this_bits);
                if (over <= 0)
                {
                    found     = 1;
                    real_bits = cod_info.part2_3_length;
                    bst_cod_info.assign(cod_info);
                    Array.Copy(xrpow, 0, bst_xrpow, 0, 576);
                    max_bits  = real_bits - 32;
                    dbits     = max_bits - min_bits;
                    this_bits = (max_bits + min_bits) / 2;
                }
                else
                {
                    min_bits  = this_bits + 32;
                    dbits     = max_bits - min_bits;
                    this_bits = (max_bits + min_bits) / 2;
                    if (found != 0)
                    {
                        found = 2;
                        cod_info.assign(bst_cod_info);
                        Array.Copy(bst_xrpow, 0, xrpow, 0, 576);
                    }
                }
            }while (dbits > 12);

            gfc.sfb21_extra = sfb21_extra;
            if (found == 2)
            {
                Array.Copy(bst_cod_info.l3_enc, 0, cod_info.l3_enc, 0, 576);
            }

            Debug.Assert(cod_info.part2_3_length <= Max_bits);
        }
        protected internal virtual void set_subblock_gain(GrInfo cod_info, int[] mingain_s, int[] sf)
        {
            const int maxrange1 = 15, maxrange2 = 7;

            var ifqstepShift = cod_info.scalefac_scale == 0 ? 1 : 2;
            var sbg          = cod_info.subblock_gain;

            var psymax = cod_info.psymax;
            var psydiv = 18;
            int sbg0, sbg1, sbg2;
            int sfb;
            var min_sbg = 7;

            if (psydiv > psymax)
            {
                psydiv = psymax;
            }

            for (var i = 0; i < 3; ++i)
            {
                int maxsf1 = 0, maxsf2 = 0, minsf = 1000;
                /* see if we should use subblock gain */
                for (sfb = i; sfb < psydiv; sfb += 3)
                {
                    /* part 1 */

                    var v = -sf[sfb];
                    if (maxsf1 < v)
                    {
                        maxsf1 = v;
                    }

                    if (minsf > v)
                    {
                        minsf = v;
                    }
                }

                for (; sfb < L3Side.SFBMAX; sfb += 3)
                {
                    /* part 2 */

                    var v = -sf[sfb];
                    if (maxsf2 < v)
                    {
                        maxsf2 = v;
                    }

                    if (minsf > v)
                    {
                        minsf = v;
                    }
                }

                /*
                 * boost subblock gain as little as possible so we can reach maxsf1
                 * with scalefactors 8*sbg >= maxsf1
                 */
                {
                    var m1 = maxsf1 - (maxrange1 << ifqstepShift);

                    var m2 = maxsf2 - (maxrange2 << ifqstepShift);
                    maxsf1 = Math.Max(m1, m2);
                }
                if (minsf > 0)
                {
                    sbg[i] = minsf >> 3;
                }
                else
                {
                    sbg[i] = 0;
                }

                if (maxsf1 > 0)
                {
                    var m1 = sbg[i];

                    var m2 = (maxsf1 + 7) >> 3;
                    sbg[i] = Math.Max(m1, m2);
                }

                if (sbg[i] > 0 && mingain_s[i] > cod_info.global_gain - sbg[i] * 8)
                {
                    sbg[i] = (cod_info.global_gain - mingain_s[i]) >> 3;
                }

                if (sbg[i] > 7)
                {
                    sbg[i] = 7;
                }

                if (min_sbg > sbg[i])
                {
                    min_sbg = sbg[i];
                }
            }

            sbg0 = sbg[0] * 8;
            sbg1 = sbg[1] * 8;
            sbg2 = sbg[2] * 8;
            for (sfb = 0; sfb < L3Side.SFBMAX; sfb += 3)
            {
                sf[sfb + 0] += sbg0;
                sf[sfb + 1] += sbg1;
                sf[sfb + 2] += sbg2;
            }

            if (min_sbg > 0)
            {
                for (var i = 0; i < 3; ++i)
                {
                    sbg[i] -= min_sbg;
                }

                cod_info.global_gain -= min_sbg * 8;
            }
        }
Beispiel #27
0
        private void psfb21_analogsilence(LameInternalFlags gfc, GrInfo cod_info)
        {
            var ath = gfc.ATH;

            var xr = cod_info.xr;

            if (cod_info.block_type != Encoder.SHORT_TYPE)
            {
                var stop = false;
                for (var gsfb = Encoder.PSFB21 - 1; gsfb >= 0 && !stop; gsfb--)
                {
                    var start = gfc.scalefac_band.psfb21[gsfb];

                    var end   = gfc.scalefac_band.psfb21[gsfb + 1];
                    var ath21 = qupvt.athAdjust(ath.adjust, ath.psfb21[gsfb], ath.floor);
                    if (gfc.nsPsy.longfact[21] > 1e-12f)
                    {
                        ath21 *= gfc.nsPsy.longfact[21];
                    }

                    for (var j = end - 1; j >= start; j--)
                    {
                        if (Math.Abs(xr[j]) < ath21)
                        {
                            xr[j] = 0;
                        }
                        else
                        {
                            stop = true;
                            break;
                        }
                    }
                }
            }
            else
            {
                for (var block = 0; block < 3; block++)
                {
                    var stop = false;
                    for (var gsfb = Encoder.PSFB12 - 1; gsfb >= 0 && !stop; gsfb--)
                    {
                        var start = gfc.scalefac_band.s[12] * 3 +
                                    (gfc.scalefac_band.s[13] - gfc.scalefac_band.s[12]) * block +
                                    (gfc.scalefac_band.psfb12[gsfb] - gfc.scalefac_band.psfb12[0]);

                        var end   = start + (gfc.scalefac_band.psfb12[gsfb + 1] - gfc.scalefac_band.psfb12[gsfb]);
                        var ath12 = qupvt.athAdjust(ath.adjust, ath.psfb12[gsfb], ath.floor);
                        if (gfc.nsPsy.shortfact[12] > 1e-12f)
                        {
                            ath12 *= gfc.nsPsy.shortfact[12];
                        }

                        for (var j = end - 1; j >= start; j--)
                        {
                            if (Math.Abs(xr[j]) < ath12)
                            {
                                xr[j] = 0;
                            }
                            else
                            {
                                stop = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
Beispiel #28
0
        private int huffman_coder_count1(LameInternalFlags gfc, GrInfo gi)
        {
            /* Write count1 area */

            var h = Tables.ht[gi.count1table_select + 32];
            int i, bits = 0;

            var ix = gi.big_values;
            var xr = gi.big_values;

            Debug.Assert(gi.count1table_select < 2);

            for (i = (gi.count1 - gi.big_values) / 4; i > 0; --i)
            {
                var huffbits = 0;
                int p = 0, v;

                v = gi.l3_enc[ix + 0];
                if (v != 0)
                {
                    p += 8;
                    if (gi.xr[xr + 0] < 0)
                    {
                        huffbits++;
                    }

                    Debug.Assert(v <= 1);
                }

                v = gi.l3_enc[ix + 1];
                if (v != 0)
                {
                    p        += 4;
                    huffbits *= 2;
                    if (gi.xr[xr + 1] < 0)
                    {
                        huffbits++;
                    }

                    Debug.Assert(v <= 1);
                }

                v = gi.l3_enc[ix + 2];
                if (v != 0)
                {
                    p        += 2;
                    huffbits *= 2;
                    if (gi.xr[xr + 2] < 0)
                    {
                        huffbits++;
                    }

                    Debug.Assert(v <= 1);
                }

                v = gi.l3_enc[ix + 3];
                if (v != 0)
                {
                    p++;
                    huffbits *= 2;
                    if (gi.xr[xr + 3] < 0)
                    {
                        huffbits++;
                    }

                    Debug.Assert(v <= 1);
                }

                ix += 4;
                xr += 4;
                putbits2(gfc, huffbits + h.table[p], h.hlen[p]);
                bits += h.hlen[p];
            }

            return(bits);
        }