Source file: /~heha/hs/puh.zip/vbrquantize.cpp

/*	MP3 quantization
 *	Copyright (c) 1999-2000 Mark Taylor
 *	Copyright (c) 2000-2012 Robert Hegemann
 */

#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "util.h"
//#include "vbrquantize.h"
#include "quantize_pvt.h"

struct algo_t {
  typedef void (algo_t::*alloc_sf_f) (const int*, const int*, int) const;
  typedef uint8_t (*find_sf_f) (const FLOAT *, const FLOAT *, FLOAT, unsigned int, uint8_t);
  alloc_sf_f alloc;	// pointer to member function
  find_sf_f  find;	// pointer to (non-member) function
  const FLOAT *xr34orig;
  lame_internal_flags &gfc;
  gr_info &cod_info;
  int mingain_l;
  int mingain_s[3];
  algo_t(lame_internal_flags&L, gr_info&I) : gfc(L),cod_info(I) {}
  int  block_sf(const FLOAT*, int*, int*);
  void short_block_constrain	(const int*, const int*, int)	const;
  void long_block_constrain	(const int*, const int*, int)	const;
  void bitcount			()				const;
  int  quantizeAndCountBits	()				const;
  void outOfBitsStrategy	(const int*, const int*, int)	const;
private:
  void quantize_x34		()				const;
  int  tryGlobalStepsize	(const int*, const int*, int)	const;
  void searchGlobalStepsizeMax	(const int*, const int*, int)	const;
  int  tryThatOne		(const int*, const int*, int)	const;
};


/*  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
#  if _MSC_VER < 1400
#  define VOLATILE volatile
#  else
#  define VOLATILE
#  endif
#else
#  define VOLATILE
#endif

typedef VOLATILE union {
    float   f;
    int     i;
} fi_union;



#ifdef TAKEHIRO_IEEE754_HACK
#define DOUBLEX double
#else
#define DOUBLEX FLOAT
#endif
 
#define MAGIC_FLOAT_def (65536*(128))
#define MAGIC_INT_def    0x4b000000

#ifdef TAKEHIRO_IEEE754_HACK
#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;
#ifndef TAKEHIRO_IEEE754_HACK
static DOUBLEX const ROUNDFAC = ROUNDFAC_def;
#endif
static DOUBLEX const MAGIC_FLOAT = MAGIC_FLOAT_def;


inline static  float
vec_max_c(const float * xr34, unsigned int bw)
{
    float   xfsf = 0;
    unsigned int i = bw >> 2u;
    unsigned int const remaining = (bw & 0x03u);

    while (i-- > 0) {
        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;
    }
    switch( remaining ) {
    case 3: if (xfsf < xr34[2]) xfsf = xr34[2];
    case 2: if (xfsf < xr34[1]) xfsf = xr34[1];
    case 1: if (xfsf < xr34[0]) xfsf = xr34[0];
    default: break;
    }
    return xfsf;
}


inline static  uint8_t
find_lowest_scalefac(const FLOAT xr34)
{
    uint8_t sf_ok = 255;
    uint8_t sf = 128, delsf = 64;
    FLOAT const ixmax_val = IXMAX_VAL;
    for (uint8_t i = 0; i < 8; ++i) {
        FLOAT const xfsf = ipow20[sf] * xr34;
        if (xfsf <= ixmax_val) {
            sf_ok = sf;
            sf -= delsf;
        }
        else {
            sf += delsf;
        }
        delsf >>= 1;
    }
    return sf_ok;
}


inline 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
}





/*  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, uint8_t sf)
{
    DOUBLEX x[4];
    int     l3[4];
    const FLOAT sfpow = pow20[sf + Q_MAX2]; /*pow(2.0,sf/4.0); */
    const FLOAT sfpow34 = ipow20[sf]; /*pow(sfpow,-3.0/4.0); */

    FLOAT   xfsf = 0;
    unsigned int i = bw >> 2u;
    unsigned int const remaining = (bw & 0x03u);

    while (i-- > 0) {
        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] = fabsf(xr[0]) - sfpow * pow43[l3[0]];
        x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]];
        x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]];
        x[3] = fabsf(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] = x[1] = x[2] = x[3] = 0;
        switch( remaining ) {
        case 3: x[2] = sfpow34 * xr34[2];
        case 2: x[1] = sfpow34 * xr34[1];
        case 1: x[0] = sfpow34 * xr34[0];
        }

        k_34_4(x, l3);
        x[0] = x[1] = x[2] = x[3] = 0;

        switch( remaining ) {
        case 3: x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]];
        case 2: x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]];
        case 1: x[0] = fabsf(xr[0]) - sfpow * pow43[l3[0]];
        }
        xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]);
    }
    return xfsf;
}



struct calc_noise_cache {
    int     valid;
    FLOAT   value;
};

typedef struct calc_noise_cache calc_noise_cache_t;


static  uint8_t
tri_calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw,
                       uint8_t sf, calc_noise_cache_t * did_it)
{
    if (did_it[sf].valid == 0) {
        did_it[sf].valid = 1;
        did_it[sf].value = calc_sfb_noise_x34(xr, xr34, bw, sf);
    }
    if (l3_xmin < did_it[sf].value) {
        return 1;
    }
    if (sf < 255) {
        uint8_t const sf_x = sf + 1;
        if (did_it[sf_x].valid == 0) {
            did_it[sf_x].valid = 1;
            did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x);
        }
        if (l3_xmin < did_it[sf_x].value) {
            return 1;
        }
    }
    if (sf > 0) {
        uint8_t const sf_x = sf - 1;
        if (did_it[sf_x].valid == 0) {
            did_it[sf_x].valid = 1;
            did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x);
        }
        if (l3_xmin < did_it[sf_x].value) {
            return 1;
        }
    }
    return 0;
}


/**
 *  Robert Hegemann 2001-05-01
 *  calculates quantization step size determined by allowed masking
 */
static int
calc_scalefac(FLOAT l3_xmin, int bw)
{
    FLOAT const c = 5.799142446; /* 10 * 10^(2/3) * log10(4/3) */
    return 210 + (int) (c * log10f(l3_xmin / bw) - .5f);
}

static uint8_t
guess_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, uint8_t sf_min)
{
    int const guess = calc_scalefac(l3_xmin, bw);
    if (guess < sf_min) return sf_min;
    if (guess >= 255) return 255;
    (void) xr;
    (void) xr34;
    return guess;
}


/* 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  uint8_t
find_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw,
                  uint8_t sf_min)
{
    calc_noise_cache_t did_it[256];
    uint8_t sf = 128, sf_ok = 255, delsf = 128, seen_good_one = 0, i;
    memset(did_it, 0, sizeof(did_it));
    for (i = 0; i < 8; ++i) {
        delsf >>= 1;
        if (sf <= sf_min) {
            sf += delsf;
        }
        else {
            uint8_t const bad = tri_calc_sfb_noise_x34(xr, xr34, l3_xmin, bw, sf, did_it);
            if (bad) {  /* distortion.  try a smaller scalefactor */
                sf -= delsf;
            }
            else {
                sf_ok = sf;
                sf += delsf;
                seen_good_one = 1;
            }
        }
    }
    /*  returning a scalefac without distortion, if possible
     */
    if (seen_good_one > 0) {
        sf = sf_ok;
    }
    if (sf <= sf_min) {
        sf = sf_min;
    }
    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 */
int algo_t::block_sf(const FLOAT l3_xmin[SFBMAX], int vbrsf[SFBMAX], int vbrsfmin[SFBMAX]) {
  FLOAT   max_xr34;
  const FLOAT *const xr = cod_info.xr;
  const FLOAT *const xr34_orig = xr34orig;
  const int *const width = cod_info.width;
  const char *const energy_above_cutoff = cod_info.energy_above_cutoff;
  unsigned int const max_nonzero_coeff = (unsigned int) cod_info.max_nonzero_coeff;
  uint8_t maxsf = 0;
  int     sfb = 0, m_o = -1;
  unsigned int j = 0, i = 0;
  int const psymax = cod_info.psymax;

  assert(cod_info.max_nonzero_coeff >= 0);

  mingain_l = 0;
  mingain_s[0] = 0;
  mingain_s[1] = 0;
  mingain_s[2] = 0;
  while (j <= max_nonzero_coeff) {
    unsigned int const w = (unsigned int) width[sfb];
    unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1);
    unsigned int l = w;
    uint8_t m1, m2;
    if (l > m) l = m;
    max_xr34 = vec_max_c(&xr34_orig[j], l);
    m1 = find_lowest_scalefac(max_xr34);
    vbrsfmin[sfb] = m1;
    if (mingain_l < m1) mingain_l = m1;
    if (mingain_s[i] < m1) mingain_s[i] = m1;
    if (++i > 2) i = 0;
    if (sfb < psymax && w > 2) { /* mpeg2.5 at 8 kHz doesn't use all scalefactors, unused have width 2 */
      if (energy_above_cutoff[sfb]) {
        m2 = find(&xr[j], &xr34_orig[j], l3_xmin[sfb], l, m1);
#if 0
        if (0) {
                    /** Robert Hegemann 2007-09-29:
                     *  It seems here is some more potential for speed improvements.
                     *  Current find method does 11-18 quantization calculations.
                     *  Using a "good guess" may help to reduce this amount.
                     */
                    uint8_t guess = calc_scalefac(l3_xmin[sfb], l);
                    DEBUGF(gfc, "sfb=%3d guess=%3d found=%3d diff=%3d\n", sfb, guess, m2,
                           m2 - guess);
                }
#endif
        if (maxsf < m2) maxsf = m2;
        if (m_o < m2 && m2 < 255) m_o = m2;
      }else{
        m2 = 255;
        maxsf = 255;
      }
    }else{
      if (maxsf < m1) maxsf = m1;
      m2 = maxsf;
    }
    vbrsf[sfb] = m2;
    ++sfb;
    j += w;        
  }
  for (; sfb < SFBMAX; ++sfb) {
    vbrsf[sfb] = maxsf;
    vbrsfmin[sfb] = 0;
  }
  if (m_o > -1) {
    maxsf = m_o;
    for (sfb = 0; sfb < SFBMAX; ++sfb) {
      if (vbrsf[sfb] == 255) vbrsf[sfb] = m_o;
    }
  }
  return maxsf;
}

/***********************************************************************
 *
 *  quantize xr34 based on scalefactors
 *
 *  block_xr34
 *
 *  Mark Taylor 2000-??-??
 *  Robert Hegemann 2000-10-20 made functions of them
 *
 ***********************************************************************/

void algo_t::quantize_x34() const {
  DOUBLEX x[4];
  const FLOAT *xr34orig = this->xr34orig;	// have moveable pointer to data
  int const ifqstep = (cod_info.scalefac_scale == 0) ? 2 : 4;
  int    *l3 = cod_info.l3_enc;
  unsigned int j = 0, sfb = 0;
  unsigned int const max_nonzero_coeff = (unsigned int) cod_info.max_nonzero_coeff;

  assert(cod_info.max_nonzero_coeff >= 0);
  assert(cod_info.max_nonzero_coeff < 576);

  while (j <= max_nonzero_coeff) {
    int const s =
            (cod_info.scalefac[sfb] + (cod_info.preflag ? pretab[sfb] : 0)) * ifqstep
            + cod_info.subblock_gain[cod_info.window[sfb]] * 8;
    uint8_t const sfac = (uint8_t) (cod_info.global_gain - s);
    FLOAT const sfpow34 = ipow20[sfac];
    unsigned int const w = (unsigned int) cod_info.width[sfb];
    unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1);
    unsigned int i, remaining;

    assert((cod_info.global_gain - s) >= 0);
    assert(cod_info.width[sfb] >= 0);
    j += w;
    ++sfb;
        
    i = (w <= m) ? w : m;
    remaining = (i & 0x03u);
    i >>= 2u;

    while (i-- > 0) {
      x[0] = sfpow34 * xr34orig[0];
      x[1] = sfpow34 * xr34orig[1];
      x[2] = sfpow34 * xr34orig[2];
      x[3] = sfpow34 * xr34orig[3];
      k_34_4(x, l3);
      l3 += 4;
      xr34orig += 4;
    }
    if (remaining) {
      int tmp_l3[4];
      x[0] = x[1] = x[2] = x[3] = 0;
      switch( remaining ) {
        case 3: x[2] = sfpow34 * xr34orig[2];
        case 2: x[1] = sfpow34 * xr34orig[1];
        case 1: x[0] = sfpow34 * xr34orig[0];
      }
      k_34_4(x, tmp_l3);
      switch( remaining ) {
        case 3: l3[2] = tmp_l3[2];
        case 2: l3[1] = tmp_l3[1];
        case 1: l3[0] = tmp_l3[0];
      }
      l3 += remaining;
      xr34orig += remaining;
    }
  }
}



static const uint8_t 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 uint8_t 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 uint8_t 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    *const sbg = cod_info.subblock_gain;
    unsigned int const psymax = (unsigned int) cod_info.psymax;
    unsigned int psydiv = 18;
    int     sbg0, sbg1, sbg2;
    unsigned int sfb, i;
    int     min_sbg = 7;

    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 const v = -sf[sfb];
            if (maxsf1 < v) {
                maxsf1 = v;
            }
            if (minsf > v) {
                minsf = v;
            }
        }
        for (; sfb < SFBMAX; sfb += 3) { /* part 2 */
            int const 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 const m1 = maxsf1 - (maxrange1 << ifqstepShift);
            int const m2 = maxsf2 - (maxrange2 << ifqstepShift);

            maxsf1 = Max(m1, m2);
        }
        if (minsf > 0) {
            sbg[i] = minsf >> 3;
        }
        else {
            sbg[i] = 0;
        }
        if (maxsf1 > 0) {
            int const m1 = sbg[i];
            int const 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;
        }
        if (min_sbg > sbg[i]) {
            min_sbg = sbg[i];
        }
    }
    sbg0 = sbg[0] * 8;
    sbg1 = sbg[1] * 8;
    sbg2 = sbg[2] * 8;
    for (sfb = 0; sfb < SFBMAX; sfb += 3) {
        sf[sfb + 0] += sbg0;
        sf[sfb + 1] += sbg1;
        sf[sfb + 2] += sbg2;
    }
    if (min_sbg > 0) {
        for (i = 0; i < 3; ++i) {
            sbg[i] -= min_sbg;
        }
        cod_info.global_gain -= min_sbg * 8;
    }
}



/*
	  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 uint8_t * max_range)
{
    const int ifqstep = (cod_info.scalefac_scale == 0) ? 2 : 4;
    const int ifqstepShift = (cod_info.scalefac_scale == 0) ? 1 : 2;
    int    *const scalefac = cod_info.scalefac;
    int const sfbmax = cod_info.sfbmax;
    int     sfb;
    int const *const sbg = cod_info.subblock_gain;
    int const *const window = cod_info.window;
    int const preflag = cod_info.preflag;

    if (preflag) {
        for (sfb = 11; sfb < sfbmax; ++sfb) {
            sf[sfb] += pretab[sfb] * ifqstep;
        }
    }
    for (sfb = 0; sfb < sfbmax; ++sfb) {
        int const gain = cod_info.global_gain - (sbg[window[sfb]] * 8)
            - ((preflag ? pretab[sfb] : 0) * ifqstep);

        if (sf[sfb] < 0) {
            int const 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 */
    }
}


#ifndef NDEBUG
static int
checkScalefactor(const gr_info & cod_info, const int vbrsfmin[SFBMAX])
{
    int const ifqstep = cod_info.scalefac_scale == 0 ? 2 : 4;
    int     sfb;
    for (sfb = 0; sfb < cod_info.psymax; ++sfb) {
        const int s =
            ((cod_info.scalefac[sfb] +
              (cod_info.preflag ? pretab[sfb] : 0)) * ifqstep) +
            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;
}
#endif


/******************************************************************
 *
 *  short block scalefacs
 *
 ******************************************************************/

void algo_t::short_block_constrain(const int vbrsf[SFBMAX],
                      const int vbrsfmin[SFBMAX], int vbrmax) const {
  SessionConfig_t const & cfg = gfc.cfg;
  int const maxminsfb = mingain_l;
  int     mover, maxover0 = 0, maxover1 = 0, delta = 0;
  int     v, v0, v1;
  int const psymax = cod_info.psymax;

  for (int 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 (cfg.noise_shaping == 2) mover = Min(maxover0, maxover1);
        /* allow scalefac_scale=1 */
  else mover = maxover0;
  if (delta > mover) delta = mover;
  vbrmax -= delta;
  maxover0 -= mover;
  maxover1 -= mover;
  if (!maxover0) cod_info.scalefac_scale = 0;
  else if (!maxover1) 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;
  {
    int     sf_temp[SFBMAX];
    for (int sfb = 0; sfb < SFBMAX; ++sfb) {
      sf_temp[sfb] = vbrsf[sfb] - vbrmax;
    }
    set_subblock_gain(cod_info, mingain_s, sf_temp);
    set_scalefacs(cod_info, vbrsfmin, sf_temp, max_range_short);
  }
  assert(checkScalefactor(cod_info, vbrsfmin));
}

/******************************************************************
 *
 *  long block scalefacs
 *
 ******************************************************************/

void algo_t::long_block_constrain(const int vbrsf[SFBMAX], const int vbrsfmin[SFBMAX], int vbrmax) const {
    SessionConfig_t const & cfg = gfc.cfg;
    uint8_t const *max_rangep;
    int const maxminsfb = mingain_l;
    int     sfb;
    int     maxover0, maxover1, maxover0p, maxover1p, mover, delta = 0;
    int     v, v0, v1, v0p, v1p, vm0p = 1, vm1p = 1;
    int const psymax = cod_info.psymax;

    max_rangep = cfg.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 const 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 const b = (gain - vbrsfmin[sfb]) - 4 * pretab[sfb];
            if (b <= 0) {
                vm1p = 0;
                break;
            }
        }
    }
    if (vm0p == 0) {
        maxover0p = maxover0;
    }
    if (vm1p == 0) {
        maxover1p = maxover1;
    }
    if (cfg.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;
    }
    {
        int     sf_temp[SFBMAX];
        for (sfb = 0; sfb < SFBMAX; ++sfb) {
            sf_temp[sfb] = vbrsf[sfb] - vbrmax;
        }
        set_scalefacs(cod_info, vbrsfmin, sf_temp, max_rangep);
    }
    assert(checkScalefactor(cod_info, vbrsfmin));
}



void algo_t::bitcount() const {
  int rc = gfc.scale_bitcount(cod_info);
  if (!rc) return;
    /*  this should not happen due to the way the scalefactors are selected  */
  ERRORF(gfc, "INTERNAL ERROR IN VBR NEW CODE (986), please send bug report\n");
  exit(-1);
}

int algo_t::quantizeAndCountBits() const {
  quantize_x34();
  cod_info.part2_3_length = gfc.noquant_count_bits(cod_info,0);
  return cod_info.part2_3_length;
}

int algo_t::tryGlobalStepsize(const int sfwork[SFBMAX], const int vbrsfmin[SFBMAX], int delta) const {
  FLOAT const xrpow_max = cod_info.xrpow_max;
  int     sftemp[SFBMAX], nbits;
  int     gain, vbrmax = 0;
  for (int 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;
  }
  algo_t*self=const_cast<algo_t*>(this);
  (self->*alloc)(sftemp, vbrsfmin, vbrmax);
  bitcount();
  nbits = quantizeAndCountBits();
  cod_info.xrpow_max = xrpow_max;
  return nbits;
}

void algo_t::searchGlobalStepsizeMax(const int sfwork[SFBMAX],
                        const int vbrsfmin[SFBMAX], int target) const {
  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(sfwork, vbrsfmin, curr - gain);
    if (nbits == 0 || (nbits + cod_info.part2_length) < target) {
      r = curr - 1;
      gain_ok = curr;
    }else{
      l = curr + 1;
      if (gain_ok == 1024) gain_ok = curr;
    }
  }
  if (gain_ok != curr) {
    curr = gain_ok;
    nbits = tryGlobalStepsize(sfwork, vbrsfmin, curr - gain);
  }
}

static int sfDepth(const int sfwork[SFBMAX]) {
    int     m = 0;
    unsigned int i, j;
    for (j = SFBMAX, i = 0; j > 0; --j, ++i) {
        int const di = 255 - sfwork[i];
        if (m < di) {
            m = di;
        }
        assert(sfwork[i] >= 0);
        assert(sfwork[i] <= 255);
    }
    assert(m >= 0);
    assert(m <= 255);
    return m;
}


static void
cutDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int cut)
{
    unsigned int i, j;
    for (j = SFBMAX, i = 0; j > 0; --j, ++i) {
        int const x = sfwork[i];
        sf_out[i] = x < cut ? x : cut;
    }
}


static int
flattenDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int dm, int k, int p)
{
    unsigned int i, j;
    int     x, sfmax = 0;
    if (dm > 0) {
        for (j = SFBMAX, i = 0; j > 0; --j, ++i) {
            int const di = p - sfwork[i];
            x = sfwork[i] + (k * di) / dm;
            if (x < 0) {
                x = 0;
            }
            else {
                if (x > 255) {
                    x = 255;
                }
            }
            sf_out[i] = x;
            if (sfmax < x) {
                sfmax = x;
            }
        }
    }
    else {
        for (j = SFBMAX, i = 0; j > 0u; --j, ++i) {
            x = sfwork[i];
            sf_out[i] = x;
            if (sfmax < x) {
                sfmax = x;
            }
        }
    }
    return sfmax;
}


int algo_t::tryThatOne(const int sftemp[SFBMAX], const int vbrsfmin[SFBMAX], int vbrmax) const {
  FLOAT const xrpow_max = cod_info.xrpow_max;
  int     nbits = LARGE_BITS;
  algo_t*self=const_cast<algo_t*>(this);
  (self->*alloc)(sftemp, vbrsfmin, vbrmax);
  bitcount();
  nbits = quantizeAndCountBits();
  nbits += cod_info.part2_length;
  cod_info.xrpow_max = xrpow_max;
  return nbits;
}


void algo_t::outOfBitsStrategy(const int sfwork[SFBMAX], const int vbrsfmin[SFBMAX], int target) const {
  int     wrk[SFBMAX];
  int const dm = sfDepth(sfwork);
  int const p = cod_info.global_gain;
  int     nbits;

    /* PART 1 */
  {
    int     bi = dm / 2;
    int     bi_ok = -1;
    int     bu = 0;
    int     bo = dm;
    for (;;) {
      int const sfmax = flattenDistribution(sfwork, wrk, dm, bi, p);
      nbits = tryThatOne(wrk, vbrsfmin, sfmax);
      if (nbits <= target) {
        bi_ok = bi;
        bo = bi - 1;
      }else bu = bi + 1;
      if (bu <= bo) bi = (bu + bo) / 2;
      else break;
    }
    if (bi_ok >= 0) {
      if (bi != bi_ok) {
        int const sfmax = flattenDistribution(sfwork, wrk, dm, bi_ok, p);
        nbits = tryThatOne(wrk, vbrsfmin, sfmax);
      }
      return;
    }
  }

    /* PART 2: */
  {
    int     bi = (255 + p) / 2;
    int     bi_ok = -1;
    int     bu = p;
    int     bo = 255;
    for (;;) {
      int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi);
      nbits = tryThatOne(wrk, vbrsfmin, sfmax);
      if (nbits <= target) {
        bi_ok = bi;
        bo = bi - 1;
      }else bu = bi + 1;
      if (bu <= bo) bi = (bu + bo) / 2;
      else break;
    }
    if (bi_ok >= 0) {
      if (bi != bi_ok) {
        int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi_ok);
        nbits = tryThatOne(wrk, vbrsfmin, sfmax);
      }
      return;
    }
  }
    /* fall back to old code, likely to be never called */
  searchGlobalStepsizeMax(wrk, vbrsfmin, target);
}


static int reduce_bit_usage(lame_internal_flags * gfc, int gr, int ch
#if 0
                 , const FLOAT xr34orig[576], const FLOAT l3_xmin[SFBMAX], int maxbits
#endif
    )
{
    SessionConfig_t const &cfg = gfc->cfg;
    gr_info & cod_info = gfc->l3_side.tt[gr][ch];
    /*  try some better scalefac storage
     */
    gfc->best_scalefac_store(gr, ch, gfc->l3_side);

    /*  best huffman_divide may save some bits too
     */
    if (cfg.use_best_huffman == 1)
        gfc->best_huffman_divide(cod_info);
    return cod_info.part2_3_length + cod_info.part2_length;
}




int lame_internal_flags::VBR_encode_frame(const FLOAT xr34orig[2][2][576],
	const FLOAT l3_xmin[2][2][SFBMAX], const int max_bits[2][2]) {
  SessionConfig_t const &cfg = this->cfg;
  int     sfwork_[2][2][SFBMAX];
  int     vbrsfmin_[2][2][SFBMAX];
  char that_[4*sizeof(algo_t)];
  int const ngr = cfg.mode_gr;
  int const nch = cfg.channels_out;
  int     max_nbits_ch[2][2] = {{0, 0}, {0 ,0}};
  int     max_nbits_gr[2] = {0, 0};
  int     max_nbits_fr = 0;
  int     use_nbits_ch[2][2] = {{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1}
                                 ,{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1}};
  int     use_nbits_gr[2] = { MAX_BITS_PER_GRANULE+1, MAX_BITS_PER_GRANULE+1 };
  int     use_nbits_fr = MAX_BITS_PER_GRANULE+MAX_BITS_PER_GRANULE;
  int     sum_fr;

    /* set up some encoding parameters
     */
  for (int gr = 0; gr < ngr; ++gr) {
    max_nbits_gr[gr] = 0;
    for (int ch = 0; ch < nch; ++ch) {
      max_nbits_ch[gr][ch] = max_bits[gr][ch];
      use_nbits_ch[gr][ch] = 0;
      max_nbits_gr[gr] += max_bits[gr][ch];
      max_nbits_fr += max_bits[gr][ch];
      // placement new into array[2][2] of POD objects with 2 function pointers and 2 references
      // References need constructor-time initialization
      algo_t*n = new(that_+(gr*2+ch)*sizeof(algo_t)) algo_t(*this,this->l3_side.tt[gr][ch]);
      n->find = (cfg.full_outer_loop < 0) ? guess_scalefac_x34 : find_scalefac_x34;
      n->xr34orig = xr34orig[gr][ch];
      n->alloc = n->cod_info.block_type == SHORT_TYPE
	  ? &algo_t::short_block_constrain
	  : &algo_t::long_block_constrain;
    }               /* for ch */
  }
    /* searches scalefactors
     */
  {for (int gr = 0; gr < ngr; ++gr) {
    for (int ch = 0; ch < nch; ++ch) {
      if (max_bits[gr][ch] > 0) {
        algo_t &that = *reinterpret_cast<algo_t*>(that_+(gr*2+ch)*sizeof(algo_t));
        int    *sfwork = sfwork_[gr][ch];
        int    *vbrsfmin = vbrsfmin_[gr][ch];
        int vbrmax = that.block_sf(l3_xmin[gr][ch], sfwork, vbrsfmin);
        (that.*that.alloc)(sfwork, vbrsfmin, vbrmax);
        that.bitcount();
      }else{
                /*  xr contains no energy 
                 *  l3_enc, our encoding data, will be quantized to zero
                 *  continue with next channel
                 */
      }
    }               /* for ch */
  }}
    /* encode 'as is'
     */
  use_nbits_fr = 0;
  {for (int gr = 0; gr < ngr; ++gr) {
    use_nbits_gr[gr] = 0;
    for (int ch = 0; ch < nch; ++ch) {
      algo_t &that = *reinterpret_cast<algo_t*>(that_+(gr*2+ch)*sizeof(algo_t));
      if (max_bits[gr][ch] > 0) {
        memset(that.cod_info.l3_enc, 0, sizeof that.cod_info.l3_enc);
        that.quantizeAndCountBits();
      }else{
                /*  xr contains no energy 
                 *  l3_enc, our encoding data, will be quantized to zero
                 *  continue with next channel
                 */
      }
      use_nbits_ch[gr][ch] = reduce_bit_usage(this, gr, ch);
      use_nbits_gr[gr] += use_nbits_ch[gr][ch];
    }               /* for ch */
    use_nbits_fr += use_nbits_gr[gr];
  }}

    /* check bit constrains
     */
  bool ok = false;
  if (use_nbits_fr <= max_nbits_fr) {
    ok = true;
    for (int gr = 0; gr < ngr; ++gr) {
      if (use_nbits_gr[gr] > MAX_BITS_PER_GRANULE) {
                /* violates the rule that every granule has to use no more
                 * bits than MAX_BITS_PER_GRANULE
                 */
        ok = false;
      }
      for (int ch = 0; ch < nch; ++ch) {
        if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) {
                    /* violates the rule that every gr_ch has to use no more
                     * bits than MAX_BITS_PER_CHANNEL
                     *
                     * This isn't explicitly stated in the ISO docs, but the
                     * part2_3_length field has only 12 bits, that makes it
                     * up to a maximum size of 4095 bits!!!
                     */
          ok = false;
        }
      }
    }
    if (ok) return use_nbits_fr;
  }
    
    /* OK, we are in trouble and have to define how many bits are
     * to be used for each granule
     */
  {
    ok = true;
    sum_fr = 0;
    for (int gr = 0; gr < ngr; ++gr) {
      max_nbits_gr[gr] = 0;
      for (int ch = 0; ch < nch; ++ch) {
        if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) {
          max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL;
        }else{
          max_nbits_ch[gr][ch] = use_nbits_ch[gr][ch];
        }
        max_nbits_gr[gr] += max_nbits_ch[gr][ch];
      }
      if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) {
        float   f[2] = {0.0f, 0.0f}, s = 0.0f;
        {for (int ch = 0; ch < nch; ++ch) {
          if (max_nbits_ch[gr][ch] > 0) {
            f[ch] = sqrt(sqrt(double(max_nbits_ch[gr][ch])));
            s += f[ch];
          }else{
            f[ch] = 0;
          }
        }}
        {for (int ch = 0; ch < nch; ++ch) {
          if (s > 0) {
            max_nbits_ch[gr][ch] = MAX_BITS_PER_GRANULE * f[ch] / s;
          }else{
            max_nbits_ch[gr][ch] = 0;
          }
        }}
        if (nch > 1) {
          if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) {
            max_nbits_ch[gr][1] += max_nbits_ch[gr][0];
            max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32;
            max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32;
          }
          if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) {
            max_nbits_ch[gr][0] += max_nbits_ch[gr][1];
            max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32;
            max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32;
          }
          if (max_nbits_ch[gr][0] > MAX_BITS_PER_CHANNEL) {
            max_nbits_ch[gr][0] = MAX_BITS_PER_CHANNEL;
          }
          if (max_nbits_ch[gr][1] > MAX_BITS_PER_CHANNEL) {
            max_nbits_ch[gr][1] = MAX_BITS_PER_CHANNEL;
          }
        }
        max_nbits_gr[gr] = 0;
        {for (int ch = 0; ch < nch; ++ch) {
          max_nbits_gr[gr] += max_nbits_ch[gr][ch];
        }}
      }
      sum_fr += max_nbits_gr[gr];
    }
    if (sum_fr > max_nbits_fr) {
      {
        float   f[2] = {0.0f, 0.0f}, s = 0.0f;
        {for (int gr = 0; gr < ngr; ++gr) {
          if (max_nbits_gr[gr] > 0) {
            f[gr] = sqrt(float(max_nbits_gr[gr]));
            s += f[gr];
          }else{
            f[gr] = 0;
          }
        }}
        {for (int gr = 0; gr < ngr; ++gr) {
          if (s > 0) {
            max_nbits_gr[gr] = max_nbits_fr * f[gr] / s;
          }else{
            max_nbits_gr[gr] = 0;
          }
        }}
      }
      if (ngr > 1) {
        if (max_nbits_gr[0] > use_nbits_gr[0] + 125) {
          max_nbits_gr[1] += max_nbits_gr[0];
          max_nbits_gr[1] -= use_nbits_gr[0] + 125;
          max_nbits_gr[0] = use_nbits_gr[0] + 125;
        }
        if (max_nbits_gr[1] > use_nbits_gr[1] + 125) {
          max_nbits_gr[0] += max_nbits_gr[1];
          max_nbits_gr[0] -= use_nbits_gr[1] + 125;
          max_nbits_gr[1] = use_nbits_gr[1] + 125;
        }
        for (int gr = 0; gr < ngr; ++gr) {
          if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) {
            max_nbits_gr[gr] = MAX_BITS_PER_GRANULE;
          }
        }
      }
      {for (int gr = 0; gr < ngr; ++gr) {
        float   f[2] = {0.0f, 0.0f}, s = 0.0f;
        {for (int ch = 0; ch < nch; ++ch) {
          if (max_nbits_ch[gr][ch] > 0) {
            f[ch] = sqrt(float(max_nbits_ch[gr][ch]));
            s += f[ch];
          }else{
            f[ch] = 0;
          }
        }}
        {for (int ch = 0; ch < nch; ++ch) {
          if (s > 0) {
            max_nbits_ch[gr][ch] = max_nbits_gr[gr] * f[ch] / s;
          }else{
            max_nbits_ch[gr][ch] = 0;
          }
        }}
        if (nch > 1) {
          if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) {
            max_nbits_ch[gr][1] += max_nbits_ch[gr][0];
            max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32;
            max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32;
          }
          if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) {
            max_nbits_ch[gr][0] += max_nbits_ch[gr][1];
            max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32;
            max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32;
          }
          for (int ch = 0; ch < nch; ++ch) {
            if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) {
              max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL;
            }
          }
        }
      }}
    }
        /* sanity check */
    sum_fr = 0;
    {for (int gr = 0; gr < ngr; ++gr) {
      int     sum_gr = 0;
      for (int ch = 0; ch < nch; ++ch) {
        sum_gr += max_nbits_ch[gr][ch];
        if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) ok = false;
      }
      sum_fr += sum_gr;
      if (sum_gr > MAX_BITS_PER_GRANULE) ok = false;
    }}
    if (sum_fr > max_nbits_fr) ok = false;
    if (!ok) {
            /* we must have done something wrong, fallback to 'on_pe' based constrain */
      for (int gr = 0; gr < ngr; ++gr) {
        for (int ch = 0; ch < nch; ++ch) {
          max_nbits_ch[gr][ch] = max_bits[gr][ch];
        }
      }
    }
  }

    /* we already called the 'best_scalefac_store' function, so we need to reset some
     * variables before we can do it again.
     */
  {for (int ch = 0; ch < nch; ++ch) {
    l3_side.scfsi[ch][0] = 0;
    l3_side.scfsi[ch][1] = 0;
    l3_side.scfsi[ch][2] = 0;
    l3_side.scfsi[ch][3] = 0;
  }}
  {for (int gr = 0; gr < ngr; ++gr) {
    for (int ch = 0; ch < nch; ++ch) {
      l3_side.tt[gr][ch].scalefac_compress = 0;
    }
  }}

    /* alter our encoded data, until it fits into the target bitrate
     */
  use_nbits_fr = 0;
  {for (int gr = 0; gr < ngr; ++gr) {
    use_nbits_gr[gr] = 0;
    for (int ch = 0; ch < nch; ++ch) {
      algo_t &that = *reinterpret_cast<algo_t*>(that_+(gr*2+ch)*sizeof(algo_t));
      use_nbits_ch[gr][ch] = 0;
      if (max_bits[gr][ch] > 0) {
        int    *sfwork = sfwork_[gr][ch];
        int const *vbrsfmin = vbrsfmin_[gr][ch];
        cutDistribution(sfwork, sfwork, that.cod_info.global_gain);
        that.outOfBitsStrategy(sfwork, vbrsfmin, max_nbits_ch[gr][ch]);
      }
      use_nbits_ch[gr][ch] = reduce_bit_usage(this, gr, ch);
      assert(use_nbits_ch[gr][ch] <= max_nbits_ch[gr][ch]);
      use_nbits_gr[gr] += use_nbits_ch[gr][ch];
    }               /* for ch */
    use_nbits_fr += use_nbits_gr[gr];
  }}

    /* check bit constrains, but it should always be ok, iff there are no bugs ;-)
     */
  if (use_nbits_fr <= max_nbits_fr) return use_nbits_fr;

  ERRORF(*this, "INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report\n"
           "maxbits=%d usedbits=%d\n", max_nbits_fr, use_nbits_fr);
  exit(-1);
}
Detected encoding: ASCII (7 bit)2