/*
* MP3 quantization
*
* Copyright (c) 1999-2000 Mark Taylor
* Copyright (c) 2000-2005 Robert Hegemann
*
* 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: vbrquantize.c,v 1.103.2.1 2005/11/20 14:08:25 bouvigne Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include "util.h"
#include "l3side.h"
#include "quantize_pvt.h"
#include "vbrquantize.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#endif
struct algo_s;
typedef struct algo_s algo_t;
typedef void (*quantize_f) (const algo_t *);
typedef int (*find_f) (const FLOAT *, const FLOAT *, FLOAT, int, int);
typedef int (*alloc_sf_f) (const algo_t *, int *, const int *, int);
struct algo_s {
find_f find;
quantize_f quantize;
alloc_sf_f alloc;
const FLOAT *xr34orig;
lame_internal_flags *gfc;
gr_info *cod_info;
int mingain_l;
int mingain_s[3];
};
/* Remarks on optimizing compilers:
*
* the MSVC compiler may get into aliasing problems when accessing
* memory through the fi_union. declaring it volatile does the trick here
*
* the calc_sfb_noise_* functions are not inlined because the intel compiler
* optimized executeables won't work as expected anymore
*/
#ifdef _MSC_VER
# define VOLATILE volatile
#else
# define VOLATILE
#endif
typedef VOLATILE union {
float f;
int i;
} fi_union;
#define DOUBLEX double
#define MAGIC_FLOAT_def (65536*(128))
#define MAGIC_INT_def 0x4b000000
#ifdef TAKEHIRO_IEEE754_HACK
# define ROUNDFAC_def -0.0946f
#else
/*********************************************************************
* XRPOW_FTOI is a macro to convert floats to ints.
* if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x]
* ROUNDFAC= -0.0946
*
* if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x]
* ROUNDFAC=0.4054
*********************************************************************/
# define QUANTFAC(rx) adj43[rx]
# define ROUNDFAC_def 0.4054f
# define XRPOW_FTOI(src,dest) ((dest) = (int)(src))
#endif
static int const MAGIC_INT = MAGIC_INT_def;
static DOUBLEX const ROUNDFAC = ROUNDFAC_def;
static DOUBLEX const MAGIC_FLOAT = (65536 * (128));
static DOUBLEX const ROUNDFAC_plus_MAGIC_FLOAT = ROUNDFAC_def + MAGIC_FLOAT_def;
static int
valid_sf(int sf)
{
return (sf >= 0 ? (sf <= 255 ? sf : 255) : 0);
}
static FLOAT
max_x34(const FLOAT * xr34, unsigned int bw)
{
FLOAT xfsf = 0;
int j = bw >> 1;
int remaining = j % 2;
assert(bw >= 0);
for (j >>= 1; j > 0; --j) {
if (xfsf < xr34[0]) {
xfsf = xr34[0];
}
if (xfsf < xr34[1]) {
xfsf = xr34[1];
}
if (xfsf < xr34[2]) {
xfsf = xr34[2];
}
if (xfsf < xr34[3]) {
xfsf = xr34[3];
}
xr34 += 4;
}
if (remaining) {
if (xfsf < xr34[0]) {
xfsf = xr34[0];
}
if (xfsf < xr34[1]) {
xfsf = xr34[1];
}
}
return xfsf;
}
static int
find_lowest_scalefac(const FLOAT xr34)
{
FLOAT xfsf;
int sf = 128, sf_ok = 10000, delsf = 128, i;
for (i = 0; i < 8; ++i) {
delsf >>= 1;
xfsf = IPOW20(sf) * xr34;
if (xfsf <= IXMAX_VAL) {
sf_ok = sf;
sf -= delsf;
}
else {
sf += delsf;
}
}
if (sf_ok < 255) {
sf = sf_ok;
}
return sf;
}
static void
k_34_4(DOUBLEX x[4], int l3[4])
{
#ifdef TAKEHIRO_IEEE754_HACK
fi_union fi[4];
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL);
x[0] += MAGIC_FLOAT;
fi[0].f = x[0];
x[1] += MAGIC_FLOAT;
fi[1].f = x[1];
x[2] += MAGIC_FLOAT;
fi[2].f = x[2];
x[3] += MAGIC_FLOAT;
fi[3].f = x[3];
fi[0].f = x[0] + adj43asm[fi[0].i - MAGIC_INT];
fi[1].f = x[1] + adj43asm[fi[1].i - MAGIC_INT];
fi[2].f = x[2] + adj43asm[fi[2].i - MAGIC_INT];
fi[3].f = x[3] + adj43asm[fi[3].i - MAGIC_INT];
l3[0] = fi[0].i - MAGIC_INT;
l3[1] = fi[1].i - MAGIC_INT;
l3[2] = fi[2].i - MAGIC_INT;
l3[3] = fi[3].i - MAGIC_INT;
#else
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL);
XRPOW_FTOI(x[0], l3[0]);
XRPOW_FTOI(x[1], l3[1]);
XRPOW_FTOI(x[2], l3[2]);
XRPOW_FTOI(x[3], l3[3]);
x[0] += QUANTFAC(l3[0]);
x[1] += QUANTFAC(l3[1]);
x[2] += QUANTFAC(l3[2]);
x[3] += QUANTFAC(l3[3]);
XRPOW_FTOI(x[0], l3[0]);
XRPOW_FTOI(x[1], l3[1]);
XRPOW_FTOI(x[2], l3[2]);
XRPOW_FTOI(x[3], l3[3]);
#endif
}
static void
k_34_2(DOUBLEX x[2], int l3[2])
{
#ifdef TAKEHIRO_IEEE754_HACK
fi_union fi[2];
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL);
x[0] += MAGIC_FLOAT;
fi[0].f = x[0];
x[1] += MAGIC_FLOAT;
fi[1].f = x[1];
fi[0].f = x[0] + adj43asm[fi[0].i - MAGIC_INT];
fi[1].f = x[1] + adj43asm[fi[1].i - MAGIC_INT];
l3[0] = fi[0].i - MAGIC_INT;
l3[1] = fi[1].i - MAGIC_INT;
#else
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL);
XRPOW_FTOI(x[0], l3[0]);
XRPOW_FTOI(x[1], l3[1]);
x[0] += QUANTFAC(l3[0]);
x[1] += QUANTFAC(l3[1]);
XRPOW_FTOI(x[0], l3[0]);
XRPOW_FTOI(x[1], l3[1]);
#endif
}
static void
k_iso_4(DOUBLEX x[4], int l3[4])
{
#ifdef TAKEHIRO_IEEE754_HACK
fi_union fi[4];
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL);
x[0] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[0].f = x[0];
x[1] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[1].f = x[1];
x[2] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[2].f = x[2];
x[3] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[3].f = x[3];
l3[0] = fi[0].i - MAGIC_INT;
l3[1] = fi[1].i - MAGIC_INT;
l3[2] = fi[2].i - MAGIC_INT;
l3[3] = fi[3].i - MAGIC_INT;
#else
l3[0] = x[0] + ROUNDFAC;
l3[1] = x[1] + ROUNDFAC;
l3[2] = x[2] + ROUNDFAC;
l3[3] = x[3] + ROUNDFAC;
#endif
}
static void
k_iso_2(DOUBLEX x[2], int l3[2])
{
#ifdef TAKEHIRO_IEEE754_HACK
fi_union fi[2];
assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL);
x[0] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[0].f = x[0];
x[1] += ROUNDFAC_plus_MAGIC_FLOAT;
fi[1].f = x[1];
l3[0] = fi[0].i - MAGIC_INT;
l3[1] = fi[1].i - MAGIC_INT;
#else
l3[0] = x[0] + ROUNDFAC;
l3[1] = x[1] + ROUNDFAC;
#endif
}
/* do call the calc_sfb_noise_* functions only with sf values
* for which holds: sfpow34*xr34 <= IXMAX_VAL
*/
static FLOAT
calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, unsigned int bw, int sf)
{
DOUBLEX x[4];
int l3[4];
const int SF = valid_sf(sf);
const FLOAT sfpow = POW20(SF); /*pow(2.0,sf/4.0); */
const FLOAT sfpow34 = IPOW20(SF); /*pow(sfpow,-3.0/4.0); */
FLOAT xfsf = 0;
int j = bw >> 1;
int remaining = j % 2;
assert(bw >= 0);
for (j >>= 1; j > 0; --j) {
x[0] = sfpow34 * xr34[0];
x[1] = sfpow34 * xr34[1];
x[2] = sfpow34 * xr34[2];
x[3] = sfpow34 * xr34[3];
k_34_4(x, l3);
x[0] = fabs(xr[0]) - sfpow * pow43[l3[0]];
x[1] = fabs(xr[1]) - sfpow * pow43[l3[1]];
x[2] = fabs(xr[2]) - sfpow * pow43[l3[2]];
x[3] = fabs(xr[3]) - sfpow * pow43[l3[3]];
xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]);
xr += 4;
xr34 += 4;
}
if (remaining) {
x[0] = sfpow34 * xr34[0];
x[1] = sfpow34 * xr34[1];
k_34_2(x, l3);
x[0] = fabs(xr[0]) - sfpow * pow43[l3[0]];
x[1] = fabs(xr[1]) - sfpow * pow43[l3[1]];
xfsf += x[0] * x[0] + x[1] * x[1];
}
return xfsf;
}
static FLOAT
calc_sfb_noise_ISO(const FLOAT * xr, const FLOAT * xr34, unsigned int bw, int sf)
{
DOUBLEX x[4];
int l3[4];
const int SF = valid_sf(sf);
const FLOAT sfpow = POW20(SF); /*pow(2.0,sf/4.0); */
const FLOAT sfpow34 = IPOW20(SF); /*pow(sfpow,-3.0/4.0); */
FLOAT xfsf = 0;
int j = bw >> 1;
int remaining = j % 2;
assert(bw >= 0);
for (j >>= 1; j > 0; --j) {
x[0] = sfpow34 * xr34[0];
x[1] = sfpow34 * xr34[1];
x[2] = sfpow34 * xr34[2];
x[3] = sfpow34 * xr34[3];
k_iso_4(x, l3);
x[0] = fabs(xr[0]) - sfpow * pow43[l3[0]];
x[1] = fabs(xr[1]) - sfpow * pow43[l3[1]];
x[2] = fabs(xr[2]) - sfpow * pow43[l3[2]];
x[3] = fabs(xr[3]) - sfpow * pow43[l3[3]];
xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]);
xr += 4;
xr34 += 4;
}
if (remaining) {
x[0] = sfpow34 * xr34[0];
x[1] = sfpow34 * xr34[1];
k_iso_2(x, l3);
x[0] = fabs(xr[0]) - sfpow * pow43[l3[0]];
x[1] = fabs(xr[1]) - sfpow * pow43[l3[1]];
xfsf += x[0] * x[0] + x[1] * x[1];
}
return xfsf;
}
/* the find_scalefac* routines calculate
* a quantization step size which would
* introduce as much noise as is allowed.
* The larger the step size the more
* quantization noise we'll get. The
* scalefactors are there to lower the
* global step size, allowing limited
* differences in quantization step sizes
* per band (shaping the noise).
*/
static int
find_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, int bw, int sf_min)
{
int sf = 128, sf_ok = 10000, delsf = 128, i;
for (i = 0; i < 8; ++i) {
delsf >>= 1;
if (sf <= sf_min) {
sf += delsf;
}
else {
if ((sf < 255 && calc_sfb_noise_x34(xr, xr34, bw, sf + 1) > l3_xmin)
|| calc_sfb_noise_x34(xr, xr34, bw, sf) > l3_xmin
|| calc_sfb_noise_x34(xr, xr34, bw, sf - 1) > l3_xmin) {
/* distortion. try a smaller scalefactor */
sf -= delsf;
}
else {
sf_ok = sf;
sf += delsf;
}
}
}
/* returning a scalefac without distortion, if possible
*/
if (sf_ok <= 255) {
sf = sf_ok;
}
return sf;
}
static int
find_scalefac_ISO(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, int bw, int sf_min)
{
int sf = 128, sf_ok = 10000, delsf = 128, i;
for (i = 0; i < 8; ++i) {
delsf >>= 1;
if (sf <= sf_min) {
sf += delsf;
}
else {
if ((sf < 255 && calc_sfb_noise_ISO(xr, xr34, bw, sf + 1) > l3_xmin)
|| calc_sfb_noise_ISO(xr, xr34, bw, sf) > l3_xmin
|| calc_sfb_noise_ISO(xr, xr34, bw, sf - 1) > l3_xmin) {
/* distortion. try a smaller scalefactor */
sf -= delsf;
}
else {
sf_ok = sf;
sf += delsf;
}
}
}
/* returning a scalefac without distortion, if possible
*/
if (sf_ok <= 255) {
sf = sf_ok;
}
return sf;
}
/***********************************************************************
*
* calc_short_block_vbr_sf()
* calc_long_block_vbr_sf()
*
* Mark Taylor 2000-??-??
* Robert Hegemann 2000-10-25 made functions of it
*
***********************************************************************/
/* a variation for vbr-mtrh */
static int
block_sf(algo_t * that, const FLOAT l3_xmin[576], int vbrsf[SFBMAX], int vbrsfmin[SFBMAX])
{
FLOAT max_xr34;
const FLOAT *xr = &that->cod_info->xr[0];
const FLOAT *xr34_orig = &that->xr34orig[0];
const int *width = &that->cod_info->width[0];
const int max_nonzero_coeff = that->cod_info->max_nonzero_coeff;
int maxsf = 0;
int sfb = 0, j = 0, i = 0;
int const psymax = that->cod_info->psymax;
that->mingain_l = 0;
that->mingain_s[0] = 0;
that->mingain_s[1] = 0;
that->mingain_s[2] = 0;
while (j <= max_nonzero_coeff) {
int l, w = l = width[sfb];
int m = max_nonzero_coeff - j + 1, m1, m2;
if (l > m) {
l = m;
}
max_xr34 = max_x34(&xr34_orig[j], l);
m1 = find_lowest_scalefac(max_xr34);
vbrsfmin[sfb] = m1;
if (that->mingain_l < m1) {
that->mingain_l = m1;
}
if (that->mingain_s[i] < m1) {
that->mingain_s[i] = m1;
}
if (i < 2) {
++i;
}
else {
i = 0;
}
if (sfb < psymax) {
m2 = that->find(&xr[j], &xr34_orig[j], l3_xmin[sfb], l, m1);
if (maxsf < m2) {
maxsf = m2;
}
}
else {
if (maxsf < m1) {
maxsf = m1;
}
m2 = maxsf;
}
vbrsf[sfb] = m2;
++sfb;
j += w;
}
for (; sfb < SFBMAX; ++sfb) {
vbrsf[sfb] = maxsf;
vbrsfmin[sfb] = 0;
}
return maxsf;
}
/***********************************************************************
*
* quantize xr34 based on scalefactors
*
* block_xr34
*
* Mark Taylor 2000-??-??
* Robert Hegemann 2000-10-20 made functions of them
*
***********************************************************************/
static void
quantize_x34(const algo_t * that)
{
DOUBLEX x[4];
const FLOAT *xr34_orig = that->xr34orig;
gr_info *cod_info = that->cod_info;
int *l3 = cod_info->l3_enc;
int j = 0, sfb = 0;
const int max_nonzero_coeff = cod_info->max_nonzero_coeff;
while (j <= max_nonzero_coeff) {
const int s = ((cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0))
<< (cod_info->scalefac_scale + 1))
+ cod_info->subblock_gain[cod_info->window[sfb]] * 8;
const int sfac = valid_sf(cod_info->global_gain - s);
const FLOAT sfpow34 = IPOW20(sfac);
int remaining;
int l , w = l = cod_info->width[sfb];
int m = max_nonzero_coeff - j + 1;
if (l > m) {
l = m;
}
j += w;
++sfb;
l >>= 1;
remaining = l % 2;
for (l >>= 1; l > 0; --l) {
x[0] = sfpow34 * xr34_orig[0];
x[1] = sfpow34 * xr34_orig[1];
x[2] = sfpow34 * xr34_orig[2];
x[3] = sfpow34 * xr34_orig[3];
k_34_4(x, l3);
l3 += 4;
xr34_orig += 4;
}
if (remaining) {
x[0] = sfpow34 * xr34_orig[0];
x[1] = sfpow34 * xr34_orig[1];
k_34_2(x, l3);
l3 += 2;
xr34_orig += 2;
}
}
}
static void
quantize_ISO(const algo_t * that)
{
DOUBLEX x[4];
const FLOAT *xr34_orig = that->xr34orig;
gr_info *cod_info = that->cod_info;
int *l3 = cod_info->l3_enc;
int j = 0, sfb = 0;
const int max_nonzero_coeff = cod_info->max_nonzero_coeff;
while (j <= max_nonzero_coeff) {
const int s = ((cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0))
<< (cod_info->scalefac_scale + 1))
+ cod_info->subblock_gain[cod_info->window[sfb]] * 8;
const int sfac = valid_sf(cod_info->global_gain - s);
const FLOAT sfpow34 = IPOW20(sfac);
int remaining;
int l, w = l = cod_info->width[sfb];
int m = max_nonzero_coeff - j + 1;
if (l > m) {
l = m;
}
j += w;
++sfb;
l >>= 1;
remaining = l % 2;
for (l >>= 1; l > 0; --l) {
x[0] = sfpow34 * xr34_orig[0];
x[1] = sfpow34 * xr34_orig[1];
x[2] = sfpow34 * xr34_orig[2];
x[3] = sfpow34 * xr34_orig[3];
k_iso_4(x, l3);
l3 += 4;
xr34_orig += 4;
}
if (remaining) {
x[0] = sfpow34 * xr34_orig[0];
x[1] = sfpow34 * xr34_orig[1];
k_iso_2(x, l3);
l3 += 2;
xr34_orig += 2;
}
}
}
static const int max_range_short[SBMAX_s * 3] = {
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0, 0, 0
};
static const int max_range_long[SBMAX_l] =
{ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0
};
static const int max_range_long_lsf_pretab[SBMAX_l] =
{ 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*
sfb=0..5 scalefac < 16
sfb>5 scalefac < 8
ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4;
ol_sf = (cod_info->global_gain-210.0);
ol_sf -= 8*cod_info->subblock_gain[i];
ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i];
*/
static void
set_subblock_gain(gr_info * cod_info, const int mingain_s[3], int sf[])
{
const int maxrange1 = 15, maxrange2 = 7;
const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2;
int *sbg = cod_info->subblock_gain;
int psymax = cod_info->psymax;
int psydiv = 18;
int sbg0, sbg1, sbg2;
int sfb, i;
if (psydiv > psymax) {
psydiv = psymax;
}
for (i = 0; i < 3; ++i) {
int maxsf1 = 0, maxsf2 = 0, minsf = 1000;
/* see if we should use subblock gain */
for (sfb = i; sfb < psydiv; sfb += 3) { /* part 1 */
int v = -sf[sfb];
if (maxsf1 < v) {
maxsf1 = v;
}
if (minsf > v) {
minsf = v;
}
}
for (; sfb < SFBMAX; sfb += 3) { /* part 2 */
int v = -sf[sfb];
if (maxsf2 < v) {
maxsf2 = v;
}
if (minsf > v) {
minsf = v;
}
}
/* boost subblock gain as little as possible so we can
* reach maxsf1 with scalefactors
* 8*sbg >= maxsf1
*/
{
int m1 = maxsf1 - (maxrange1 << ifqstepShift);
int m2 = maxsf2 - (maxrange2 << ifqstepShift);
maxsf1 = Max(m1, m2);
}
if (minsf > 0) {
sbg[i] = minsf >> 3;
}
else {
sbg[i] = 0;
}
if (maxsf1 > 0) {
int m1 = sbg[i];
int m2 = (maxsf1 + 7) >> 3;
sbg[i] = Max(m1, m2);
}
if (sbg[i] > 0 && mingain_s[i] > (cod_info->global_gain - sbg[i] * 8)) {
sbg[i] = (cod_info->global_gain - mingain_s[i]) >> 3;
}
if (sbg[i] > 7) {
sbg[i] = 7;
}
}
sbg0 = sbg[0] << 3;
sbg1 = sbg[1] << 3;
sbg2 = sbg[2] << 3;
for (sfb = 0; sfb < SFBMAX; sfb += 3) {
sf[sfb + 0] += sbg0;
sf[sfb + 1] += sbg1;
sf[sfb + 2] += sbg2;
}
}
/*
ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4;
ol_sf = (cod_info->global_gain-210.0);
ol_sf -= ifqstep*scalefac[gr][ch].l[sfb];
if (cod_info->preflag && sfb>=11)
ol_sf -= ifqstep*pretab[sfb];
*/
static void
set_scalefacs(gr_info * cod_info, const int *vbrsfmin, int sf[], const int *max_range)
{
const int ifqstep = (cod_info->scalefac_scale == 0) ? 2 : 4;
const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2;
int *scalefac = cod_info->scalefac;
int sfb, sfbmax = cod_info->sfbmax;
int *sbg = cod_info->subblock_gain;
int *window = cod_info->window;
int preflag = cod_info->preflag;
if (preflag) {
for (sfb = 11; sfb < sfbmax; ++sfb) {
sf[sfb] += pretab[sfb] << ifqstepShift;
}
}
for (sfb = 0; sfb < sfbmax; ++sfb) {
int gain = cod_info->global_gain - (sbg[window[sfb]] << 3)
- ((preflag ? pretab[sfb] : 0) << ifqstepShift);
if (sf[sfb] < 0) {
int m = gain - vbrsfmin[sfb];
/* ifqstep*scalefac >= -sf[sfb], so round UP */
scalefac[sfb] = (ifqstep - 1 - sf[sfb]) >> ifqstepShift;
if (scalefac[sfb] > max_range[sfb]) {
scalefac[sfb] = max_range[sfb];
}
if (scalefac[sfb] > 0 && (scalefac[sfb] << ifqstepShift) > m) {
scalefac[sfb] = m >> ifqstepShift;
}
}
else {
scalefac[sfb] = 0;
}
}
for (; sfb < SFBMAX; ++sfb) {
scalefac[sfb] = 0; /* sfb21 */
}
}
static int
checkScalefactor(const gr_info * cod_info, const int vbrsfmin[SFBMAX])
{
int sfb;
for (sfb = 0; sfb < cod_info->psymax; ++sfb) {
const int s =
((cod_info->scalefac[sfb] +
(cod_info->preflag ? pretab[sfb] : 0)) << (cod_info->
scalefac_scale + 1)) +
cod_info->subblock_gain[cod_info->window[sfb]] * 8;
if ((cod_info->global_gain - s) < vbrsfmin[sfb]) {
/*
fprintf( stdout, "sf %d\n", sfb );
fprintf( stdout, "min %d\n", vbrsfmin[sfb] );
fprintf( stdout, "ggain %d\n", cod_info->global_gain );
fprintf( stdout, "scalefac %d\n", cod_info->scalefac[sfb] );
fprintf( stdout, "pretab %d\n", (cod_info->preflag ? pretab[sfb] : 0) );
fprintf( stdout, "scale %d\n", (cod_info->scalefac_scale + 1) );
fprintf( stdout, "subgain %d\n", cod_info->subblock_gain[cod_info->window[sfb]] * 8 );
fflush( stdout );
exit(-1);
*/
return 0;
}
}
return 1;
}
/******************************************************************
*
* short block scalefacs
*
******************************************************************/
static int
short_block_constrain(const algo_t * that, int vbrsf[SFBMAX],
const int vbrsfmin[SFBMAX], int vbrmax)
{
gr_info *cod_info = that->cod_info;
lame_internal_flags *gfc = that->gfc;
int const maxminsfb = that->mingain_l;
int mover, maxover0 = 0, maxover1 = 0, delta = 0;
int v, v0, v1;
int sfb;
int psymax = cod_info->psymax;
for (sfb = 0; sfb < psymax; ++sfb) {
assert( vbrsf[sfb] >= vbrsfmin[sfb] );
v = vbrmax - vbrsf[sfb];
if (delta < v) {
delta = v;
}
v0 = v - (4 * 14 + 2 * max_range_short[sfb]);
v1 = v - (4 * 14 + 4 * max_range_short[sfb]);
if (maxover0 < v0) {
maxover0 = v0;
}
if (maxover1 < v1) {
maxover1 = v1;
}
}
if (gfc->noise_shaping == 2) {
/* allow scalefac_scale=1 */
mover = Min(maxover0, maxover1);
}
else {
mover = maxover0;
}
if (delta > mover) {
delta = mover;
}
vbrmax -= delta;
maxover0 -= mover;
maxover1 -= mover;
if (maxover0 == 0) {
cod_info->scalefac_scale = 0;
}
else if (maxover1 == 0) {
cod_info->scalefac_scale = 1;
}
if (vbrmax < maxminsfb) {
vbrmax = maxminsfb;
}
cod_info->global_gain = vbrmax;
if (cod_info->global_gain < 0) {
cod_info->global_gain = 0;
}
else if (cod_info->global_gain > 255) {
cod_info->global_gain = 255;
}
for (sfb = 0; sfb < SFBMAX; ++sfb) {
vbrsf[sfb] -= vbrmax;
}
set_subblock_gain(cod_info, &that->mingain_s[0], vbrsf);
set_scalefacs(cod_info, vbrsfmin, vbrsf, max_range_short);
assert(checkScalefactor(cod_info, vbrsfmin));
return checkScalefactor(cod_info, vbrsfmin);
}
/******************************************************************
*
* long block scalefacs
*
******************************************************************/
static int
long_block_constrain(const algo_t * that, int vbrsf[SFBMAX], const int vbrsfmin[SFBMAX], int vbrmax)
{
gr_info *cod_info = that->cod_info;
lame_internal_flags *gfc = that->gfc;
const int *max_rangep;
int const maxminsfb = that->mingain_l;
int sfb;
int maxover0, maxover1, maxover0p, maxover1p, mover, delta = 0;
int v, v0, v1, v0p, v1p, vm0p = 1, vm1p = 1;
int psymax = cod_info->psymax;
max_rangep = gfc->mode_gr == 2 ? max_range_long : max_range_long_lsf_pretab;
maxover0 = 0;
maxover1 = 0;
maxover0p = 0; /* pretab */
maxover1p = 0; /* pretab */
for (sfb = 0; sfb < psymax; ++sfb) {
assert( vbrsf[sfb] >= vbrsfmin[sfb] );
v = vbrmax - vbrsf[sfb];
if (delta < v) {
delta = v;
}
v0 = v - 2 * max_range_long[sfb];
v1 = v - 4 * max_range_long[sfb];
v0p = v - 2 * (max_rangep[sfb] + pretab[sfb]);
v1p = v - 4 * (max_rangep[sfb] + pretab[sfb]);
if (maxover0 < v0) {
maxover0 = v0;
}
if (maxover1 < v1) {
maxover1 = v1;
}
if (maxover0p < v0p) {
maxover0p = v0p;
}
if (maxover1p < v1p) {
maxover1p = v1p;
}
}
if (vm0p == 1) {
int gain = vbrmax - maxover0p;
if (gain < maxminsfb) {
gain = maxminsfb;
}
for (sfb = 0; sfb < psymax; ++sfb) {
int a = (gain - vbrsfmin[sfb]) - 2 * pretab[sfb];
if (a <= 0) {
vm0p = 0;
vm1p = 0;
break;
}
}
}
if (vm1p == 1) {
int gain = vbrmax - maxover1p;
if (gain < maxminsfb) {
gain = maxminsfb;
}
for (sfb = 0; sfb < psymax; ++sfb) {
int b = (gain - vbrsfmin[sfb]) - 4 * pretab[sfb];
if (b <= 0) {
vm1p = 0;
break;
}
}
}
if (vm0p == 0) {
maxover0p = maxover0;
}
if (vm1p == 0) {
maxover1p = maxover1;
}
if (gfc->noise_shaping != 2) {
maxover1 = maxover0;
maxover1p = maxover0p;
}
mover = Min(maxover0, maxover0p);
mover = Min(mover, maxover1);
mover = Min(mover, maxover1p);
if (delta > mover) {
delta = mover;
}
vbrmax -= delta;
if (vbrmax < maxminsfb) {
vbrmax = maxminsfb;
}
maxover0 -= mover;
maxover0p -= mover;
maxover1 -= mover;
maxover1p -= mover;
if (maxover0 == 0) {
cod_info->scalefac_scale = 0;
cod_info->preflag = 0;
max_rangep = max_range_long;
}
else if (maxover0p == 0) {
cod_info->scalefac_scale = 0;
cod_info->preflag = 1;
}
else if (maxover1 == 0) {
cod_info->scalefac_scale = 1;
cod_info->preflag = 0;
max_rangep = max_range_long;
}
else if (maxover1p == 0) {
cod_info->scalefac_scale = 1;
cod_info->preflag = 1;
}
else {
assert(0); /* this should not happen */
}
cod_info->global_gain = vbrmax;
if (cod_info->global_gain < 0) {
cod_info->global_gain = 0;
}
else if (cod_info->global_gain > 255) {
cod_info->global_gain = 255;
}
for (sfb = 0; sfb < SFBMAX; ++sfb) {
vbrsf[sfb] -= vbrmax;
}
set_scalefacs(cod_info, vbrsfmin, vbrsf, max_rangep);
assert(checkScalefactor(cod_info, vbrsfmin));
return checkScalefactor(cod_info, vbrsfmin);
}
static int
bitcount(const algo_t * that)
{
if (that->gfc->mode_gr == 2) {
return scale_bitcount(that->cod_info);
}
else {
return scale_bitcount_lsf(that->gfc, that->cod_info);
}
}
static int
quantizeAndCountBits(const algo_t * that)
{
that->quantize(that);
that->cod_info->part2_3_length = noquant_count_bits(that->gfc, that->cod_info, 0);
return that->cod_info->part2_3_length;
}
static int
tryScalefacColor(const algo_t * that, int vbrsf[SFBMAX],
const int vbrsf2[SFBMAX], const int vbrsfmin[SFBMAX], int I, int M, int target)
{
FLOAT xrpow_max = that->cod_info->xrpow_max;
int i, nbits;
int gain, vbrmax = 0;
for (i = 0; i < SFBMAX; ++i) {
gain = target + (vbrsf2[i] - target) * I / M;
if (gain < vbrsfmin[i]) {
gain = vbrsfmin[i];
}
if (gain > 255) {
gain = 255;
}
if (vbrmax < gain) {
vbrmax = gain;
}
vbrsf[i] = gain;
}
if (!that->alloc(that, vbrsf, vbrsfmin, vbrmax)) {
return LARGE_BITS;
}
bitcount(that);
nbits = quantizeAndCountBits(that);
that->cod_info->xrpow_max = xrpow_max;
return nbits;
}
static void
searchScalefacColorMax(const algo_t * that, int sfwork[SFBMAX],
const int sfcalc[SFBMAX], const int vbrsfmin[SFBMAX], int bits)
{
int const psymax = that->cod_info->psymax;
int nbits, last, i, ok = -1, l = 0, r, vbrmin = 255, vbrmax = 0, M, target;
for (i = 0; i < psymax; ++i) {
if (vbrmin > sfcalc[i]) {
vbrmin = sfcalc[i];
}
if (vbrmax < sfcalc[i]) {
vbrmax = sfcalc[i];
}
}
M = vbrmax - vbrmin;
if (M == 0) {
return;
}
target = vbrmax;
for (l = 0, r = M, last = i = M / 2; l <= r; i = (l + r) / 2) {
nbits = tryScalefacColor(that, sfwork, sfcalc, vbrsfmin, i, M, target);
if (nbits < bits) {
ok = i;
l = i + 1;
}
else {
r = i - 1;
}
last = i;
}
if (last != ok) {
if (ok == -1) {
ok = 0;
}
nbits = tryScalefacColor(that, sfwork, sfcalc, vbrsfmin, ok, M, target);
}
}
#if 0
static void
searchScalefacColorMin(const algo_t * that, int sfwork[SFBMAX],
const int sfcalc[SFBMAX], const int vbrsfmin[SFBMAX], int bits)
{
int const psymax = that->cod_info->psymax;
int nbits, last, i, ok = -1, l = 0, r, vbrmin = 255, vbrmax = 0, M, target;
for (i = 0; i < psymax; ++i) {
if (vbrmin > sfcalc[i]) {
vbrmin = sfcalc[i];
}
if (vbrmax < sfcalc[i]) {
vbrmax = sfcalc[i];
}
}
M = vbrmax - vbrmin;
if (M == 0) {
return;
}
target = vbrmin;
for (l = 0, r = M, last = i = M / 2; l <= r; i = (l + r) / 2) {
nbits = tryScalefacColor(that, sfwork, sfcalc, vbrsfmin, i, M, target);
if (nbits > bits) {
ok = i;
r = i - 1;
}
else {
l = i + 1;
}
last = i;
}
if (last != ok) {
if (ok == -1) {
ok = 0;
}
nbits = tryScalefacColor(that, sfwork, sfcalc, vbrsfmin, ok, M, target);
}
}
#endif
static int
tryGlobalStepsize(const algo_t * that, const int sfwork[SFBMAX],
const int vbrsfmin[SFBMAX], int delta)
{
FLOAT xrpow_max = that->cod_info->xrpow_max;
int sftemp[SFBMAX], i, nbits;
int gain, vbrmax = 0;
for (i = 0; i < SFBMAX; ++i) {
gain = sfwork[i] + delta;
if (gain < vbrsfmin[i]) {
gain = vbrsfmin[i];
}
if (gain > 255) {
gain = 255;
}
if (vbrmax < gain) {
vbrmax = gain;
}
sftemp[i] = gain;
}
if (!that->alloc(that, sftemp, vbrsfmin, vbrmax)) {
return LARGE_BITS;
}
bitcount(that);
nbits = quantizeAndCountBits(that);
that->cod_info->xrpow_max = xrpow_max;
return nbits;
}
static void
searchGlobalStepsizeMax(const algo_t * that, const int sfwork[SFBMAX],
const int vbrsfmin[SFBMAX], int target)
{
gr_info *cod_info = that->cod_info;
const int gain = cod_info->global_gain;
int curr = gain;
int gain_ok = 1024;
int nbits = LARGE_BITS;
int l = gain, r = 512;
assert(gain >= 0);
while (l <= r) {
curr = (l + r) >> 1;
nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
if (cod_info->part2_length >= LARGE_BITS || nbits >= LARGE_BITS) {
l = curr + 1;
continue;
}
if (nbits + cod_info->part2_length < target) {
r = curr - 1;
gain_ok = curr;
}
else {
l = curr + 1;
if (gain_ok == 1024) {
gain_ok = curr;
}
}
}
if (gain_ok != curr) {
curr = gain_ok;
nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
}
}
#if 0
static void
searchGlobalStepsizeMin(const algo_t * that, const int sfwork[SFBMAX],
const int vbrsfmin[SFBMAX], int target)
{
gr_info *cod_info = that->cod_info;
const int gain = cod_info->global_gain;
int curr = gain;
int gain_ok = 1024;
int nbits = LARGE_BITS;
int l = 0, r = gain;
assert(gain >= 0);
while (l <= r) {
curr = (l + r) >> 1;
nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
if (cod_info->part2_length >= LARGE_BITS || nbits >= LARGE_BITS) {
l = curr + 1;
continue;
}
if (nbits + cod_info->part2_length < target) {
l = curr + 1;
if (gain_ok == 1024) {
gain_ok = curr;
}
}
else {
r = curr - 1;
gain_ok = curr;
}
}
if (gain_ok != curr) {
curr = gain_ok;
nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain);
}
}
#endif
/************************************************************************
*
* VBR_noise_shaping()
*
* may result in a need of too many bits, then do it CBR like
*
* Robert Hegemann 2000-10-25
*
***********************************************************************/
int
VBR_noise_shaping(lame_internal_flags * gfc, const FLOAT xr34orig[576],
const FLOAT l3_xmin[576], int maxbits, int gr, int ch)
{
int sfwork[SFBMAX];
int sfcalc[SFBMAX];
int vbrsfmin[SFBMAX];
algo_t that;
int vbrmax;
gr_info *cod_info = &gfc->l3_side.tt[gr][ch];
that.xr34orig = xr34orig;
if (gfc->quantization) {
that.find = find_scalefac_x34;
that.quantize = quantize_x34;
}
else {
that.find = find_scalefac_ISO;
that.quantize = quantize_ISO;
}
if (cod_info->block_type == SHORT_TYPE) {
that.alloc = short_block_constrain;
}
else {
that.alloc = long_block_constrain;
}
that.gfc = gfc;
that.cod_info = &gfc->l3_side.tt[gr][ch];
memset(cod_info->l3_enc, 0, 576 * sizeof(int));
vbrmax = block_sf(&that, l3_xmin, sfcalc, vbrsfmin);
memcpy(sfwork, sfcalc, SFBMAX * sizeof(int));
that.alloc(&that, sfwork, vbrsfmin, vbrmax);
if (0 != bitcount(&that)) {
/* this should not happen due to the way the scalefactors are selected
*/
cod_info->part2_3_length = LARGE_BITS;
return -1;
}
quantizeAndCountBits(&that);
if (cod_info->part2_3_length > maxbits - cod_info->part2_length) {
searchScalefacColorMax(&that, sfwork, sfcalc, vbrsfmin, maxbits);
}
if (cod_info->part2_3_length > maxbits - cod_info->part2_length) {
searchGlobalStepsizeMax(&that, sfwork, vbrsfmin, maxbits);
}
if (gfc->use_best_huffman == 2) {
best_huffman_divide(gfc, cod_info);
}
assert(cod_info->global_gain < 256u);
if (cod_info->part2_3_length + cod_info->part2_length >= LARGE_BITS) {
cod_info->part2_3_length = LARGE_BITS;
return -2; /* Houston, we have a problem */
}
return 0;
}