1838 lines · 58.0 KB · C
RawDownload
/* * MP3 quantization * * Copyright (c) 1999 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* $Id: quantize.c,v 1.57 2001/02/27 06:14:57 markt Exp $ */ #ifdef HAVE_CONFIG_H# include <config.h>#endif #include <math.h>#include <assert.h>#include "util.h"#include "l3side.h"#include "quantize.h"#include "reservoir.h"#include "quantize_pvt.h"#include "lame-analysis.h" #ifdef WITH_DMALLOC#include <dmalloc.h>#endif  /************************************************************************ * *      init_outer_loop() *  mt 6/99                                     * *  initializes cod_info, scalefac and xrpow * *  returns 0 if all energies in xr are zero, else 1                     * ************************************************************************/ static int init_outer_loop(    gr_info *const cod_info,     III_scalefac_t *const scalefac,     const int is_mpeg1,    const FLOAT8 xr[576],     FLOAT8 xrpow[576] ){    FLOAT8 tmp, sum = 0;    int i;     /*  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;    /* window_switching_flag was set in psymodel.c? */    /* block_type            was set in psymodel.c? */    /* mixed_block_flag      would be set in ^      */    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->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;    if (cod_info->block_type == SHORT_TYPE) {        cod_info->sfb_lmax        = 0;        cod_info->sfb_smin        = 0;	if (cod_info->mixed_block_flag) {            /*             *  MPEG-1:      sfbs 0-7 long block, 3-12 short blocks              *  MPEG-2(.5):  sfbs 0-5 long block, 3-12 short blocks             */             cod_info->sfb_lmax    = is_mpeg1 ? 8 : 6;	    cod_info->sfb_smin    = 3;	}    } else {        cod_info->sfb_lmax        = SBPSY_l;        cod_info->sfb_smin        = SBPSY_s;    }       cod_info->count1bits          = 0;      cod_info->sfb_partition_table = 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;     /*  fresh scalefactors are all zero     */    memset(scalefac, 0, sizeof(III_scalefac_t));      /*  check if there is some energy we have to quantize     *  and calculate xrpow matching our fresh scalefactors     */    for (i = 0; i < 576; ++i) {        tmp = fabs (xr[i]);	sum += tmp;        xrpow[i] = sqrt (tmp * sqrt(tmp));    }   /*  return 1 if we have something to quantize, else 0    */   return sum > (FLOAT8)1E-20;}   /************************************************************************ * *      bin_search_StepSize() * *  author/date?? * *  binary step size search *  used by outer_loop to get a quantizer step size to start with * ************************************************************************/ typedef enum {    BINSEARCH_NONE,    BINSEARCH_UP,     BINSEARCH_DOWN} binsearchDirection_t; int bin_search_StepSize(          lame_internal_flags * const gfc,          gr_info * const cod_info,    const int             desired_rate,     const int             start,     const FLOAT8          xrpow [576],          int             l3enc [576] ) {    int nBits;    int CurrentStep;    int flag_GoneOver = 0;    int StepSize      = start;     binsearchDirection_t Direction = BINSEARCH_NONE;    assert(gfc->CurrentStep);    CurrentStep = gfc->CurrentStep;     do {        cod_info->global_gain = StepSize;        nBits = count_bits(gfc,l3enc,xrpow,cod_info);           if (CurrentStep == 1) break; /* nothing to adjust anymore */            if (flag_GoneOver) CurrentStep /= 2;         if (nBits > desired_rate) {              /* increase Quantize_StepSize */            if (Direction == BINSEARCH_DOWN && !flag_GoneOver) {                flag_GoneOver = 1;                CurrentStep  /= 2; /* late adjust */            }            Direction = BINSEARCH_UP;            StepSize += CurrentStep;            if (StepSize > 255) break;        }        else if (nBits < desired_rate) {            /* decrease Quantize_StepSize */            if (Direction == BINSEARCH_UP && !flag_GoneOver) {                flag_GoneOver = 1;                CurrentStep  /= 2; /* late adjust */            }            Direction = BINSEARCH_DOWN;            StepSize -= CurrentStep;            if (StepSize < 0) break;        }        else break; /* nBits == desired_rate;; most unlikely to happen.*/    } while (1); /* For-ever, break is adjusted. */     CurrentStep = start - StepSize;        gfc->CurrentStep = CurrentStep/4 != 0 ? 4 : 2;     return nBits;}    /***************************************************************************  * *         inner_loop ()                                                      * *  author/date?? * *  The code selects the best global gain for a particular set of scalefacs  * ***************************************************************************/  int inner_loop(          lame_internal_flags * const gfc,          gr_info * const cod_info,    const int             max_bits,    const FLOAT8          xrpow [576],          int             l3enc [576] ){    int bits;        assert(max_bits >= 0);     /*  scalefactors may have changed, so count bits     */    bits=count_bits(gfc,l3enc,xrpow,cod_info);     /*  increase quantizer stepsize until needed bits are below maximum     */    while (bits > max_bits) {        cod_info->global_gain++;        bits = count_bits (gfc, l3enc, xrpow, cod_info);    }      return bits;}   /************************************************************************* * *      loop_break()                                                * *  author/date?? * *  Function: Returns zero if there is a scalefac which has not been *            amplified. Otherwise it returns one.  * *************************************************************************/ inline static intloop_break(     const gr_info        * const cod_info,    const III_scalefac_t * const scalefac ) {    unsigned int i, sfb;     for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++)        if (scalefac->l[sfb] == 0)            return 0;     for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++)        for (i = 0; i < 3; i++)             if (scalefac->s[sfb][i] == 0 && cod_info->subblock_gain[i] == 0)                return 0;     return 1;}    /************************************************************************* * *      quant_compare()                                                * *  author/date?? * *  several different codes to decide which quantization is better * *************************************************************************/ inline static int quant_compare(    const int                       experimentalX,    const calc_noise_result * const best,    const calc_noise_result * const calc ){    /*       noise is given in decibels (dB) relative to masking thesholds.        over_noise:  ??? (the previous comment is fully wrong)       tot_noise:   ??? (the previous comment is fully wrong)       max_noise:   max quantization noise       */    int better;     switch (experimentalX) {        default:        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  &&                     calc->over_noise == best->over_noise  &&                     calc->tot_noise   < best->tot_noise  ); 	    break;        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+2; 	    break;        case 4: 	    better = ( calc->max_noise <= 0  &&                       best->max_noise >  2 )                 ||  ( calc->max_noise <= 0  &&                       best->max_noise <  0  &&                       best->max_noise >  calc->max_noise-2  &&                       calc->tot_noise <  best->tot_noise )                 ||  ( calc->max_noise <= 0  &&                       best->max_noise >  0  &&                       best->max_noise >  calc->max_noise-2  &&                       calc->tot_noise <  best->tot_noise+best->over_noise )                 ||  ( calc->max_noise >  0  &&                       best->max_noise > -0.5  &&                       best->max_noise >  calc->max_noise-1  &&                       calc->tot_noise+calc->over_noise < best->tot_noise+best->over_noise )                 ||  ( calc->max_noise >  0  &&                       best->max_noise > -1  &&                       best->max_noise >  calc->max_noise-1.5  &&                       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                 ||  ( calc->over_noise == best->over_noise  &&                       calc->tot_noise   < best->tot_noise ); 	    break;        case 6: 	    better =   calc->over_noise  < best->over_noise                 ||  ( calc->over_noise == best->over_noise  &&                     ( calc->max_noise   < best->max_noise  		     ||  ( 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;        case 8: 	    better =   calc->klemm_noise < best->klemm_noise;            break;    }        return better;}   /************************************************************************* * *          amp_scalefac_bands()  * *  author/date?? *         *  Amplify the scalefactor bands that violate the masking threshold. *  See ISO 11172-3 Section C.1.5.4.3.5 *  *  distort[] = noise/masking *  distort[] > 1   ==> noise is not masked *  distort[] < 1   ==> noise is masked *  max_dist = maximum value of distort[] *   *  Three algorithms: *  noise_shaping_amp *        0             Amplify all bands with distort[]>1. * *        1             Amplify all bands with distort[] >= max_dist^(.5); *                     ( 50% in the db scale) * *        2             Amplify first band with distort[] >= max_dist; *                        * *  For algorithms 0 and 1, if max_dist < 1, then amplify all bands  *  with distort[] >= .95*max_dist.  This is to make sure we always *  amplify at least one band.   *  * *************************************************************************/static void amp_scalefac_bands(    lame_global_flags *gfp,    const gr_info  *const cod_info,     III_scalefac_t *const scalefac,    III_psy_xmin *distort,    FLOAT8 xrpow[576] ){  lame_internal_flags *gfc=gfp->internal_flags;  int start, end, l,i,j,sfb;  FLOAT8 ifqstep34, trigger;   if (cod_info->scalefac_scale == 0) {    ifqstep34 = 1.29683955465100964055; /* 2**(.75*.5)*/  } else {    ifqstep34 = 1.68179283050742922612;  /* 2**(.75*1) */  }   /* compute maximum value of distort[]  */  trigger = 0;  for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) {    if (trigger < distort->l[sfb])        trigger = distort->l[sfb];  }  for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) {    for (i = 0; i < 3; i++ ) {      if (trigger < distort->s[sfb][i])          trigger = distort->s[sfb][i];    }  }   switch (gfc->noise_shaping_amp) {   case 2:    /* amplify exactly 1 band */    //trigger = distort_thresh;    break;   case 1:    /* amplify bands within 50% of max (on db scale) */    if (trigger>1.0)        trigger = 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;  }   for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++ ) {    start = gfc->scalefac_band.l[sfb];    end   = gfc->scalefac_band.l[sfb+1];    if (distort->l[sfb]>=trigger  ) {      scalefac->l[sfb]++;      for ( l = start; l < end; l++ )	xrpow[l] *= ifqstep34;      if (gfc->noise_shaping_amp==2) goto done;    }  }    for ( j=0,sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++ ) {    start = gfc->scalefac_band.s[sfb];    end   = gfc->scalefac_band.s[sfb+1];    for ( i = 0; i < 3; i++ ) {      int j2 = j;      if ( distort->s[sfb][i]>=trigger) {	scalefac->s[sfb][i]++;	for (l = start; l < end; l++) 	  xrpow[j2++] *= ifqstep34;        if (gfc->noise_shaping_amp==2) goto done;      }      j += end-start;    }  } done: return;} /************************************************************************* * *      inc_scalefac_scale() * *  Takehiro Tominaga 2000-xx-xx * *  turns on scalefac scale and adjusts scalefactors * *************************************************************************/ static voidinc_scalefac_scale (    const lame_internal_flags        * const gfc,           gr_info        * const cod_info,           III_scalefac_t * const scalefac,          FLOAT8                 xrpow[576] ){

Lines 1–500 of 1838.