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