Пример #1
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);
        }
Пример #2
0
        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;
        }
Пример #3
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);
        }
Пример #4
0
        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);
        }