lamejs
Version:
Pure JavaScript MP3 Encoder
1,409 lines (1,242 loc) • 53.3 kB
JavaScript
/*
* 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;
var common = require('./common.js');
var System = common.System;
var VbrMode = common.VbrMode;
var Float = common.Float;
var ShortBlock = common.ShortBlock;
var Util = common.Util;
var Arrays = common.Arrays;
var new_array_n = common.new_array_n;
var new_byte = common.new_byte;
var new_double = common.new_double;
var new_float = common.new_float;
var new_float_n = common.new_float_n;
var new_int = common.new_int;
var new_int_n = common.new_int_n;
var assert = common.assert;
var VBRQuantize = require('./VBRQuantize.js');
var CalcNoiseResult = require('./CalcNoiseResult.js');
var CalcNoiseData = require('./CalcNoiseData.js');
var Encoder = require('./Encoder.js');
var GrInfo = require('./GrInfo.js');
var L3Side = require('./L3Side.js');
function Quantize() {
var bs;
this.rv = null;
var rv;
this.qupvt = null;
var qupvt;
var vbr = new VBRQuantize();
var tk;
this.setModules = function (_bs, _rv, _qupvt, _tk) {
bs = _bs;
rv = _rv;
this.rv = _rv;
qupvt = _qupvt;
this.qupvt = _qupvt;
tk = _tk;
vbr.setModules(qupvt, tk);
}
/**
* convert from L/R <. Mid/Side
*/
this.ms_convert = function (l3_side, gr) {
for (var i = 0; i < 576; ++i) {
var l = l3_side.tt[gr][0].xr[i];
var r = l3_side.tt[gr][1].xr[i];
l3_side.tt[gr][0].xr[i] = (l + r) * (Util.SQRT2 * 0.5);
l3_side.tt[gr][1].xr[i] = (l - r) * (Util.SQRT2 * 0.5);
}
};
/**
* mt 6/99
*
* initializes cod_info, scalefac and xrpow
*
* returns 0 if all energies in xr are zero, else 1
*/
function init_xrpow_core(cod_info, xrpow, upper, sum) {
sum = 0;
for (var i = 0; i <= upper; ++i) {
var tmp = Math.abs(cod_info.xr[i]);
sum += tmp;
xrpow[i] = Math.sqrt(tmp * Math.sqrt(tmp));
if (xrpow[i] > cod_info.xrpow_max)
cod_info.xrpow_max = xrpow[i];
}
return sum;
}
this.init_xrpow = function (gfc, cod_info, xrpow) {
var sum = 0;
var upper = 0 | 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-20) {
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;
}
/**
* 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.
*/
function psfb21_analogsilence(gfc, cod_info) {
var ath = gfc.ATH;
var xr = cod_info.xr;
if (cod_info.block_type != Encoder.SHORT_TYPE) {
/* NORM, START or STOP type, but not SHORT blocks */
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-12)
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 {
/* note: short blocks coeffs are reordered */
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-12)
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;
}
}
}
}
}
}
this.init_outer_loop = function (gfc, 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 (var 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) {
var 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...
*/
var ix = gfc.scalefac_band.l[cod_info.sfb_lmax];
System.arraycopy(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;
/*
* fresh scalefactors are all zero
*/
Arrays.fill(cod_info.scalefac, 0);
psfb21_analogsilence(gfc, cod_info);
};
function BinSearchDirection(ordinal) {
this.ordinal = ordinal;
}
BinSearchDirection.BINSEARCH_NONE = new BinSearchDirection(0);
BinSearchDirection.BINSEARCH_UP = new BinSearchDirection(1);
BinSearchDirection.BINSEARCH_DOWN = new BinSearchDirection(2);
/**
* author/date??
*
* binary step size search used by outer_loop to get a quantizer step size
* to start with
*/
function bin_search_StepSize(gfc, cod_info, desired_rate, ch, xrpow) {
var 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;
assert(CurrentStep != 0);
for (; ;) {
var 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;
}
this.trancate_smallspectrums = function (gfc, gi, l3_xmin, 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 j = 0; j < 576; j++) {
var xr = 0.0;
if (gi.l3_enc[j] != 0)
xr = Math.abs(gi.xr[j]);
work[j] = xr;
}
var j = 0;
var sfb = 8;
if (gi.block_type == Encoder.SHORT_TYPE)
sfb = 6;
do {
var allowedNoise, trancateThreshold;
var 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.0))
continue;
/* all zero sfb */
allowedNoise = (1.0 - distort[sfb]) * l3_xmin[sfb];
trancateThreshold = 0.0;
start = 0;
do {
var 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.0))
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.
*/
function loop_break(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;
}
/* mt 5/99: Function: Improved calc_noise for a single channel */
function penalties(noise) {
return Util.FAST_LOG10((0.368 + 0.632 * noise * noise * noise));
}
/**
* author/date??
*
* several different codes to decide which quantization is better
*/
function get_klemm_noise(distort, 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);
}
function quant_compare(quant_comp, best, calc, gi, 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
*/
var 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 = 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>
*/
function amp_scalefac_bands(gfp, cod_info, distort, xrpow, bRefine) {
var gfc = gfp.internal_flags;
var ifqstep34;
if (cod_info.scalefac_scale == 0) {
ifqstep34 = 1.29683955465100964055;
/* 2**(.75*.5) */
} else {
ifqstep34 = 1.68179283050742922612;
/* 2**(.75*1) */
}
/* compute maximum value of distort[] */
var 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:
/* amplify exactly 1 band */
break;
case 1:
/* amplify bands within 50% of max (on db scale) */
if (trigger > 1.0)
trigger = 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.0;
else
trigger *= .95;
break;
}
var j = 0;
for (var sfb = 0; sfb < cod_info.sfbmax; sfb++) {
var width = cod_info.width[sfb];
var 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
*/
function inc_scalefac_scale(cod_info, xrpow) {
var ifqstep34 = 1.29683955465100964055;
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;
}
/**
* Takehiro Tominaga 2000-xx-xx
*
* increases the subblock gain and adjusts scalefactors
*/
function inc_subblock_gain(gfc, cod_info, xrpow) {
var sfb;
var 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 (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;
/*
* 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]++;
var j = gfc.scalefac_band.l[cod_info.sfb_lmax];
for (sfb = cod_info.sfb_lmax + window; sfb < cod_info.sfbmax; sfb += 3) {
var amp;
var width = cod_info.width[sfb];
var 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;
{
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;
}
/**
* <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>
*/
function balance_noise(gfp, cod_info, distort, xrpow, bRefine) {
var 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
*/
var 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
*/
this.outer_loop = function (gfp, cod_info, l3_xmin, xrpow, ch, 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();
var 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)
/* 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);
var age = 0;
System.arraycopy(xrpow, 0, save_xrpow, 0, 576);
while (!bEndOfSearch) {
/* BEGIN MAIN LOOP */
do {
var noise_info = new CalcNoiseResult();
var search_limit;
var 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
*/
var 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
*/
this.iteration_finish_one = function (gfc, gr, ch) {
var l3_side = gfc.l3_side;
var 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
*/
this.VBR_encode_granule = function (gfp, cod_info, l3_xmin, xrpow, ch, min_bits, 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;
var dbits, over, found = 0;
var 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);
System.arraycopy(xrpow, 0, bst_xrpow, 0, 576);
/*
* try with fewer bits
*/
max_bits = real_bits - 32;
dbits = max_bits - min_bits;
this_bits = (max_bits + min_bits) / 2;
} else {
/*
* try with more bits
*/
min_bits = this_bits + 32;
dbits = max_bits - min_bits;
this_bits = (max_bits + min_bits) / 2;
if (found != 0) {
found = 2;
/*
* start again with best quantization so far
*/
cod_info.assign(bst_cod_info);
System.arraycopy(bst_xrpow, 0, xrpow, 0, 576);
}
}
} while (dbits > 12);
gfc.sfb21_extra = sfb21_extra;
/*
* found=0 => nothing found, use last one found=1 => we just found the
* best and left the loop found=2 => we restored a good one and have now
* l3_enc to restore too
*/
if (found == 2) {
System.arraycopy(bst_cod_info.l3_enc, 0, cod_info.l3_enc, 0, 576);
}
assert(cod_info.part2_3_length <= Max_bits);
}
/**
* 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
*/
this.get_framebits = function (gfp, frameBits) {
var gfc = gfp.internal_flags;
/*
* always use at least this many bits per granule per channel unless we
* detect analog silence, see below
*/
gfc.bitrate_index = gfc.VBR_min_bitrate;
var bitsPerFrame = bs.getframebits(gfp);
/*
* bits for analog silence
*/
gfc.bitrate_index = 1;
bitsPerFrame = bs.getframebits(gfp);
for (var i = 1; i <= gfc.VBR_max_bitrate; i++) {
gfc.bitrate_index = i;
var mb = new MeanBits(bitsPerFrame);
frameBits[i] = rv.ResvFrameBegin(gfp, mb);
bitsPerFrame = mb.bits;
}
};
/* RH: this one needs to be overhauled sometime */
/**
* <PRE>
* 2000-09-04 Robert Hegemann
*
* * converts LR to MS coding when necessary
* * calculates allowed/adjusted quantization noise amounts
* * detects analog silent frames
*
* some remarks:
* - lower masking depending on Quality setting
* - quality control together with adjusted ATH MDCT scaling
* on lower quality setting allocate more noise from
* ATH masking, and on higher quality setting allocate
* less noise from ATH masking.
* - experiments show that going more than 2dB over GPSYCHO's
* limits ends up in very annoying artefacts
* </PRE>
*/
this.VBR_old_prepare = function (gfp, pe, ms_ener_ratio, ratio, l3_xmin, frameBits, min_bits,
max_bits, bands) {
var gfc = gfp.internal_flags;
var masking_lower_db, adjust = 0.0;
var analog_silence = 1;
var bits = 0;
gfc.bitrate_index = gfc.VBR_max_bitrate;
var avg = rv.ResvFrameBegin(gfp, new MeanBits(0)) / gfc.mode_gr;
get_framebits(gfp, frameBits);
for (var gr = 0; gr < gfc.mode_gr; gr++) {
var mxb = qupvt.on_pe(gfp, pe, max_bits[gr], avg, gr, 0);
if (gfc.mode_ext == Encoder.MPG_MD_MS_LR) {
ms_convert(gfc.l3_side, gr);
qupvt.reduce_side(max_bits[gr], ms_ener_ratio[gr], avg, mxb);
}
for (var ch = 0; ch < gfc.channels_out; ++ch) {
var cod_info = gfc.l3_side.tt[gr][ch];
if (cod_info.block_type != Encoder.SHORT_TYPE) {
// NORM, START or STOP type
adjust = 1.28 / (1 + Math
.exp(3.5 - pe[gr][ch] / 300.)) - 0.05;
masking_lower_db = gfc.PSY.mask_adjust - adjust;
} else {
adjust = 2.56 / (1 + Math
.exp(3.5 - pe[gr][ch] / 300.)) - 0.14;
masking_lower_db = gfc.PSY.mask_adjust_short - adjust;
}
gfc.masking_lower = Math.pow(10.0,
masking_lower_db * 0.1);
init_outer_loop(gfc, cod_info);
bands[gr][ch] = qupvt.calc_xmin(gfp, ratio[gr][ch], cod_info,
l3_xmin[gr][ch]);
if (bands[gr][ch] != 0)
analog_silence = 0;
min_bits[gr][ch] = 126;
bits += max_bits[gr][ch];
}
}
for (var gr = 0; gr < gfc.mode_gr; gr++) {
for (var ch = 0; ch < gfc.channels_out; ch++) {
if (bits > frameBits[gfc.VBR_max_bitrate]) {
max_bits[gr][ch] *= frameBits[gfc.VBR_max_bitrate];
max_bits[gr][ch] /= bits;
}
if (min_bits[gr][ch] > max_bits[gr][ch])
min_bits[gr][ch] = max_bits[gr][ch];
}
/* for ch */
}
/* for gr */
return analog_silence;
};
this.bitpressure_strategy = function (gfc, l3_xmin, min_bits, max_bits) {
for (var gr = 0; gr < gfc.mode_gr; gr++) {
for (var ch = 0; ch < gfc.channels_out; ch++) {
var gi = gfc.l3_side.tt[gr][ch];
var pxmin = l3_xmin[gr][ch];
var pxminPos = 0;
for (var sfb = 0; sfb < gi.psy_lmax; sfb++)
pxmin[pxminPos++] *= 1. + .029 * sfb * sfb
/ Encoder.SBMAX_l / Encoder.SBMAX_l;
if (gi.block_type == Encoder.SHORT_TYPE) {
for (var sfb = gi.sfb_smin; sfb < Encoder.SBMAX_s; sfb++) {
pxmin[pxminPos++] *= 1. + .029 * sfb * sfb
/ Encoder.SBMAX_s / Encoder.SBMAX_s;
pxmin[pxminPos++] *= 1. + .029 * sfb * sfb
/ Encoder.SBMAX_s / Encoder.SBMAX_s;
pxmin[pxminPos++] *= 1. + .029 * sfb * sfb
/ Encoder.SBMAX_s / Encoder.SBMAX_s;
}
}
max_bits[gr][ch] = 0 | Math.max(min_bits[gr][ch],
0.9 * max_bits[gr][ch]);
}
}
};
this.VBR_new_prepare = function (gfp, pe, ratio, l3_xmin, frameBits, max_bits) {
var gfc = gfp.internal_flags;
var analog_silence = 1;
var avg = 0, bits = 0;
var maximum_framebits;
if (!gfp.free_format) {
gfc.bitrate_index = gfc.VBR_max_bitrate;
var mb = new MeanBits(avg);
rv.ResvFrameBegin(gfp, mb);
avg = mb.bits;
get_framebits(gfp, frameBits);
maximum_framebits = frameBits[gfc.VBR_max_bitrate];
} else {
gfc.bitrate_index = 0;
var mb = new MeanBits(avg);
maximum_framebits = rv.ResvFrameBegin(gfp, mb);
avg = mb.bits;
frameBits[0] = maximum_framebits;
}
for (var gr = 0; gr < gfc.mode_gr; gr++) {
qupvt.on_pe(gfp, pe, max_bits[gr], avg, gr, 0);
if (gfc.mode_ext == Encoder.MPG_MD_MS_LR) {
ms_convert(gfc.l3_side, gr);
}
for (var ch = 0; ch < gfc.channels_out; ++ch) {
var cod_info = gfc.l3_side.tt[gr][ch];
gfc.masking_lower = Math.pow(10.0,
gfc.PSY.mask_adjust * 0.1);
init_outer_loop(gfc, cod_info);
if (0 != qupvt.calc_xmin(gfp, ratio[gr][ch], cod_info,
l3_xmin[gr][ch]))
analog_silence = 0;
bits += max_bits[gr][ch];
}
}
for (var gr = 0; gr < gfc.mode_gr; gr++) {
for (var ch = 0; ch < gfc.channels_out; ch++) {
if (bits > maximum_framebits) {
max_bits[gr][ch] *= maximum_framebits;
max_bits[gr][ch] /= bits;
}
}
/* for ch */
}
/* for gr */
return analog_silence;
};
/**
* calculates target bits for ABR encoding
*
* mt 2000/05/31
*/
this.calc_target_bits = function (gfp, pe, ms_ener_ratio, targ_bits, analog_silence_bits, max_frame_bits) {
var gfc = gfp.internal_flags;
var l3_side = gfc.l3_side;
var res_factor;
var gr, ch, totbits, mean_bits = 0;
gfc.bitrate_index = gfc.VBR_max_bitrate;
var mb = new MeanBits(mean_bits);
max_frame_bits[0] = rv.ResvFrameBegin(gfp, mb);
mean_bits = mb.bits;
gfc.bitrate_index = 1;
mean_bits = bs.getframebits(gfp) - gfc.sideinfo_len * 8;
analog_silence_bits[0] = mean_bits / (gfc.mode_gr * gfc.channels_out);
mean_bits = gfp.VBR_mean_bitrate_kbps * gfp.framesize * 1000;
if ((gfc.substep_shaping & 1) != 0)
mean_bits *= 1.09;
mean_bits /= gfp.out_samplerate;
mean_bits -= gfc.sideinfo_len * 8;
mean_bits /= (gfc.mode_gr * gfc.channels_out);
/**
* <PRE>
* res_factor is the percentage of the target bitrate that should
* be used on average. the remaining bits are added to the
* bitreservoir and used for difficult to encode frames.
*
* Since we are tracking the average bitrate, we should adjust
* res_factor "on the fly", increasing it if the average bitrate
* is greater than the requested bitrate, and decreasing it
* otherwise. Reasonable ranges are from .9 to 1.0
*
* Until we get the above suggestion working, w