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); }
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; }
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); }
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); }
internal IIISideInfo() { for (var gr = 0; gr < 2; gr++) { for (var ch = 0; ch < 2; ch++) { tt[gr][ch] = new GrInfo(); } } }
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 } }
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); }
/// <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); }
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); }
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; }
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); }
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); }
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); }
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); }
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; } } }
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); }
/// <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); }
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); }
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; } }
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; } } } } } }
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); }