private int tryGlobalStepsize(algo_t that, int[] sfwork, int[] vbrsfmin, int delta) { var xrpow_max = that.cod_info.xrpow_max; var sftemp = new int[L3Side.SFBMAX]; int nbits; var vbrmax = 0; for (var i = 0; i < L3Side.SFBMAX; ++i) { var gain = sfwork[i] + delta; if (gain < vbrsfmin[i]) { gain = vbrsfmin[i]; } if (gain > 255) { gain = 255; } if (vbrmax < gain) { vbrmax = gain; } sftemp[i] = gain; } that.alloc.alloc(that, sftemp, vbrsfmin, vbrmax); bitcount(that); nbits = quantizeAndCountBits(that); that.cod_info.xrpow_max = xrpow_max; return(nbits); }
private int tryThatOne(algo_t that, int[] sftemp, int[] vbrsfmin, int vbrmax) { var xrpow_max = that.cod_info.xrpow_max; var nbits = QuantizePVT.LARGE_BITS; that.alloc.alloc(that, sftemp, vbrsfmin, vbrmax); bitcount(that); nbits = quantizeAndCountBits(that); nbits += that.cod_info.part2_length; that.cod_info.xrpow_max = xrpow_max; return(nbits); }
private void bitcount(algo_t that) { bool rc; if (that.gfc.mode_gr == 2) { rc = tak.scale_bitcount(that.cod_info); } else { rc = tak.scale_bitcount_lsf(that.gfc, that.cod_info); } if (!rc) { return; } /* this should not happen due to the way the scalefactors are selected */ throw new Exception("INTERNAL ERROR IN VBR NEW CODE (986), please send bug report"); }
private void searchGlobalStepsizeMax(algo_t that, int[] sfwork, int[] vbrsfmin, int target) { var cod_info = that.cod_info; var gain = cod_info.global_gain; var curr = gain; var gain_ok = 1024; var nbits = QuantizePVT.LARGE_BITS; int l = gain, r = 512; Debug.Assert(gain >= 0); while (l <= r) { curr = (l + r) >> 1; nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); if (nbits == 0 || nbits + cod_info.part2_length < target) { r = curr - 1; gain_ok = curr; } else { l = curr + 1; if (gain_ok == 1024) { gain_ok = curr; } } } if (gain_ok != curr) { curr = gain_ok; nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); } }
private void outOfBitsStrategy(algo_t that, int[] sfwork, int[] vbrsfmin, int target) { var wrk = new int[L3Side.SFBMAX]; var dm = sfDepth(sfwork); var p = that.cod_info.global_gain; /* PART 1 */ { var bi = dm / 2; var bi_ok = -1; var bu = 0; var bo = dm; for (;;) { var sfmax = flattenDistribution(sfwork, wrk, dm, bi, p); var nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); if (nbits <= target) { bi_ok = bi; bo = bi - 1; } else { bu = bi + 1; } if (bu <= bo) { bi = (bu + bo) / 2; } else { break; } } if (bi_ok >= 0) { if (bi != bi_ok) { var sfmax = flattenDistribution(sfwork, wrk, dm, bi_ok, p); tryThatOne(that, wrk, vbrsfmin, sfmax); } return; } } /* PART 2: */ { var bi = (255 + p) / 2; var bi_ok = -1; var bu = p; var bo = 255; for (;;) { var sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi); var nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); if (nbits <= target) { bi_ok = bi; bo = bi - 1; } else { bu = bi + 1; } if (bu <= bo) { bi = (bu + bo) / 2; } else { break; } } if (bi_ok >= 0) { if (bi != bi_ok) { var sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi_ok); tryThatOne(that, wrk, vbrsfmin, sfmax); } return; } } /* fall back to old code, likely to be never called */ searchGlobalStepsizeMax(that, wrk, vbrsfmin, target); }
private int quantizeAndCountBits(algo_t that) { quantize_x34(that); that.cod_info.part2_3_length = tak.noquant_count_bits(that.gfc, that.cod_info, null); return(that.cod_info.part2_3_length); }
/// <summary> /// quantize xr34 based on scalefactors /// block_xr34 /// @author Mark Taylor 2000-??-?? /// @author Robert Hegemann 2000-10-20 made functions of them /// </summary> private void quantize_x34(algo_t that) { var x = new double[4]; var xr34_orig = 0; var cod_info = that.cod_info; var ifqstep = cod_info.scalefac_scale == 0 ? 2 : 4; var l3 = 0; int j = 0, sfb = 0; var max_nonzero_coeff = cod_info.max_nonzero_coeff; Debug.Assert(cod_info.max_nonzero_coeff >= 0); Debug.Assert(cod_info.max_nonzero_coeff < 576); while (j <= max_nonzero_coeff) { var s = (cod_info.scalefac[sfb] + (cod_info.preflag != 0 ? qupvt.pretab[sfb] : 0)) * ifqstep + cod_info.subblock_gain[cod_info.window[sfb]] * 8; var sfac = cod_info.global_gain - s; var sfpow34 = qupvt.ipow20[sfac]; var w = cod_info.width[sfb]; var m = max_nonzero_coeff - j + 1; var l = w; int remaining; Debug.Assert(cod_info.global_gain - s >= 0); Debug.Assert(cod_info.width[sfb] >= 0); if (l > m) { l = m; } j += w; ++sfb; l >>= 1; remaining = l & 1; for (l >>= 1; l > 0; --l) { x[0] = sfpow34 * that.xr34orig[xr34_orig + 0]; x[1] = sfpow34 * that.xr34orig[xr34_orig + 1]; x[2] = sfpow34 * that.xr34orig[xr34_orig + 2]; x[3] = sfpow34 * that.xr34orig[xr34_orig + 3]; k_34_4(x, cod_info.l3_enc, l3); l3 += 4; xr34_orig += 4; } if (remaining != 0) { x[0] = sfpow34 * that.xr34orig[xr34_orig + 0]; x[1] = sfpow34 * that.xr34orig[xr34_orig + 1]; k_34_2(x, cod_info.l3_enc, l3); l3 += 2; xr34_orig += 2; } } }
/// <summary> /// calc_short_block_vbr_sf(), calc_long_block_vbr_sf() /// a variation for vbr-mtrh /// @author Mark Taylor 2000-??-?? /// @author Robert Hegemann 2000-10-25 made functions of it /// </summary> private int block_sf(algo_t that, float[] l3_xmin, int[] vbrsf, int[] vbrsfmin) { float max_xr34; var xr = that.cod_info.xr; var xr34_orig = that.xr34orig; var width = that.cod_info.width; var max_nonzero_coeff = that.cod_info.max_nonzero_coeff; var maxsf = 0; var sfb = 0; int j = 0, i = 0; var psymax = that.cod_info.psymax; Debug.Assert(that.cod_info.max_nonzero_coeff >= 0); that.mingain_l = 0; that.mingain_s[0] = 0; that.mingain_s[1] = 0; that.mingain_s[2] = 0; while (j <= max_nonzero_coeff) { var w = width[sfb]; var m = max_nonzero_coeff - j + 1; var l = w; int m1, m2; if (l > m) { l = m; } max_xr34 = max_x34(xr34_orig, j, l); m1 = findLowestScalefac(max_xr34); vbrsfmin[sfb] = m1; if (that.mingain_l < m1) { that.mingain_l = m1; } if (that.mingain_s[i] < m1) { that.mingain_s[i] = m1; } if (++i > 2) { i = 0; } if (sfb < psymax) { if (belowNoiseFloor(xr, j, l3_xmin[sfb], l) == 0) { m2 = find_scalefac_x34(xr, xr34_orig, j, l3_xmin[sfb], l, m1); if (maxsf < m2) { maxsf = m2; } } else { m2 = 255; maxsf = 255; } } else { if (maxsf < m1) { maxsf = m1; } m2 = maxsf; } vbrsf[sfb] = m2; ++sfb; j += w; } for (; sfb < L3Side.SFBMAX; ++sfb) { vbrsf[sfb] = maxsf; vbrsfmin[sfb] = 0; } return(maxsf); }
internal virtual int VBR_encode_frame( LameInternalFlags gfc, float[][][] xr34orig, float[][][] l3_xmin, int[][] max_bits) { var sfwork_ = Arrays.ReturnRectangularArray <int>(2, 2, L3Side.SFBMAX); var vbrsfmin_ = Arrays.ReturnRectangularArray <int>(2, 2, L3Side.SFBMAX); var that_ = Arrays.ReturnRectangularArray <algo_t>(2, 2); var ngr = gfc.mode_gr; var nch = gfc.channels_out; var max_nbits_ch = Arrays.ReturnRectangularArray <int>(2, 2); var max_nbits_gr = new int[2]; var max_nbits_fr = 0; var use_nbits_ch = Arrays.ReturnRectangularArray <int>(2, 2); var use_nbits_gr = new int[2]; var use_nbits_fr = 0; /* * set up some encoding parameters */ for (var gr = 0; gr < ngr; ++gr) { max_nbits_gr[gr] = 0; for (var ch = 0; ch < nch; ++ch) { max_nbits_ch[gr][ch] = max_bits[gr][ch]; use_nbits_ch[gr][ch] = 0; max_nbits_gr[gr] += max_bits[gr][ch]; max_nbits_fr += max_bits[gr][ch]; that_[gr][ch] = new algo_t(); that_[gr][ch].gfc = gfc; that_[gr][ch].cod_info = gfc.l3_side.tt[gr][ch]; that_[gr][ch].xr34orig = xr34orig[gr][ch]; if (that_[gr][ch].cod_info.block_type == Encoder.SHORT_TYPE) { that_[gr][ch].alloc = new ShortBlockConstrain(this); } else { that_[gr][ch].alloc = new LongBlockConstrain(this); } } // for ch } /* * searches scalefactors */ for (var gr = 0; gr < ngr; ++gr) { for (var ch = 0; ch < nch; ++ch) { if (max_bits[gr][ch] > 0) { var that = that_[gr][ch]; var sfwork = sfwork_[gr][ch]; var vbrsfmin = vbrsfmin_[gr][ch]; int vbrmax; vbrmax = block_sf(that, l3_xmin[gr][ch], sfwork, vbrsfmin); that.alloc.alloc(that, sfwork, vbrsfmin, vbrmax); bitcount(that); } } } /* * encode 'as is' */ use_nbits_fr = 0; for (var gr = 0; gr < ngr; ++gr) { use_nbits_gr[gr] = 0; for (var ch = 0; ch < nch; ++ch) { var that = that_[gr][ch]; if (max_bits[gr][ch] > 0) { var max_nonzero_coeff = that.cod_info.max_nonzero_coeff; Debug.Assert(max_nonzero_coeff < 576); Arrays.Fill(that.cod_info.l3_enc, max_nonzero_coeff, 576, 0); quantizeAndCountBits(that); } use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); use_nbits_gr[gr] += use_nbits_ch[gr][ch]; } // for ch use_nbits_fr += use_nbits_gr[gr]; } /* * check bit constrains */ if (use_nbits_fr <= max_nbits_fr) { var ok = true; for (var gr = 0; gr < ngr; ++gr) { if (use_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE) { ok = false; } for (var ch = 0; ch < nch; ++ch) { if (use_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { ok = false; } } } if (ok) { return(use_nbits_fr); } } /* * OK, we are in trouble and have to define how many bits are to be used * for each granule */ { var ok = true; var sum_fr = 0; for (var gr = 0; gr < ngr; ++gr) { max_nbits_gr[gr] = 0; for (var ch = 0; ch < nch; ++ch) { if (use_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { max_nbits_ch[gr][ch] = LameInternalFlags.MAX_BITS_PER_CHANNEL; } else { max_nbits_ch[gr][ch] = use_nbits_ch[gr][ch]; } max_nbits_gr[gr] += max_nbits_ch[gr][ch]; } if (max_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE) { var f = new float[2]; float s = 0; for (var ch = 0; ch < nch; ++ch) { if (max_nbits_ch[gr][ch] > 0) { f[ch] = (float)Math.Sqrt(Math.Sqrt(max_nbits_ch[gr][ch])); s += f[ch]; } else { f[ch] = 0; } } for (var ch = 0; ch < nch; ++ch) { if (s > 0) { max_nbits_ch[gr][ch] = (int)(LameInternalFlags.MAX_BITS_PER_GRANULE * f[ch] / s); } else { max_nbits_ch[gr][ch] = 0; } } if (nch > 1) { if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; } if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; } if (max_nbits_ch[gr][0] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { max_nbits_ch[gr][0] = LameInternalFlags.MAX_BITS_PER_CHANNEL; } if (max_nbits_ch[gr][1] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { max_nbits_ch[gr][1] = LameInternalFlags.MAX_BITS_PER_CHANNEL; } } max_nbits_gr[gr] = 0; for (var ch = 0; ch < nch; ++ch) { max_nbits_gr[gr] += max_nbits_ch[gr][ch]; } } sum_fr += max_nbits_gr[gr]; } if (sum_fr > max_nbits_fr) { { var f = new float[2]; float s = 0; for (var gr = 0; gr < ngr; ++gr) { if (max_nbits_gr[gr] > 0) { f[gr] = (float)Math.Sqrt(max_nbits_gr[gr]); s += f[gr]; } else { f[gr] = 0; } } for (var gr = 0; gr < ngr; ++gr) { if (s > 0) { max_nbits_gr[gr] = (int)(max_nbits_fr * f[gr] / s); } else { max_nbits_gr[gr] = 0; } } } if (ngr > 1) { if (max_nbits_gr[0] > use_nbits_gr[0] + 125) { max_nbits_gr[1] += max_nbits_gr[0]; max_nbits_gr[1] -= use_nbits_gr[0] + 125; max_nbits_gr[0] = use_nbits_gr[0] + 125; } if (max_nbits_gr[1] > use_nbits_gr[1] + 125) { max_nbits_gr[0] += max_nbits_gr[1]; max_nbits_gr[0] -= use_nbits_gr[1] + 125; max_nbits_gr[1] = use_nbits_gr[1] + 125; } for (var gr = 0; gr < ngr; ++gr) { if (max_nbits_gr[gr] > LameInternalFlags.MAX_BITS_PER_GRANULE) { max_nbits_gr[gr] = LameInternalFlags.MAX_BITS_PER_GRANULE; } } } for (var gr = 0; gr < ngr; ++gr) { var f = new float[2]; float s = 0; for (var ch = 0; ch < nch; ++ch) { if (max_nbits_ch[gr][ch] > 0) { f[ch] = (float)Math.Sqrt(max_nbits_ch[gr][ch]); s += f[ch]; } else { f[ch] = 0; } } for (var ch = 0; ch < nch; ++ch) { if (s > 0) { max_nbits_ch[gr][ch] = (int)(max_nbits_gr[gr] * f[ch] / s); } else { max_nbits_ch[gr][ch] = 0; } } if (nch > 1) { if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; } if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; } for (var ch = 0; ch < nch; ++ch) { if (max_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { max_nbits_ch[gr][ch] = LameInternalFlags.MAX_BITS_PER_CHANNEL; } } } } } /* sanity check */ sum_fr = 0; for (var gr = 0; gr < ngr; ++gr) { var sum_gr = 0; for (var ch = 0; ch < nch; ++ch) { sum_gr += max_nbits_ch[gr][ch]; if (max_nbits_ch[gr][ch] > LameInternalFlags.MAX_BITS_PER_CHANNEL) { ok = false; } } sum_fr += sum_gr; if (sum_gr > LameInternalFlags.MAX_BITS_PER_GRANULE) { ok = false; } } if (sum_fr > max_nbits_fr) { ok = false; } if (!ok) { for (var gr = 0; gr < ngr; ++gr) { for (var ch = 0; ch < nch; ++ch) { max_nbits_ch[gr][ch] = max_bits[gr][ch]; } } } } /* we already called the 'best_scalefac_store' function, so we need to reset some variables before we can do it again. */ for (var ch = 0; ch < nch; ++ch) { gfc.l3_side.scfsi[ch][0] = 0; gfc.l3_side.scfsi[ch][1] = 0; gfc.l3_side.scfsi[ch][2] = 0; gfc.l3_side.scfsi[ch][3] = 0; } for (var gr = 0; gr < ngr; ++gr) { for (var ch = 0; ch < nch; ++ch) { gfc.l3_side.tt[gr][ch].scalefac_compress = 0; } } /* alter our encoded data, until it fits into the target bitrate */ use_nbits_fr = 0; for (var gr = 0; gr < ngr; ++gr) { use_nbits_gr[gr] = 0; for (var ch = 0; ch < nch; ++ch) { var that = that_[gr][ch]; use_nbits_ch[gr][ch] = 0; if (max_bits[gr][ch] > 0) { var sfwork = sfwork_[gr][ch]; var vbrsfmin = vbrsfmin_[gr][ch]; cutDistribution(sfwork, sfwork, that.cod_info.global_gain); outOfBitsStrategy(that, sfwork, vbrsfmin, max_nbits_ch[gr][ch]); } use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); Debug.Assert(use_nbits_ch[gr][ch] <= max_nbits_ch[gr][ch]); use_nbits_gr[gr] += use_nbits_ch[gr][ch]; } // for ch use_nbits_fr += use_nbits_gr[gr]; } /* check bit constrains, but it should always be ok, if there are no bugs ;-) */ if (use_nbits_fr <= max_nbits_fr) { return(use_nbits_fr); } throw new Exception( string.Format( "INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report\n" + "maxbits={0:D} usedbits={1:D}\n", max_nbits_fr, use_nbits_fr)); }