gt: 				System.arraycopy(xrpow, 0, bst_xrpow, 0, 576);
context: /*
   * MP3 quantization
   *
   *      Copyright (c) 1999-2000 Mark Taylor
   *      Copyright (c) 1999-2003 Takehiro Tominaga
   *      Copyright (c) 2000-2007 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 Lesser 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 Lesser 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.java,v 1.24 2011/05/24 20:48:06 kenchis Exp $ */
  
  package mp3;
  
  import java.util.Arrays;
  
  public class Quantize {
  	BitStream bs;
  	Reservoir rv;
  	QuantizePVT qupvt;
  	VBRQuantize vbr = new VBRQuantize();
  	Takehiro tk;
  
  	public final void setModules(BitStream bs, Reservoir rv, QuantizePVT qupvt,
  			Takehiro tk) {
  		this.bs = bs;
  		this.rv = rv;
  		this.qupvt = qupvt;
  		this.tk = tk;
  		this.vbr.setModules(qupvt, tk);
  	}
  
  	/**
  	 * convert from L/R <. Mid/Side
  	 */
  	public final void ms_convert(final IIISideInfo l3_side, final int gr) {
  		for (int i = 0; i < 576; ++i) {
  			float l = l3_side.tt[gr][0].xr[i];
  			float r = l3_side.tt[gr][1].xr[i];
  			l3_side.tt[gr][0].xr[i] = (l + r) * (float) (Util.SQRT2 * 0.5);
  			l3_side.tt[gr][1].xr[i] = (l - r) * (float) (Util.SQRT2 * 0.5);
  		}
  	}
  
  	/**
  	 * mt 6/99
  	 * 
  	 * initializes cod_info, scalefac and xrpow
  	 * 
  	 * returns 0 if all energies in xr are zero, else 1
  	 */
  	private float init_xrpow_core(final GrInfo cod_info, float xrpow[],
  			int upper, float sum) {
  		sum = 0;
  		for (int i = 0; i <= upper; ++i) {
  			float 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;
  	}
  
  	public final boolean init_xrpow(final LameInternalFlags gfc,
  			final GrInfo cod_info, float xrpow[]) {
  		float sum = 0;
  		final int upper = cod_info.max_nonzero_coeff;
  
  		assert (xrpow != null);
  		cod_info.xrpow_max = 0;
  
  		/*
  		 * check if there is some energy we have to quantize and calculate xrpow
  		 * matching our fresh scalefactors
  		 */
  		assert (0 <= upper && upper <= 575);
  
  		Arrays.fill(xrpow, upper, 576, 0);
  
  		sum = init_xrpow_core(cod_info, xrpow, upper, sum);
  
  		/*
  		 * return 1 if we have something to quantize, else 0
  		 */
  		if (sum > 1E-20f) {
  			int j = 0;
  			if ((gfc.substep_shaping & 2) != 0)
  				j = 1;
  
  			for (int i = 0; i < cod_info.psymax; i++)
  				gfc.pseudohalf[i] = j;
  
  			return true;
  		}
  
  		Arrays.fill(cod_info.l3_enc, 0, 576, 0);
  		return false;
  	}
  
  	/**
  	 * Gabriel Bouvigne feb/apr 2003<BR>
  	 * 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 void psfb21_analogsilence(final LameInternalFlags gfc,
  			final GrInfo cod_info) {
  		final ATH ath = gfc.ATH;
  		final float[] xr = cod_info.xr;
  
  		if (cod_info.block_type != Encoder.SHORT_TYPE) {
  			/* NORM, START or STOP type, but not SHORT blocks */
  			boolean stop = false;
  			for (int gsfb = Encoder.PSFB21 - 1; gsfb >= 0 && !stop; gsfb--) {
  				final int start = gfc.scalefac_band.psfb21[gsfb];
  				final int end = gfc.scalefac_band.psfb21[gsfb + 1];
  				float ath21 = qupvt.athAdjust(ath.adjust, ath.psfb21[gsfb],
  						ath.floor);
  
  				if (gfc.nsPsy.longfact[21] > 1e-12f)
  					ath21 *= gfc.nsPsy.longfact[21];
  
  				for (int j = end - 1; j >= start; j--) {
  					if (Math.abs(xr[j]) < ath21)
  						xr[j] = 0;
  					else {
  						stop = true;
  						break;
  					}
  				}
  			}
  		} else {
  			/* note: short blocks coeffs are reordered */
  			for (int block = 0; block < 3; block++) {
  				boolean stop = false;
  				for (int gsfb = Encoder.PSFB12 - 1; gsfb >= 0 && !stop; gsfb--) {
  					final int 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]);
  					final int end = start
  							+ (gfc.scalefac_band.psfb12[gsfb + 1] - gfc.scalefac_band.psfb12[gsfb]);
  					float ath12 = qupvt.athAdjust(ath.adjust, ath.psfb12[gsfb],
  							ath.floor);
  
  					if (gfc.nsPsy.shortfact[12] > 1e-12f)
  						ath12 *= gfc.nsPsy.shortfact[12];
  
  					for (int j = end - 1; j >= start; j--) {
  						if (Math.abs(xr[j]) < ath12)
  							xr[j] = 0;
  						else {
  							stop = true;
  							break;
  						}
  					}
  				}
  			}
  		}
  
  	}
  
  	public final void init_outer_loop(final LameInternalFlags gfc,
  			final GrInfo cod_info) {
  		/*
  		 * 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 = 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 (int sfb = 0; sfb < Encoder.SBMAX_l; sfb++) {
  			cod_info.width[sfb] = gfc.scalefac_band.l[sfb + 1]
  					- gfc.scalefac_band.l[sfb];
  			/* which is always 0. */
  			cod_info.window[sfb] = 3;
  		}
  		if (cod_info.block_type == Encoder.SHORT_TYPE) {
  			float ixwork[] = new float[576];
  
  			cod_info.sfb_smin = 0;
  			cod_info.sfb_lmax = 0;
  			if (cod_info.mixed_block_flag != 0) {
  				/*
  				 * 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 = 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;
  			/* 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...
  			 */
  			int ix = gfc.scalefac_band.l[cod_info.sfb_lmax];
  			System.arraycopy(cod_info.xr, 0, ixwork, 0, 576);
  			for (int sfb = cod_info.sfb_smin; sfb < Encoder.SBMAX_s; sfb++) {
  				final int start = gfc.scalefac_band.s[sfb];
  				final int end = gfc.scalefac_band.s[sfb + 1];
  				for (int window = 0; window < 3; window++) {
  					for (int l = start; l < end; l++) {
  						cod_info.xr[ix++] = ixwork[3 * l + window];
  					}
  				}
  			}
  
  			int j = cod_info.sfb_lmax;
  			for (int 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;
  
  		/*
  		 * fresh scalefactors are all zero
  		 */
  		Arrays.fill(cod_info.scalefac, 0);
  
  		psfb21_analogsilence(gfc, cod_info);
  	}
  
  	private enum BinSearchDirection {
  		BINSEARCH_NONE, BINSEARCH_UP, BINSEARCH_DOWN
  	}
  
  	/**
  	 * author/date??
  	 * 
  	 * binary step size search used by outer_loop to get a quantizer step size
  	 * to start with
  	 */
  	private int bin_search_StepSize(final LameInternalFlags gfc,
  			final GrInfo cod_info, int desired_rate, final int ch,
  			final float xrpow[]) {
  		int nBits;
  		int CurrentStep = gfc.CurrentStep[ch];
  		boolean flagGoneOver = false;
  		final int start = gfc.OldValue[ch];
  		BinSearchDirection Direction = BinSearchDirection.BINSEARCH_NONE;
  		cod_info.global_gain = start;
  		desired_rate -= cod_info.part2_length;
  
  		assert (CurrentStep != 0);
  		for (;;) {
  			int step;
  			nBits = tk.count_bits(gfc, xrpow, cod_info, null);
  
  			if (CurrentStep == 1 || nBits == desired_rate)
  				break; /* nothing to adjust anymore */
  
  			if (nBits > desired_rate) {
  				/* increase Quantize_StepSize */
  				if (Direction == BinSearchDirection.BINSEARCH_DOWN)
  					flagGoneOver = true;
  
  				if (flagGoneOver)
  					CurrentStep /= 2;
  				Direction = BinSearchDirection.BINSEARCH_UP;
  				step = CurrentStep;
  			} else {
  				/* decrease Quantize_StepSize */
  				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;
  			}
  		}
  
  		assert (cod_info.global_gain >= 0);
  		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;
  	}
  
  	public final void trancate_smallspectrums(final LameInternalFlags gfc,
  			final GrInfo gi, final float[] l3_xmin, final float[] work) {
  		float 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 (int j = 0; j < 576; j++) {
  			float xr = 0.0f;
  			if (gi.l3_enc[j] != 0)
  				xr = Math.abs(gi.xr[j]);
  			work[j] = xr;
  		}
  
  		int j = 0;
  		int sfb = 8;
  		if (gi.block_type == Encoder.SHORT_TYPE)
  			sfb = 6;
  		do {
  			float allowedNoise, trancateThreshold;
  			int nsame, start;
  
  			int 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; /* all zero sfb */
  
  			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);
  	}
  
  	/**
  	 * author/date??
  	 * 
  	 * Function: Returns zero if there is a scalefac which has not been
  	 * amplified. Otherwise it returns one.
  	 */
  	private boolean loop_break(final GrInfo cod_info) {
  		for (int 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;
  	}
  
  	/* mt 5/99: Function: Improved calc_noise for a single channel */
  
  	private double penalties(final double noise) {
  		return Util.FAST_LOG10((float) (0.368 + 0.632 * noise * noise * noise));
  	}
  
  	/**
  	 * author/date??
  	 * 
  	 * several different codes to decide which quantization is better
  	 */
  	private double get_klemm_noise(final float[] distort, final GrInfo gi) {
  		double klemm_noise = 1E-37;
  		for (int sfb = 0; sfb < gi.psymax; sfb++)
  			klemm_noise += penalties(distort[sfb]);
  
  		return Math.max(1e-20, klemm_noise);
  	}
  
  	private boolean quant_compare(final int quant_comp,
  			final CalcNoiseResult best, final CalcNoiseResult calc,
  			final GrInfo gi, final float[] distort) {
  		/**
  		 * noise is given in decibels (dB) relative to masking thesholds.<BR>
  		 * 
  		 * over_noise: ??? (the previous comment is fully wrong)<BR>
  		 * tot_noise: ??? (the previous comment is fully wrong)<BR>
  		 * 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
  							&& 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);
  			//$FALL-THROUGH$
  		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) {
  			/*
  			 * 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;
  	}
  
  	/**
  	 * author/date??
  	 * 
  	 * <PRE>
  	 *  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.
  	 * </PRE>
  	 */
  	private void amp_scalefac_bands(final LameGlobalFlags gfp,
  			final GrInfo cod_info, final float[] distort,
  			final float xrpow[], final boolean bRefine) {
  		final LameInternalFlags gfc = gfp.internal_flags;
  		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 = 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:
  			/* amplify exactly 1 band */
  			break;
  
  		case 1:
  			/* amplify bands within 50% of max (on db scale) */
  			if (trigger > 1.0)
  				trigger = (float) Math.pow(trigger, .5);
  			else
  				trigger *= .95;
  			break;
  
  		case 0:
  		default:
  			/* ISO algorithm. amplify all bands with distort>1 */
  			if (trigger > 1.0)
  				trigger = 1.0f;
  			else
  				trigger *= .95;
  			break;
  		}
  
  		int j = 0;
  		for (int sfb = 0; sfb < cod_info.sfbmax; sfb++) {
  			final int 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;
  		}
  	}
  
  	/**
  	 * Takehiro Tominaga 2000-xx-xx
  	 * 
  	 * turns on scalefac scale and adjusts scalefactors
  	 */
  	private void inc_scalefac_scale(final GrInfo cod_info, float xrpow[]) {
  		final float ifqstep34 = 1.29683955465100964055f;
  
  		int j = 0;
  		for (int sfb = 0; sfb < cod_info.sfbmax; sfb++) {
  			final int width = cod_info.width[sfb];
  			int s = cod_info.scalefac[sfb];
  			if (cod_info.preflag != 0)
  				s += qupvt.pretab[sfb];
  			j += width;
  			if ((s & 1) != 0) {
  				s++;
  				for (int 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;
  	}
  
  	/**
  	 * Takehiro Tominaga 2000-xx-xx
  	 * 
  	 * increases the subblock gain and adjusts scalefactors
  	 */
  	private boolean inc_subblock_gain(final LameInternalFlags gfc,
  			final GrInfo cod_info, float xrpow[]) {
  		int sfb;
  		final int[] scalefac = cod_info.scalefac;
  
  		/* subbloc_gain can't do anything in the long block region */
  		for (sfb = 0; sfb < cod_info.sfb_lmax; sfb++) {
  			if (scalefac[sfb] >= 16)
  				return true;
  		}
  
  		for (int window = 0; window < 3; window++) {
  			int s1 = 0;
  			int 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;
  
  			/*
  			 * 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 = gfc.scalefac_band.l[cod_info.sfb_lmax];
  			for (sfb = cod_info.sfb_lmax + window; sfb < cod_info.sfbmax; sfb += 3) {
  				float amp;
  				final int width = cod_info.width[sfb];
  				int s = scalefac[sfb];
  				assert (s >= 0);
  				s = s - (4 >> cod_info.scalefac_scale);
  				if (s >= 0) {
  					scalefac[sfb] = s;
  					j += width * 3;
  					continue;
  				}
  
  				scalefac[sfb] = 0;
  				{
  					final int gain = 210 + (s << (cod_info.scalefac_scale + 1));
  					amp = qupvt.IPOW20(gain);
  				}
  				j += width * (window + 1);
  				for (int 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);
  			}
  
  			{
  				final float amp = qupvt.IPOW20(202);
  				j += cod_info.width[sfb] * (window + 1);
  				for (int 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;
  	}
  
  	/**
  	 * <PRE>
  	 *  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
  	 * </PRE>
  	 */
  	private boolean balance_noise(final LameGlobalFlags gfp,
  			final GrInfo cod_info, final float[] distort, float xrpow[],
  			final boolean bRefine) {
  		final LameInternalFlags gfc = gfp.internal_flags;
  
  		amp_scalefac_bands(gfp, 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 = loop_break(cod_info);
  
  		if (status)
  			return false; /* all bands amplified */
  
  		/*
  		 * not all scalefactors have been amplified. so these scalefacs are
  		 * possibly valid. encode them:
  		 */
  		if (gfc.mode_gr == 2)
  			status = tk.scale_bitcount(cod_info);
  		else
  			status = tk.scale_bitcount_lsf(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 (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;
  	}
  
  	/**
  	 * <PRE>
  	 *  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
  	 * </PRE>
  	 * 
  	 * @param l3_xmin
  	 *            allowed distortion
  	 * @param xrpow
  	 *            coloured magnitudes of spectral
  	 * @param targ_bits
  	 *            maximum allowed bits
  	 */
  	public final int outer_loop(final LameGlobalFlags gfp,
  			final GrInfo cod_info, final float[] l3_xmin, float xrpow[],
  			final int ch, final int targ_bits) {
  		final LameInternalFlags gfc = gfp.internal_flags;
  		GrInfo cod_info_w = new GrInfo();
  		float save_xrpow[] = new float[576];
  		float distort[] = new float[L3Side.SFBMAX];
  		CalcNoiseResult best_noise_info = new CalcNoiseResult();
  		int better;
  		CalcNoiseData prev_noise = new CalcNoiseData();
  		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 == gfc.noise_shaping)
  			/* fast mode, no noise shaping, we are ready */
  			return 100; /* default noise_info.over_count */
  
  		/* compute the distortion in this quantization */
  		/* coefficients and thresholds both l/r (or both mid/side) */
  		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);
  		int age = 0;
  		System.arraycopy(xrpow, 0, save_xrpow, 0, 576);
  
  		while (!bEndOfSearch) {
  			/* BEGIN MAIN LOOP */
  			do {
  				CalcNoiseResult noise_info = new CalcNoiseResult();
  				int search_limit;
  				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.
  				 */
  
  				if ((gfc.substep_shaping & 2) != 0) {
  					search_limit = 20;
  				} else {
  					search_limit = 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.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;
  				}
  
  				/* try a new scalefactor conbination on cod_info_w */
  				if (!balance_noise(gfp, 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
  				 */
  				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 = 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;
  				}
  
  				/* compute the distortion in this quantization */
  				qupvt.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
  				 */
  				if (cod_info.block_type != Encoder.SHORT_TYPE) {
  					// NORM, START or STOP 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;
  
  				/* save data so we can restore this quantization later */
  				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;
  					/* save data so we can restore this quantization later */
  					/* store for later reuse */
  					System.arraycopy(xrpow, 0, save_xrpow, 0, 576);
  				} else {
  					/* early stop? */
  					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) {
  					/* refine search */
  					cod_info_w.assign(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;
  			}
  		}
  
  		assert ((cod_info.global_gain + cod_info.scalefac_scale) <= 255);
  		/*
  		 * finish up
  		 */
  		if (gfp.VBR == VbrMode.vbr_rh || gfp.VBR == VbrMode.vbr_mtrh)
  			/* restore for reuse on next try */
  			System.arraycopy(save_xrpow, 0, xrpow, 0, 576);
  		/*
  		 * do the 'substep shaping'
  		 */
  		else if ((gfc.substep_shaping & 1) != 0)
  			trancate_smallspectrums(gfc, cod_info, l3_xmin, xrpow);
  
  		return best_noise_info.over_count;
  	}
  
  	/**
  	 * Robert Hegemann 2000-09-06
  	 * 
  	 * update reservoir status after FINAL quantization/bitrate
  	 */
  	public final void iteration_finish_one(final LameInternalFlags gfc,
  			final int gr, final int ch) {
  		final IIISideInfo l3_side = gfc.l3_side;
  		final GrInfo cod_info = l3_side.tt[gr][ch];
  
  		/*
  		 * try some better scalefac storage
  		 */
  		tk.best_scalefac_store(gfc, gr, ch, l3_side);
  
  		/*
  		 * best huffman_divide may save some bits too
  		 */
  		if (gfc.use_best_huffman == 1)
  			tk.best_huffman_divide(gfc, cod_info);
  
  		/*
  		 * update reservoir status after FINAL quantization/bitrate
  		 */
  		rv.ResvAdjust(gfc, cod_info);
  	}
  
  	/**
  	 * 
  	 * 2000-09-04 Robert Hegemann
  	 * 
  	 * @param l3_xmin
  	 *            allowed distortion of the scalefactor
  	 * @param xrpow
  	 *            coloured magnitudes of spectral values
  	 */
  	public final void VBR_encode_granule(final LameGlobalFlags gfp,
  			GrInfo cod_info, final float[] l3_xmin, float xrpow[],
  			final int ch, int min_bits, int max_bits) {
  		final LameInternalFlags gfc = gfp.internal_flags;
  		GrInfo bst_cod_info = new GrInfo();
  		float bst_xrpow[] = new float[576];
  		final int Max_bits = max_bits;
  		int real_bits = max_bits + 1;
  		int this_bits = (max_bits + min_bits) / 2;
  		int dbits, over, found = 0;
  		final boolean sfb21_extra = gfc.sfb21_extra;
  
  		assert (Max_bits <= LameInternalFlags.MAX_BITS_PER_CHANNEL);
  		Arrays.fill(bst_cod_info.l3_enc, 0);
  
  		/*
  		 * search within round about 40 bits of optimal
  		 */
  		do {
  			assert (this_bits >= min_bits);
  			assert (this_bits <= max_bits);
  			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);
  
  			/*
  			 * is quantization as good as we are looking for ? in this case: is
  			 * no scalefactor band distorted?
  			 */
  			if (over <= 0) {
  				found = 1;
  				/*
  				 * now we know it can be done with "real_bits" and maybe we can
  				 * skip some iterations
  				 */
  				real_bits = cod_info.part2_3_length;
  
  				/*
  				 * store best quantization so far
  				 */
  				bst_cod_info.assign(cod_info);
  