All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vacco.libmp3lame.Jquantize Maven / Gradle / Ivy

package io.vacco.libmp3lame;

import java.util.Arrays;

/*
 * MP3 quantization
 *
 *      Copyright (c) 1999-2000 Mark Taylor
 *      Copyright (c) 1999-2003 Takehiro Tominaga
 *      Copyright (c) 2000-2011 Robert Hegemann
 *      Copyright (c) 2001-2005 Gabriel Bouvigne
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* $Id: quantize.c,v 1.216.2.1 2012/01/08 23:49:58 robert Exp $ */

// quantize.c

class Jquantize {

  static final boolean EQ(final float a, final float b) {
    return (Math.abs(a) > Math.abs(b))
        ? (Math.abs((a) - (b)) <= (Math.abs(a) * 1e-6f))
        : (Math.abs((a) - (b)) <= (Math.abs(b) * 1e-6f));
  }
  ;

  static final void init_xrpow_core_init(final Jlame_internal_flags gfc) {
    // gfc.init_xrpow_core = init_xrpow_core_c;
  }

  static final boolean init_xrpow(
      final Jlame_internal_flags gfc, final Jgr_info cod_info, final float xrpow[ /*576*/]) {
    final int upper = cod_info.max_nonzero_coeff;

    cod_info.xrpow_max = 0;

    /*  check if there is some energy we have to quantize
     *  and calculate xrpow matching our fresh scalefactors
     */
    for (int i = upper; i < 576; i++) {
      xrpow[i] = 0;
    }

    final float sum = cod_info.init_xrpow_core_c(xrpow, upper /*, &sum*/);

    /*  return 1 if we have something to quantize, else 0 */
    if (sum > 1E-20f) {
      final boolean j = ((gfc.sv_qnt.substep_shaping & 2) != 0);

      for (int i = 0; i < cod_info.psymax; i++) {
        gfc.sv_qnt.pseudohalf[i] = j;
      }

      return true;
    }

    for (int i = 0; i < 576; i++) {
      cod_info.l3_enc[i] = 0;
    }
    return false;
  }

  /**
   * Gabriel Bouvigne feb/apr 2003 Analog silence detection in partitionned sfb21 or sfb12 for short
   * blocks
   *
   * 

From top to bottom of sfb, changes to 0 coeffs which are below ath. It stops on the first * coeff higher than ath. */ private static final void psfb21_analogsilence( final Jlame_internal_flags gfc, final Jgr_info cod_info) { final JATH ATH = gfc.ATH; final float[] xr = cod_info.xr; if (cod_info.block_type != Jencoder.SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT blocks */ final float longfact_21 = gfc.sv_qnt.longfact[21]; // java final boolean is_more = longfact_21 > 1e-12f; // java final int[] psfb21 = gfc.scalefac_band.psfb21; // java boolean stop = false; for (int gsfb = Jencoder.PSFB21 - 1; gsfb >= 0 && !stop; gsfb--) { final int start = psfb21[gsfb]; final int end = psfb21[gsfb + 1]; float ath21 = Jquantize_pvt.athAdjust(ATH.adjust_factor, ATH.psfb21[gsfb], ATH.floor, 0); if (is_more) { ath21 *= longfact_21; } for (int j = end - 1; j >= start; j--) { final float v = xr[j]; if ((v >= 0 ? v : -v) < ath21) { xr[j] = 0; } else { stop = true; break; } } } return; } // else { final float shortfact_12 = gfc.sv_qnt.shortfact[12]; // java final boolean is_more = shortfact_12 > 1e-12f; // java final int[] psfb12 = gfc.scalefac_band.psfb12; // java final int[] s = gfc.scalefac_band.s; // java /*note: short blocks coeffs are reordered */ for (int block = 0; block < 3; block++) { boolean stop = false; for (int gsfb = Jencoder.PSFB12 - 1; gsfb >= 0 && !stop; gsfb--) { int start = s[12]; start = start * 3 + (s[13] - start) * block + (psfb12[gsfb] - psfb12[0]); final int end = start + (psfb12[gsfb + 1] - psfb12[gsfb]); float ath12 = Jquantize_pvt.athAdjust(ATH.adjust_factor, ATH.psfb12[gsfb], ATH.floor, 0); if (is_more) { ath12 *= shortfact_12; } for (int j = end - 1; j >= start; j--) { final float v = xr[j]; if ((v >= 0 ? v : -v) < ath12) { xr[j] = 0; } else { stop = true; break; } } } } // } } static final void init_outer_loop(final Jlame_internal_flags gfc, final Jgr_info cod_info) { final JSessionConfig cfg = gfc.cfg; /* initialize fresh 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; /* mixed_block_flag, block_type was set in psymodel.c */ 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; /* this one is always 0 */ cod_info.region0_count = 0; cod_info.region1_count = 0; cod_info.preflag = false; cod_info.scalefac_scale = 0; cod_info.count1table_select = 0; cod_info.part2_length = 0; if (cfg.samplerate <= 8000) { cod_info.sfb_lmax = 17; cod_info.sfb_smin = 9; cod_info.psy_lmax = 17; } else { cod_info.sfb_lmax = Jencoder.SBPSY_l; cod_info.sfb_smin = Jencoder.SBPSY_s; cod_info.psy_lmax = gfc.sv_qnt.sfb21_extra ? Jencoder.SBMAX_l : Jencoder.SBPSY_l; } cod_info.psymax = cod_info.psy_lmax; cod_info.sfbmax = cod_info.sfb_lmax; cod_info.sfbdivide = 11; final int[] band_l = gfc.scalefac_band.l; // java final int[] width = cod_info.width; // java final int[] cod_info_window = cod_info.window; // java for (int sfb = 0; sfb < Jencoder.SBMAX_l; sfb++) { width[sfb] = band_l[sfb + 1] - band_l[sfb]; cod_info_window[sfb] = 3; /* which is always 0. */ } if (cod_info.block_type == Jencoder.SHORT_TYPE) { final float ixwork[] = new float[576]; cod_info.sfb_smin = 0; cod_info.sfb_lmax = 0; if (cod_info.mixed_block_flag) { /* * MPEG-1: sfbs 0-7 long block, 3-12 short blocks * MPEG-2(.5): sfbs 0-5 long block, 3-12 short blocks */ cod_info.sfb_smin = 3; cod_info.sfb_lmax = (cfg.mode_gr << 1) + 4; } if (cfg.samplerate <= 8000) { cod_info.psymax = cod_info.sfb_lmax + 3 * (9 - cod_info.sfb_smin); cod_info.sfbmax = cod_info.sfb_lmax + 3 * (9 - cod_info.sfb_smin); } else { cod_info.psymax = cod_info.sfb_lmax + 3 * ((gfc.sv_qnt.sfb21_extra ? Jencoder.SBMAX_s : Jencoder.SBPSY_s) - cod_info.sfb_smin); cod_info.sfbmax = cod_info.sfb_lmax + 3 * (Jencoder.SBPSY_s - cod_info.sfb_smin); } cod_info.sfbdivide = cod_info.sfbmax - 18; cod_info.psy_lmax = cod_info.sfb_lmax; /* re-order the short blocks, for more efficient encoding below */ /* By Takehiro TOMINAGA */ /* Within each scalefactor band, data is given for successive time windows, beginning with window 0 and ending with window 2. Within each window, the quantized values are then arranged in order of increasing frequency... */ final float[] x = cod_info.xr; // java int ix = band_l[cod_info.sfb_lmax]; // x[ix] System.arraycopy(cod_info.xr, 0, ixwork, 0, 576); final int[] band_s = gfc.scalefac_band.s; // java for (int sfb = cod_info.sfb_smin; sfb < Jencoder.SBMAX_s; sfb++) { final int start = band_s[sfb]; final int end = band_s[sfb + 1]; for (int window = 0; window < 3; window++) { for (int l = start; l < end; l++) { x[ix++] = ixwork[3 * l + window]; } } } int j = cod_info.sfb_lmax; for (int sfb = cod_info.sfb_smin; sfb < Jencoder.SBMAX_s; sfb++) { width[j] = width[j + 1] = width[j + 2] = band_s[sfb + 1] - 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 = Jquantize_pvt.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; /* fresh scalefactors are all zero */ final int[] buf = cod_info.scalefac; int i = buf.length; do { buf[--i] = 0; } while (i > 0); if (cfg.vbr != Jlame.vbr_mt && cfg.vbr != Jlame.vbr_mtrh && cfg.vbr != Jlame.vbr_abr && cfg.vbr != Jlame.vbr_off) { psfb21_analogsilence(gfc, cod_info); } } /************************************************************************ * * bin_search_StepSize() * * author/date?? * * binary step size search * used by outer_loop to get a quantizer step size to start with * ************************************************************************/ // typedef enum { private static final int BINSEARCH_NONE = 0; private static final int BINSEARCH_UP = 1; private static final int BINSEARCH_DOWN = 2; // } binsearchDirection_t; private static final int bin_search_StepSize( final Jlame_internal_flags gfc, final Jgr_info cod_info, int desired_rate, final int ch, final float xrpow[ /*576*/]) { int CurrentStep = gfc.sv_qnt.CurrentStep[ch]; boolean flag_GoneOver = false; final int start = gfc.sv_qnt.OldValue[ch]; int /*binsearchDirection_t*/ Direction = BINSEARCH_NONE; cod_info.global_gain = start; desired_rate -= cod_info.part2_length; int nBits; for (; ; ) { nBits = Jtakehiro.count_bits(gfc, xrpow, cod_info, null); if (CurrentStep == 1 || nBits == desired_rate) { break; /* nothing to adjust anymore */ } int step; if (nBits > desired_rate) { /* increase Quantize_StepSize */ if (Direction == BINSEARCH_DOWN) { flag_GoneOver = true; } if (flag_GoneOver) { CurrentStep >>= 1; } Direction = BINSEARCH_UP; step = CurrentStep; } else { /* decrease Quantize_StepSize */ if (Direction == BINSEARCH_UP) { flag_GoneOver = true; } if (flag_GoneOver) { CurrentStep >>= 1; } Direction = BINSEARCH_DOWN; step = -CurrentStep; } cod_info.global_gain += step; if (cod_info.global_gain < 0) { cod_info.global_gain = 0; flag_GoneOver = true; } if (cod_info.global_gain > 255) { cod_info.global_gain = 255; flag_GoneOver = true; } } while (nBits > desired_rate && cod_info.global_gain < 255) { cod_info.global_gain++; nBits = Jtakehiro.count_bits(gfc, xrpow, cod_info, null); } gfc.sv_qnt.CurrentStep[ch] = (start - cod_info.global_gain >= 4) ? 4 : 2; gfc.sv_qnt.OldValue[ch] = cod_info.global_gain; cod_info.part2_3_length = nBits; return nBits; } /************************************************************************ * * trancate_smallspectrums() * * Takehiro TOMINAGA 2002-07-21 * * trancate smaller nubmers into 0 as long as the noise threshold is allowed. * ************************************************************************/ /* private static final int floatcompare(final float a, final float b) { if( a > b ) { return 1; } if( a < b ) { return -1; } return 0; } */ static final void trancate_smallspectrums( final Jlame_internal_flags gfc, final Jgr_info gi, final float[] l3_xmin, final float[] work) { final float distort[] = new float[Jencoder.SFBMAX]; final Jcalc_noise_result dummy = new Jcalc_noise_result(); if ((0 == (gfc.sv_qnt.substep_shaping & 4) && gi.block_type == Jencoder.SHORT_TYPE) || (gfc.sv_qnt.substep_shaping & 0x80) != 0) { return; } Jquantize_pvt.calc_noise(gi, l3_xmin, distort, dummy, null); final int[] l3_enc = gi.l3_enc; // java final float[] gi_xr = gi.xr; // java for (int j = 0; j < 576; j++) { float xr = 0.0f; if (l3_enc[j] != 0) { xr = gi_xr[j]; if (xr < 0) { xr = -xr; } } work[j] = xr; } int j = 0; int sfb = 8; if (gi.block_type == Jencoder.SHORT_TYPE) { sfb = 6; } do { final int width = gi.width[sfb]; j += width; if (distort[sfb] >= 1.0f) { continue; } // qsort( &work[j - width], width, sizeof(float), floatcompare ); Arrays.sort(work, j - width, j); // TODO java: check sort order if (EQ(work[j - 1], 0.0f)) { continue; } /* all zero sfb */ float allowedNoise = (1.0f - distort[sfb]) * l3_xmin[sfb]; float trancateThreshold = 0.0f; int jw = j - width; int start = 0; do { int nsame = 1; for (; start + nsame < width; nsame++) { if (!EQ(work[start + jw], work[start + jw + nsame])) { break; } } final float noise = work[start + jw] * work[start + jw] * nsame; if (allowedNoise < noise) { if (start != 0) { trancateThreshold = work[start + jw - 1]; } break; } allowedNoise -= noise; start += nsame; } while (start < width); if (EQ(trancateThreshold, 0.0f)) { continue; } /* printf("%e %e %e\n", */ /* trancateThreshold/l3_xmin[sfb], */ /* trancateThreshold/(l3_xmin[sfb]*start), */ /* trancateThreshold/(l3_xmin[sfb]*(start+width)) */ /* ); */ /* if( trancateThreshold > 1000*l3_xmin[sfb]*start) */ /* trancateThreshold = 1000*l3_xmin[sfb]*start; */ // java: check the loop do { final float v = gi_xr[jw]; // xr[j - width] if ((v >= 0 ? v : -v) <= trancateThreshold) { l3_enc[jw] = 0; // l3_enc[j - width] } } while (++jw < j); // (--width > 0) } while (++sfb < gi.psymax); gi.part2_3_length = Jtakehiro.noquant_count_bits(gfc, gi, null); } /* mt 5/99: Function: Improved calc_noise for a single channel */ /************************************************************************* * * quant_compare() * * author/date?? * * several different codes to decide which quantization is better * *************************************************************************/ private static final float penalties(final float noise) { return (float) Math.log10( (double) (0.368f + 0.632f * noise * noise * noise)); // Jutil.FAST_LOG10( 0.368f + 0.632f * noise * noise * noise ); } private static final float get_klemm_noise(final float[] distort, final Jgr_info gi) { float klemm_noise = 1E-37f; for (int sfb = 0, psymax = gi.psymax; sfb < psymax; sfb++) { klemm_noise += penalties(distort[sfb]); } return (1e-20f >= klemm_noise ? 1e-20f : klemm_noise); } private static final boolean quant_compare( final int quant_comp, final Jcalc_noise_result best, final Jcalc_noise_result calc, final Jgr_info gi, final float[] distort) { /* noise is given in decibels (dB) relative to masking thesholds. over_noise: ??? (the previous comment is fully wrong) tot_noise: ??? (the previous comment is fully wrong) max_noise: max quantization noise */ boolean better; switch (quant_comp) { default: case 9: { if (best.over_count > 0) { /* there are distorted sfb */ better = calc.over_SSD <= best.over_SSD; if (calc.over_SSD == best.over_SSD) { better = calc.bits < best.bits; } } else { /* no distorted sfb */ 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 && EQ(calc.over_noise, best.over_noise) && calc.tot_noise < best.tot_noise); break; case 8: calc.max_noise = get_klemm_noise(distort, gi); /*lint --fallthrough */ 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.2f) || (calc.max_noise <= 0.0f && best.max_noise < 0.0f && best.max_noise > calc.max_noise - 0.2f && calc.tot_noise < best.tot_noise) || (calc.max_noise <= 0.0f && best.max_noise > 0.0f && best.max_noise > calc.max_noise - 0.2f && calc.tot_noise < best.tot_noise + best.over_noise) || (calc.max_noise > 0.0f && best.max_noise > -0.05f && best.max_noise > calc.max_noise - 0.1f && calc.tot_noise + calc.over_noise < best.tot_noise + best.over_noise) || (calc.max_noise > 0.0f && best.max_noise > -0.1f && best.max_noise > calc.max_noise - 0.15f && 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 || (EQ(calc.over_noise, best.over_noise) && calc.tot_noise < best.tot_noise); break; case 6: better = calc.over_noise < best.over_noise || (EQ(calc.over_noise, best.over_noise) && (calc.max_noise < best.max_noise || (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) { /* If no distorted bands, only use this quantization if it is better, and if it uses less bits. Unfortunately, part2_3_length is sometimes a poor estimator of the final size at low bitrates. */ better = better && calc.bits < best.bits; } return better; } /************************************************************************* * * amp_scalefac_bands() * * author/date?? * * Amplify the scalefactor bands that violate the masking threshold. * See ISO 11172-3 Section C.1.5.4.3.5 * * distort[] = noise/masking * distort[] > 1 ==> noise is not masked * distort[] < 1 ==> noise is masked * max_dist = maximum value of distort[] * * Three algorithms: * noise_shaping_amp * 0 Amplify all bands with distort[]>1. * * 1 Amplify all bands with distort[] >= max_dist^(.5); * ( 50% in the db scale) * * 2 Amplify first band with distort[] >= max_dist; * * * For algorithms 0 and 1, if max_dist < 1, then amplify all bands * with distort[] >= .95*max_dist. This is to make sure we always * amplify at least one band. * * *************************************************************************/ private static final void amp_scalefac_bands( final Jlame_internal_flags gfc, final Jgr_info cod_info, final float[] distort, final float xrpow[ /*576*/], final boolean bRefine) { final JSessionConfig cfg = gfc.cfg; float ifqstep34; if (cod_info.scalefac_scale == 0) { ifqstep34 = 1.29683955465100964055f; /* 2**(.75*.5) */ } else { ifqstep34 = 1.68179283050742922612f; /* 2**(.75*1) */ } /* compute maximum value of distort[] */ float trigger = 0; for (int sfb = 0; sfb < cod_info.sfbmax; sfb++) { if (trigger < distort[sfb]) { trigger = distort[sfb]; } } int noise_shaping_amp = cfg.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: /* amplify exactly 1 band */ break; case 1: /* amplify bands within 50% of max (on db scale) */ if (trigger > 1.0f) { trigger = (float) Math.pow(trigger, .5); } else { trigger *= .95f; } break; case 0: default: /* ISO algorithm. amplify all bands with distort>1 */ if (trigger > 1.0f) { trigger = 1.0f; } else { trigger *= .95f; } break; } final int[] cod_info_width = cod_info.width; // java final boolean[] pseudohalf = gfc.sv_qnt.pseudohalf; // java final int[] scalefac = cod_info.scalefac; // java int j = 0; for (int sfb = 0, sfbmax = cod_info.sfbmax; sfb < sfbmax; sfb++) { final int width = cod_info_width[sfb]; j += width; if (distort[sfb] < trigger) { continue; } if ((gfc.sv_qnt.substep_shaping & 2) != 0) { pseudohalf[sfb] = !pseudohalf[sfb]; if (!pseudohalf[sfb] && cfg.noise_shaping_amp == 2) { return; } } scalefac[sfb]++; for (int l = -width + j; l < j; l++) { xrpow[l] *= ifqstep34; if (xrpow[l] > cod_info.xrpow_max) { cod_info.xrpow_max = xrpow[l]; } } if (cfg.noise_shaping_amp == 2) { return; } } } /************************************************************************* * * inc_subblock_gain() * * Takehiro Tominaga 2000-xx-xx * * increases the subblock gain and adjusts scalefactors * *************************************************************************/ private static final boolean inc_subblock_gain( final Jlame_internal_flags gfc, final Jgr_info cod_info, final float xrpow[ /*576*/]) { final int[] scalefac = cod_info.scalefac; final int sfb_lmax = cod_info.sfb_lmax; // java final int sfbmax = cod_info.sfbmax; // java /* subbloc_gain can't do anything in the long block region */ for (int sfb = 0; sfb < sfb_lmax; sfb++) { if (scalefac[sfb] >= 16) { return true; } } final int max = gfc.scalefac_band.l[sfb_lmax]; // java final int scale4 = (4 >> cod_info.scalefac_scale); // java final int scale1 = cod_info.scalefac_scale + 1; // java final int sfbdivide = cod_info.sfbdivide; // java for (int window = 0; window < 3; window++) { int s1, s2, sfb; s1 = s2 = 0; for (sfb = sfb_lmax + window; sfb < sfbdivide; sfb += 3) { if (s1 < scalefac[sfb]) { s1 = scalefac[sfb]; } } for (; sfb < 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; } /* even though there is no scalefactor for sfb12 * subblock gain affects upper frequencies too, that's why * we have to go up to SBMAX_s */ cod_info.subblock_gain[window]++; int j = max; for (sfb = sfb_lmax + window; sfb < sfbmax; sfb += 3) { final int width = cod_info.width[sfb]; int s = scalefac[sfb]; s = s - scale4; if (s >= 0) { scalefac[sfb] = s; j += width * 3; continue; } scalefac[sfb] = 0; // { final int gain = 210 + (s << scale1); final float amp = Jquantize_pvt.ipow20[gain]; // } j += width * (window + 1); for (int l = -width + j; l < j; l++) { xrpow[l] *= amp; if (xrpow[l] > cod_info.xrpow_max) { cod_info.xrpow_max = xrpow[l]; } } j += width * (3 - window - 1); } { final float amp = Jquantize_pvt.ipow20[202]; j += cod_info.width[sfb] * (window + 1); for (int l = -cod_info.width[sfb] + j; l < j; l++) { xrpow[l] *= amp; if (xrpow[l] > cod_info.xrpow_max) { cod_info.xrpow_max = xrpow[l]; } } } } return false; } /******************************************************************** * * balance_noise() * * Takehiro Tominaga /date?? * Robert Hegemann 2000-09-06: made a function of it * * amplifies scalefactor bands, * - if all are already amplified returns 0 * - if some bands are amplified too much: * * try to increase scalefac_scale * * if already scalefac_scale was set * try on short blocks to increase subblock gain * ********************************************************************/ private static final boolean balance_noise( final Jlame_internal_flags gfc, final Jgr_info cod_info, final float[] distort, final float xrpow[ /*576*/], final boolean bRefine) { final JSessionConfig cfg = gfc.cfg; amp_scalefac_bands(gfc, cod_info, distort, xrpow, bRefine); /* check to make sure we have not amplified too much * loop_break returns 0 if there is an unamplified scalefac * scale_bitcount returns 0 if no scalefactors are too large */ boolean status = cod_info.loop_break(); if (status) { return false; } /* all bands amplified */ /* not all scalefactors have been amplified. so these * scalefacs are possibly valid. encode them: */ status = Jtakehiro.scale_bitcount(gfc, cod_info); if (!status) { return true; } /* amplified some bands not exceeding limits */ /* some scalefactors are too large. * lets try setting scalefac_scale=1 */ if (cfg.noise_shaping > 1) { final boolean[] pseudohalf = gfc.sv_qnt.pseudohalf; int i = pseudohalf.length; do { pseudohalf[--i] = false; } while (i > 0); if (0 == cod_info.scalefac_scale) { cod_info.inc_scalefac_scale(xrpow); status = false; } else { if (cod_info.block_type == Jencoder.SHORT_TYPE && cfg.subblock_gain > 0) { status = inc_subblock_gain(gfc, cod_info, xrpow) || cod_info.loop_break(); } } } if (!status) { status = Jtakehiro.scale_bitcount(gfc, cod_info); } return !status; } /************************************************************************ * * outer_loop () * * Function: The outer iteration loop controls the masking conditions * of all scalefactorbands. It computes the best scalefac and * global gain. This module calls the inner iteration loop * * mt 5/99 completely rewritten to allow for bit reservoir control, * mid/side channels with L/R or mid/side masking thresholds, * and chooses best quantization instead of last quantization when * no distortion free quantization can be found. * * added VBR support mt 5/99 * * some code shuffle rh 9/00 ************************************************************************/ static final int outer_loop( final Jlame_internal_flags gfc, final Jgr_info cod_info, final float[] l3_xmin, /* allowed distortion */ final float xrpow[ /*576*/], /* coloured magnitudes of spectral */ final int ch, final int targ_bits) { /* maximum allowed bits */ final JSessionConfig cfg = gfc.cfg; final float save_xrpow[] = new float[576]; final float distort[] = new float[Jencoder.SFBMAX]; final Jcalc_noise_result best_noise_info = new Jcalc_noise_result(); final Jcalc_noise_data prev_noise = new Jcalc_noise_data(); // java: already zeroed int best_part2_3_length = 9999999; boolean bEndOfSearch = false; boolean bRefine = false; int best_ggain_pass1 = 0; bin_search_StepSize(gfc, cod_info, targ_bits, ch, xrpow); if (0 == cfg.noise_shaping) { return 100; } /* default noise_info.over_count */ /* compute the distortion in this quantization */ /* coefficients and thresholds both l/r (or both mid/side) */ Jquantize_pvt.calc_noise(cod_info, l3_xmin, distort, best_noise_info, prev_noise); best_noise_info.bits = cod_info.part2_3_length; final Jgr_info cod_info_w = new Jgr_info(cod_info); int age = 0; /* if( cfg.vbr == vbr_rh || cfg.vbr == vbr_mtrh) */ System.arraycopy(xrpow, 0, save_xrpow, 0, 576); final Jcalc_noise_result noise_info = new Jcalc_noise_result(); // java: moved up while (!bEndOfSearch) { /* BEGIN MAIN LOOP */ do { int maxggain = 255; /* When quantization with no distorted bands is found, * allow up to X new unsuccesful tries in serial. This * gives us more possibilities for different quant_compare modes. * Much more than 3 makes not a big difference, it is only slower. */ final int search_limit = ((gfc.sv_qnt.substep_shaping & 2) != 0) ? 20 : 3; /* Check if the last scalefactor band is distorted. * in VBR mode we can't get rid of the distortion, so quit now * and VBR mode will try again with more bits. * (makes a 10% speed increase, the files I tested were * binary identical, 2000/05/20 Robert Hegemann) * distort[] > 1 means noise > allowed noise */ if (gfc.sv_qnt.sfb21_extra) { if (distort[cod_info_w.sfbmax] > 1.0f) { break; } if (cod_info_w.block_type == Jencoder.SHORT_TYPE && (distort[cod_info_w.sfbmax + 1] > 1.0f || distort[cod_info_w.sfbmax + 2] > 1.0f)) { break; } } /* try a new scalefactor conbination on cod_info_w */ if (!balance_noise(gfc, cod_info_w, distort, xrpow, bRefine)) { break; } if (cod_info_w.scalefac_scale != 0) { maxggain = 254; } /* inner_loop starts with the initial quantization step computed above * and slowly increases until the bits < huff_bits. * Thus it is important not to start with too large of an inital * quantization step. Too small is ok, but inner_loop will take longer */ final int huff_bits = targ_bits - cod_info_w.part2_length; if (huff_bits <= 0) { break; } /* increase quantizer stepsize until needed bits are below maximum */ while ((cod_info_w.part2_3_length = Jtakehiro.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 = Jtakehiro.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; } } /* compute the distortion in this quantization */ Jquantize_pvt.calc_noise(cod_info_w, l3_xmin, distort, noise_info, prev_noise); noise_info.bits = cod_info_w.part2_3_length; /* check if this quantization is better * than our saved quantization */ final int quant = (cod_info.block_type != Jencoder.SHORT_TYPE) ? cfg.quant_comp : cfg.quant_comp_short; final boolean better = quant_compare(quant, best_noise_info, noise_info, cod_info_w, distort); /* save data so we can restore this quantization later */ if (better) { best_part2_3_length = cod_info.part2_3_length; best_noise_info.copyFrom(noise_info); cod_info.copyFrom(cod_info_w); age = 0; /* save data so we can restore this quantization later */ /*if( cfg.vbr == vbr_rh || cfg.vbr == vbr_mtrh) */ { /* store for later reuse */ System.arraycopy(xrpow, 0, save_xrpow, 0, 576); } } else { /* early stop? */ if (cfg.full_outer_loop == 0) { if (++age > search_limit && best_noise_info.over_count == 0) { break; } if ((cfg.noise_shaping_amp == 3) && bRefine && age > 30) { break; } if ((cfg.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 (cfg.noise_shaping_amp == 3) { if (!bRefine) { /* refine search */ cod_info_w.copyFrom(cod_info); System.arraycopy(save_xrpow, 0, xrpow, 0, 576); age = 0; best_ggain_pass1 = cod_info_w.global_gain; bRefine = true; } else { /* search already refined, stop */ bEndOfSearch = true; } } else { bEndOfSearch = true; } } /* finish up */ if (cfg.vbr == Jlame.vbr_rh || cfg.vbr == Jlame.vbr_mtrh || cfg.vbr == Jlame.vbr_mt) { System.arraycopy(save_xrpow, 0, xrpow, 0, 576); } else if ((gfc.sv_qnt.substep_shaping & 1) != 0) { trancate_smallspectrums(gfc, cod_info, l3_xmin, xrpow); } return best_noise_info.over_count; } /************************************************************************ * * iteration_finish_one() * * Robert Hegemann 2000-09-06 * * update reservoir status after FINAL quantization/bitrate * ************************************************************************/ static final void iteration_finish_one( final Jlame_internal_flags gfc, final int gr, final int ch) { final JSessionConfig cfg = gfc.cfg; final JIII_side_info l3_side = gfc.l3_side; final Jgr_info cod_info = l3_side.tt[gr][ch]; /* try some better scalefac storage */ Jtakehiro.best_scalefac_store(gfc, gr, ch, l3_side); /* best huffman_divide may save some bits too */ if (cfg.use_best_huffman == 1) { Jtakehiro.best_huffman_divide(gfc, cod_info); } /* update reservoir status after FINAL quantization/bitrate */ Jreservoir.ResvAdjust(gfc, cod_info); } /************************************************************************ * * get_framebits() * * Robert Hegemann 2000-09-05 * * calculates * * how many bits are available for analog silent granules * * how many bits to use for the lowest allowed bitrate * * how many bits each bitrate would provide * ************************************************************************/ static final void get_framebits(final Jlame_internal_flags gfc, final int frameBits[ /*15*/]) { final JSessionConfig cfg = gfc.cfg; final JEncResult eov = gfc.ov_enc; // int bitsPerFrame;// FIXME result never uses /* always use at least this many bits per granule per channel * unless we detect analog silence, see below */ // eov.bitrate_index = cfg.vbr_min_bitrate_index; // bitsPerFrame = Jbitstream.getframebits( gfc ); /* bits for analog silence */ // eov.bitrate_index = 1; // bitsPerFrame = Jbitstream.getframebits( gfc ); for (int i = 1, max = cfg.vbr_max_bitrate_index; i <= max; i++) { eov.bitrate_index = i; frameBits[i] = (int) Jreservoir.ResvFrameBegin(gfc /*, &bitsPerFrame*/); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy