⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quantize.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:
#define MAXNOISEXX
/*
 *	MP3 quantization
 *
 *	Copyright (c) 1999 Mark Taylor
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */



#include <assert.h>
#include "util.h"
#include "l3side.h"
#include "quantize.h"
#include "l3bitstream.h"
#include "reservoir.h"
#include "quantize-pvt.h"
#ifdef HAVEGTK
#include "gtkanal.h"
#endif



#ifdef HAVEGTK

/************************************************************************/
/*  updates plotting data                                               */
/************************************************************************/
void 
set_pinfo (
    gr_info *cod_info,
    III_psy_ratio *ratio, 
    III_scalefac_t *scalefac,
    FLOAT8 xr[576],        
    FLOAT8 xfsf[4][SBPSY_l],
    FLOAT8 noise[4],
    int gr,
    int ch
)
{
  int sfb;
  FLOAT ifqstep;
  int i,l,start,end,bw;
  FLOAT8 en0;
  D192_3 *xr_s = (D192_3 *)xr;
  ifqstep = ( cod_info->scalefac_scale == 0 ) ? .5 : 1.0;
	  
  if (cod_info->block_type == SHORT_TYPE) {
    for ( i = 0; i < 3; i++ ) {
      for ( sfb = 0; sfb < SBPSY_s; sfb++ )  {
	start = scalefac_band.s[ sfb ];
	end   = scalefac_band.s[ sfb + 1 ];
	bw = end - start;
	for ( en0 = 0.0, l = start; l < end; l++ ) 
	  en0 += (*xr_s)[l][i] * (*xr_s)[l][i];
	en0=Max(en0/bw,1e-20);
		
	/* conversion to FFT units */
	en0 = ratio->en.s[sfb][i]/en0;
	
	pinfo->xfsf_s[gr][ch][3*sfb+i] =  xfsf[i+1][sfb]*en0;
	pinfo->thr_s[gr][ch][3*sfb+i] = ratio->thm.s[sfb][i];
	pinfo->en_s[gr][ch][3*sfb+i] = ratio->en.s[sfb][i]; 
	
	pinfo->LAMEsfb_s[gr][ch][3*sfb+i]=
	  -2*cod_info->subblock_gain[i]-ifqstep*scalefac->s[sfb][i];
      }
    }
  }else{
    for ( sfb = 0; sfb < SBPSY_l; sfb++ )   {
      start = scalefac_band.l[ sfb ];
      end   = scalefac_band.l[ sfb+1 ];
      bw = end - start;
      for ( en0 = 0.0, l = start; l < end; l++ ) 
	en0 += xr[l] * xr[l];
      en0=Max(en0/bw,1e-20);
      /*
	printf("diff  = %f \n",10*log10(Max(ratio[gr][ch].en.l[sfb],1e-20))
	-(10*log10(en0)+150));
      */
      
      /* convert to FFT units */
      en0 =   ratio->en.l[sfb]/en0;
      
      pinfo->xfsf[gr][ch][sfb] =  xfsf[0][sfb]*en0;
      pinfo->thr[gr][ch][sfb] = ratio->thm.l[sfb];
      pinfo->en[gr][ch][sfb] = ratio->en.l[sfb];
      
      pinfo->LAMEsfb[gr][ch][sfb]=-ifqstep*scalefac->l[sfb];
      if (cod_info->preflag && sfb>=11) 
	pinfo->LAMEsfb[gr][ch][sfb]-=ifqstep*pretab[sfb];
    }
  }
  pinfo->LAMEqss[gr][ch] = cod_info->global_gain;
  pinfo->LAMEmainbits[gr][ch] = cod_info->part2_3_length;

  pinfo->over      [gr][ch] = noise[0];
  pinfo->max_noise [gr][ch] = noise[1];
  pinfo->over_noise[gr][ch] = noise[2];
  pinfo->tot_noise [gr][ch] = noise[3];
}

#endif



/************************************************************************/
/*  iteration_loop()                                                    */
/************************************************************************/
void
iteration_loop( lame_global_flags *gfp,
                FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2],
		FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2],
		III_side_info_t *l3_side, int l3_enc[2][2][576],
		III_scalefac_t scalefac[2][2])
{
  FLOAT8 xfsf[4][SBPSY_l];
  FLOAT8 noise[4]; /* over,max_noise,over_noise,tot_noise; */
  III_psy_xmin l3_xmin[2];
  gr_info *cod_info;
  int bitsPerFrame;
  int mean_bits;
  int ch, gr, i, bit_rate;


  iteration_init(gfp,l3_side,l3_enc);
  bit_rate = bitrate_table[gfp->version][gfp->bitrate_index];


  getframebits(gfp,&bitsPerFrame, &mean_bits);
  ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame );

  /* quantize! */



  for ( gr = 0; gr < gfp->mode_gr; gr++ ) {
    int targ_bits[2];

    if (convert_mdct) 
      ms_convert(xr[gr], xr[gr]);
    
    on_pe(gfp,pe,l3_side,targ_bits,mean_bits, gr);
#ifdef RH_SIDE_CBR
#else
    if (reduce_sidechannel) 
      reduce_side(targ_bits,ms_ener_ratio[gr],mean_bits);
#endif      
    
    for (ch=0 ; ch < gfp->stereo ; ch ++) {
      cod_info = &l3_side->gr[gr].ch[ch].tt;	
      if (!init_outer_loop(gfp,xr[gr][ch], cod_info))
        {
          /* xr contains no energy 
           * cod_info was set in init_outer_loop above
	   */
          memset(&scalefac[gr][ch],0,sizeof(III_scalefac_t));
          memset(l3_enc[gr][ch],0,576*sizeof(int));
	  noise[0]=noise[1]=noise[2]=noise[3]=0;
        }
      else
	{
          calc_xmin(gfp,xr[gr][ch], &ratio[gr][ch], cod_info, &l3_xmin[ch]);
	  outer_loop( gfp,xr[gr][ch], targ_bits[ch], noise,
		      &l3_xmin[ch], l3_enc[gr][ch], 
		      &scalefac[gr][ch], cod_info, xfsf, ch);
        }
      best_scalefac_store(gfp,gr, ch, l3_enc, l3_side, scalefac);
      if (gfp->use_best_huffman==1 && cod_info->block_type == NORM_TYPE) {
	best_huffman_divide(gr, ch, cod_info, l3_enc[gr][ch]);
      }
#ifdef HAVEGTK
      if (gfp->gtkflag)
	set_pinfo (cod_info, &ratio[gr][ch], &scalefac[gr][ch], xr[gr][ch], xfsf, noise, gr, ch);
#endif

/*#define NORES_TEST */
#ifndef NORES_TEST
      ResvAdjust(gfp,cod_info, l3_side, mean_bits );
#endif
      /* set the sign of l3_enc */
      for ( i = 0; i < 576; i++) {
	if (xr[gr][ch][i] < 0)
	  l3_enc[gr][ch][i] *= -1;
      }
    }
  } /* loop over gr */

#ifdef NORES_TEST
  /* replace ResvAdjust above with this code if you do not want
     the second granule to use bits saved by the first granule.
     when combined with --nores, this is usefull for testing only */
  for ( gr = 0; gr < gfp->mode_gr; gr++ ) {
    for ( ch =  0; ch < gfp->stereo; ch++ ) {
	cod_info = &l3_side->gr[gr].ch[ch].tt;
	ResvAdjust(gfp, cod_info, l3_side, mean_bits );
    }
  }
#endif



  ResvFrameEnd(gfp,l3_side, mean_bits );
}


void 
set_masking_lower (int VBR_q,int nbits)
{
	FLOAT masking_lower_db, adjust;
	
	/* quality setting */
	/* Adjust allowed masking based on quality setting */
	
#ifdef  RH_QUALITY_CONTROL	
	/* - 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
	 */
	static FLOAT dbQ[10]={-6.0,-4.5,-3.0,-1.5,0,0.3,0.6,1.0,1.5,2.0};
	
	assert( VBR_q <= 9 );
	assert( VBR_q >= 0 );
	
	masking_lower_db = dbQ[VBR_q];	
	adjust = 0;
#else
	/* masking_lower varies from -8 to +10 db */
	masking_lower_db = -6 + 2*VBR_q;
	/* adjust by -6(min)..0(max) depending on bitrate */
	adjust = (nbits-125)/(2500.0-125.0);
	adjust = 4*(adjust-1);
#endif
	masking_lower_db += adjust;
	masking_lower = pow(10.0,masking_lower_db/10);
}

/************************************************************************
 *
 * VBR_iteration_loop()   
 *
 * tries to find out how many bits are needed for each granule and channel
 * to get an acceptable quantization. An appropriate bitrate will then be
 * choosed for quantization.  rh 8/99                                                
 *
 ************************************************************************/
void
VBR_iteration_loop (lame_global_flags *gfp,
                FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2],
                FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2],
                III_side_info_t * l3_side, int l3_enc[2][2][576],
                III_scalefac_t scalefac[2][2])
{
#ifdef HAVEGTK
  plotting_data bst_pinfo;
#endif
  gr_info         bst_cod_info, clean_cod_info;
  III_scalefac_t  bst_scalefac;
  int             bst_l3_enc[576]; 
  
  III_psy_xmin l3_xmin;
  gr_info  *cod_info = NULL;
  int       save_bits[2][2];
  FLOAT8    noise[4];      /* over,max_noise,over_noise,tot_noise; */
  FLOAT8    targ_noise[4]; /* over,max_noise,over_noise,tot_noise; */
  FLOAT8    xfsf[4][SBPSY_l];
  int       this_bits, dbits;
  int       used_bits=0;
  int       min_bits,max_bits,min_mean_bits=0;
  int       frameBits[15];
  int       bitsPerFrame;
  int       bits;
  int       mean_bits;
  int       i,ch, gr, analog_silence;
  int	    reparted = 0;

  iteration_init(gfp,l3_side,l3_enc);

#ifdef RH_QUALITY_CONTROL
  /* with RH_QUALITY_CONTROL we have to set masking_lower only once */
  set_masking_lower(gfp->VBR_q, 0 );
#endif      

  /*******************************************************************
   * how many bits are available for each bitrate?
   *******************************************************************/
  for( gfp->bitrate_index = 1;
       gfp->bitrate_index <= gfp->VBR_max_bitrate;
       gfp->bitrate_index++    ) {
    getframebits (gfp,&bitsPerFrame, &mean_bits);
    if (gfp->bitrate_index == gfp->VBR_min_bitrate) {
      /* always use at least this many bits per granule per channel */
      /* unless we detect analog silence, see below */
      min_mean_bits=mean_bits/gfp->stereo;
    }
    frameBits[gfp->bitrate_index]=
      ResvFrameBegin (gfp,l3_side, mean_bits, bitsPerFrame);
  }

  gfp->bitrate_index=gfp->VBR_max_bitrate;

  
  /*******************************************************************
   * how many bits would we use of it?
   *******************************************************************/
  analog_silence=0;
  for (gr = 0; gr < gfp->mode_gr; gr++) {
    int num_chan=gfp->stereo;
#ifdef  RH_SIDE_VBR
    /* my experiences are, that side channel reduction  
     * does more harm than good when VBR encoding
     * (Robert.Hegemann@gmx.de 2000-02-18)
     */
#else
    /* determine quality based on mid channel only */
    if (reduce_sidechannel) num_chan=1;  
#endif

    /* copy data to be quantized into xr */
    if (convert_mdct)
	ms_convert(xr[gr],xr[gr]);

    for (ch = 0; ch < num_chan; ch++) { 
      int real_bits;
      
      /******************************************************************
       * find smallest number of bits for an allowable quantization
       ******************************************************************/
      cod_info = &l3_side->gr[gr].ch[ch].tt;
      min_bits = Max(125,min_mean_bits);

      if (!init_outer_loop(gfp,xr[gr][ch], cod_info))
      {
        /* xr contains no energy 
         * cod_info was set in init_outer_loop above
	 */
        memset(&scalefac[gr][ch],0,sizeof(III_scalefac_t));
        memset(l3_enc[gr][ch],0,576*sizeof(int));
        save_bits[gr][ch] = 0;
#ifdef HAVEGTK
	if (gfp->gtkflag)
	  set_pinfo(cod_info, &ratio[gr][ch], &scalefac[gr][ch], xr[gr][ch], xfsf, noise, gr, ch);
#endif
	analog_silence=1;
	continue; /* with next channel */
      }
      
      memcpy( &clean_cod_info, cod_info, sizeof(gr_info) );
      
#ifdef RH_QUALITY_CONTROL
      /*
       * masking lower already set in the beginning
       */
#else
      /*
       * has to be set before calculating l3_xmin
       */
      set_masking_lower( gfp->VBR_q,2500 );
#endif      
      /* check for analolg silence */
      /* if energy < ATH, set min_bits = 125 */
      if (0==calc_xmin(gfp,xr[gr][ch], &ratio[gr][ch], cod_info, &l3_xmin)) {
	  analog_silence=1;
	  min_bits=125;
      }

      if (cod_info->block_type==SHORT_TYPE) {
	  min_bits += Max(1100,pe[gr][ch]);
	  min_bits=Min(min_bits,1800);
      }

      max_bits = 1200 + frameBits[gfp->VBR_max_bitrate]/(gfp->stereo*gfp->mode_gr);
      max_bits=Min(max_bits,2500);
      max_bits=Max(max_bits,min_bits);

      dbits = (max_bits-min_bits)/4;
      this_bits = (max_bits+min_bits)/2;
      real_bits = max_bits+1;

      /* bin search to within +/- 10 bits of optimal */
      do {
	  int better;
	  assert(this_bits>=min_bits);
	  assert(this_bits<=max_bits);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -