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); }
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); }