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

📄 lame.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:



  if (gfp->bWriteVbrTag)
    {
      /* Write initial VBR Header to bitstream */
      InitVbrTag(&bs,1-gfp->version,gfp->mode,gfp->samplerate_index);
    }

#ifdef HAVEGTK
  gtkflag=gfp->gtkflag;
#endif

#ifdef BRHIST
  if (gfp->VBR) {
    if (disp_brhist)
      brhist_init(gfp,1, 14);
  } else
    disp_brhist = 0;
#endif
  return;
}









/************************************************************************
 *
 * print_config
 *
 * PURPOSE:  Prints the encoding parameters used
 *
 ************************************************************************/
void lame_print_config(lame_global_flags *gfp)
{
  static const char *mode_names[4] = { "stereo", "j-stereo", "dual-ch", "single-ch" };
  FLOAT out_samplerate=gfp->out_samplerate/1000.0;
  FLOAT in_samplerate = gfp->resample_ratio*out_samplerate;
  FLOAT compression=
    (FLOAT)(gfp->stereo*16*out_samplerate)/(FLOAT)(gfp->brate);

  lame_print_version(stderr);
  if (gfp->num_channels==2 && gfp->stereo==1) {
    fprintf(stderr, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n");
  }
  if (gfp->resample_ratio!=1) {
    fprintf(stderr,"Resampling:  input=%ikHz  output=%ikHz\n",
	    (int)in_samplerate,(int)out_samplerate);
  }
  if (gfp->highpass2>0.0)
    fprintf(stderr, "Using polyphase highpass filter, transition band: %.0f Hz -  %.0f Hz\n",
	    gfp->highpass1*out_samplerate*500,
	    gfp->highpass2*out_samplerate*500);
  if (gfp->lowpass1>0.0)
    fprintf(stderr, "Using polyphase lowpass filter,  transition band:  %.0f Hz - %.0f Hz\n",
	    gfp->lowpass1*out_samplerate*500,
	    gfp->lowpass2*out_samplerate*500);

  if (gfp->gtkflag) {
    fprintf(stderr, "Analyzing %s \n",gfp->inPath);
  }
  else {
    fprintf(stderr, "Encoding %s to %s\n",
	    (strcmp(gfp->inPath, "-")? gfp->inPath : "stdin"),
	    (strcmp(gfp->outPath, "-")? gfp->outPath : "stdout"));
    if (gfp->VBR)
      fprintf(stderr, "Encoding as %.1fkHz VBR(q=%i) %s MPEG%i LayerIII  qval=%i\n",
	      gfp->out_samplerate/1000.0,
	      gfp->VBR_q,mode_names[gfp->mode],2-gfp->version,gfp->quality);
    else
      fprintf(stderr, "Encoding as %.1f kHz %d kbps %s MPEG%i LayerIII (%4.1fx)  qval=%i\n",
	      gfp->out_samplerate/1000.0,gfp->brate,
	      mode_names[gfp->mode],2-gfp->version,compression,gfp->quality);
  }
  fflush(stderr);
}












/************************************************************************
*
* encodeframe()           Layer 3
*
* encode a single frame
*
************************************************************************
lame_encode_frame()


                       gr 0            gr 1
inbuf:           |--------------|---------------|-------------|
MDCT output:  |--------------|---------------|-------------|

FFT's                    <---------1024---------->
                                         <---------1024-------->



    inbuf = buffer of PCM data size=MP3 framesize
    encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY
    so the MDCT coefficints are from inbuf[ch][-MDCTDELAY]

    psy-model FFT has a 1 granule day, so we feed it data for the next granule.
    FFT is centered over granule:  224+576+224
    So FFT starts at:   576-224-MDCTDELAY

    MPEG2:  FFT ends at:  BLKSIZE+576-224-MDCTDELAY
    MPEG1:  FFT ends at:  BLKSIZE+2*576-224-MDCTDELAY    (1904)

    FFT starts at 576-224-MDCTDELAY (304)  = 576-FFTOFFSET

*/
int lame_encode_frame(lame_global_flags *gfp,
short int inbuf_l[],short int inbuf_r[],
int mf_size,char *mp3buf, int mp3buf_size)
{
  static unsigned long frameBits;
  static unsigned long bitsPerSlot;
  static FLOAT8 frac_SpF;
  static FLOAT8 slot_lag;
  static unsigned long sentBits = 0;
  FLOAT8 xr[2][2][576];
  int l3_enc[2][2][576];
  int mp3count;
  III_psy_ratio masking_ratio[2][2];    /*LR ratios */
  III_psy_ratio masking_MS_ratio[2][2]; /*MS ratios */
  III_psy_ratio (*masking)[2][2];  /*LR ratios and MS ratios*/
  III_scalefac_t scalefac[2][2];
  short int *inbuf[2];

  typedef FLOAT8 pedata[2][2];
  pedata pe,pe_MS;
  pedata *pe_use;

  int ch,gr,mean_bits;
  int bitsPerFrame;

  int check_ms_stereo;
  static FLOAT8 ms_ratio[2]={0,0};
  FLOAT8 ms_ratio_next=0;
  FLOAT8 ms_ratio_prev=0;
  static FLOAT8 ms_ener_ratio[2]={0,0};

  memset((char *) masking_ratio, 0, sizeof(masking_ratio));
  memset((char *) masking_MS_ratio, 0, sizeof(masking_MS_ratio));
  memset((char *) scalefac, 0, sizeof(scalefac));
  inbuf[0]=inbuf_l;
  inbuf[1]=inbuf_r;

  gfp->mode_ext = MPG_MD_LR_LR;

  if (gfp->frameNum==0 )  {
    /* Figure average number of 'slots' per frame. */
    FLOAT8 avg_slots_per_frame;
    FLOAT8 sampfreq =   gfp->out_samplerate/1000.0;
    int bit_rate = gfp->brate;
    sentBits = 0;
    bitsPerSlot = 8;
    avg_slots_per_frame = (bit_rate*gfp->framesize) /
           (sampfreq* bitsPerSlot);
    /* -f fast-math option causes some strange rounding here, be carefull: */
    frac_SpF  = avg_slots_per_frame - floor(avg_slots_per_frame + 1e-9);
    if (fabs(frac_SpF) < 1e-9) frac_SpF = 0;

    slot_lag  = -frac_SpF;
    gfp->padding = 1;
    if (frac_SpF==0) gfp->padding = 0;
    /* check FFT will not use a negative starting offset */
    assert(576>=FFTOFFSET);
    /* check if we have enough data for FFT */
    assert(mf_size>=(BLKSIZE+gfp->framesize-FFTOFFSET));
  }


  /********************** padding *****************************/
  switch (gfp->padding_type) {
  case 0:
    gfp->padding=0;
    break;
  case 1:
    gfp->padding=1;
    break;
  case 2:
  default:
    if (gfp->VBR) {
      gfp->padding=0;
    } else {
      if (gfp->disable_reservoir) {
	gfp->padding = 0;
	/* if the user specified --nores, dont very gfp->padding either */
	/* tiny changes in frac_SpF rounding will cause file differences */
      }else{
	if (frac_SpF != 0) {
	  if (slot_lag > (frac_SpF-1.0) ) {
	    slot_lag -= frac_SpF;
	    gfp->padding = 0;
	  }
	  else {
	    gfp->padding = 1;
	    slot_lag += (1-frac_SpF);
	  }
	}
      }
    }
  }


  /********************** status display  *****************************/
  if (!gfp->gtkflag && !gfp->silent) {
    int mod = gfp->version == 0 ? 200 : 50;
    if (gfp->frameNum%mod==0) {
      timestatus(gfp->out_samplerate,gfp->frameNum,gfp->totalframes,gfp->framesize);
#ifdef BRHIST
      if (disp_brhist)
	{
	  brhist_add_count();
	  brhist_disp();
	}
#endif
    }
  }


  if (gfp->psymodel) {
    /* psychoacoustic model
     * psy model has a 1 granule (576) delay that we must compensate for
     * (mt 6/99).
     */
    short int *bufp[2];  /* address of beginning of left & right granule */
    int blocktype[2];

    ms_ratio_prev=ms_ratio[gfp->mode_gr-1];
    for (gr=0; gr < gfp->mode_gr ; gr++) {

      for ( ch = 0; ch < gfp->stereo; ch++ )
	bufp[ch] = &inbuf[ch][576 + gr*576-FFTOFFSET];

      L3psycho_anal( gfp,bufp, gr, 
		     &ms_ratio[gr],&ms_ratio_next,&ms_ener_ratio[gr],
		     masking_ratio, masking_MS_ratio,
		     pe[gr],pe_MS[gr],blocktype);

      for ( ch = 0; ch < gfp->stereo; ch++ )
	l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch];

    }
  }else{
    for (gr=0; gr < gfp->mode_gr ; gr++)
      for ( ch = 0; ch < gfp->stereo; ch++ ) {
	l3_side.gr[gr].ch[ch].tt.block_type=NORM_TYPE;
	pe[gr][ch]=700;
      }
  }


  /* block type flags */
  for( gr = 0; gr < gfp->mode_gr; gr++ ) {
    for ( ch = 0; ch < gfp->stereo; ch++ ) {
      gr_info *cod_info = &l3_side.gr[gr].ch[ch].tt;
      cod_info->mixed_block_flag = 0;     /* never used by this model */
      if (cod_info->block_type == NORM_TYPE )
	cod_info->window_switching_flag = 0;
      else
	cod_info->window_switching_flag = 1;
    }
  }

  /* polyphase filtering / mdct */
  mdct_sub48(gfp,inbuf[0], inbuf[1], xr, &l3_side);

  /* use m/s gfp->stereo? */
  check_ms_stereo =  (gfp->mode == MPG_MD_JOINT_STEREO);
  if (check_ms_stereo) {
    /* make sure block type is the same in each channel */
    check_ms_stereo =
      (l3_side.gr[0].ch[0].tt.block_type==l3_side.gr[0].ch[1].tt.block_type) &&
      (l3_side.gr[1].ch[0].tt.block_type==l3_side.gr[1].ch[1].tt.block_type);
  }
  if (check_ms_stereo) {
    /* ms_ratio = is like the ratio of side_energy/total_energy */
    FLOAT8 ms_ratio_ave,ms_ener_ratio_ave;
    /*     ms_ratio_ave = .5*(ms_ratio[0] + ms_ratio[1]);*/
    ms_ratio_ave = .25*(ms_ratio[0] + ms_ratio[1]+
			 ms_ratio_prev + ms_ratio_next);
    ms_ener_ratio_ave = .5*(ms_ener_ratio[0]+ms_ener_ratio[1]);
    if ( ms_ratio_ave <.35 /*&& ms_ener_ratio_ave<.75*/ ) gfp->mode_ext = MPG_MD_MS_LR;
  }
  if (gfp->force_ms) gfp->mode_ext = MPG_MD_MS_LR;


#ifdef HAVEGTK
  if (gfp->gtkflag) {
    int j;
    for ( gr = 0; gr < gfp->mode_gr; gr++ ) {
      for ( ch = 0; ch < gfp->stereo; ch++ ) {
	pinfo->ms_ratio[gr]=ms_ratio[gr];
	pinfo->ms_ener_ratio[gr]=ms_ener_ratio[gr];
	pinfo->blocktype[gr][ch]=
	  l3_side.gr[gr].ch[ch].tt.block_type;
	for ( j = 0; j < 576; j++ ) pinfo->xr[gr][ch][j]=xr[gr][ch][j];
	/* if MS stereo, switch to MS psy data */
	if (gfp->mode_ext==MPG_MD_MS_LR) {
	  pinfo->pe[gr][ch]=pinfo->pe[gr][ch+2];
	  pinfo->ers[gr][ch]=pinfo->ers[gr][ch+2];
	  memcpy(pinfo->energy[gr][ch],pinfo->energy[gr][ch+2],
		 sizeof(pinfo->energy[gr][ch]));
	}
      }
    }
  }
#endif




  /* bit and noise allocation */
  if (MPG_MD_MS_LR == gfp->mode_ext) {
    masking = &masking_MS_ratio;    /* use MS masking */
    pe_use=&pe_MS;
  } else {
    masking = &masking_ratio;    /* use LR masking */
    pe_use=&pe;
  }


  /*
  VBR_iteration_loop_new( gfp,*pe_use, ms_ratio, xr, masking, &l3_side, l3_enc,
  	  &scalefac);
  */


  if (gfp->VBR) {
    VBR_iteration_loop( gfp,*pe_use, ms_ratio, xr, *masking, &l3_side, l3_enc,
			scalefac);
  }else{
    iteration_loop( gfp,*pe_use, ms_ratio, xr, *masking, &l3_side, l3_enc,
		    scalefac);
  }




#ifdef BRHIST
  brhist_temp[gfp->bitrate_index]++;
#endif


  /*  write the frame to the bitstream  */
  getframebits(gfp,&bitsPerFrame,&mean_bits);
  III_format_bitstream( gfp,bitsPerFrame, l3_enc, &l3_side,
			scalefac, &bs);


  frameBits = bs.totbit - sentBits;


  if ( frameBits % bitsPerSlot )   /* a program failure */
    fprintf( stderr, "Sent %ld bits = %ld slots plus %ld\n",
	     frameBits, frameBits/bitsPerSlot,
	     frameBits%bitsPerSlot );
  sentBits += frameBits;

  /* copy mp3 bit buffer into array */
  mp3count = copy_buffer(mp3buf,mp3buf_size,&bs);

  if (gfp->bWriteVbrTag) AddVbrFrame((int)(sentBits/8));

#ifdef HAVEGTK
  if (gfp->gtkflag) {
    int j;
    for ( ch = 0; ch < gfp->stereo; ch++ ) {
      for ( j = 0; j < FFTOFFSET; j++ )
	pinfo->pcmdata[ch][j] = pinfo->pcmdata[ch][j+gfp->framesize];
      for ( j = FFTOFFSET; j < 1600; j++ ) {
	pinfo->pcmdata[ch][j] = inbuf[ch][j-FFTOFFSET];
      }
    }
  }
#endif
  gfp->frameNum++;

  return mp3count;
}



int fill_buffer_resample(lame_global_flags *gfp,short int *outbuf,int desired_len,
        short int *inbuf,int len,int *num_used,int ch) {

  static FLOAT8 itime[2];
#define OLDBUFSIZE 5
  static short int inbuf_old[2][OLDBUFSIZE];
  static int init[2]={0,0};
  int i,j=0,k,linear,value;

  if (gfp->frameNum==0 && !init[ch]) {
    init[ch]=1;
    itime[ch]=0;
    memset((char *) inbuf_old[ch], 0, sizeof(short int)*OLDBUFSIZE);
  }
  if (gfp->frameNum!=0) init[ch]=0; /* reset, for next time framenum=0 */


  /* if downsampling by an integer multiple, use linear resampling,
   * otherwise use quadratic */
  linear = ( fabs(gfp->resample_ratio - floor(.5+gfp->resample_ratio)) < .0001 );

  /* time of j'th element in inbuf = itime + j/ifreq; */
  /* time of k'th element in outbuf   =  j/ofreq */
  for (k=0;k<desired_len;k++) {
    int y0,y1,y2,y3;
    FLOAT8 x0,x1,x2,x3;
    FLOAT8 time0;

    time0 = k*gfp->resample_ratio;       /* time of k'th output sample */
    j = floor( time0 -itime[ch]  );
    /* itime[ch] + j;    */            /* time of j'th input sample */
    if (j+2 >= len) break;             /* not enough data in input buffer */

    x1 = time0-(itime[ch]+j);
    x2 = x1-1;
    y1 = (j<0) ? inbuf_old[ch][OLDBUFSIZE+j] : inbuf[j];
    y2 = ((1+j)<0) ? inbuf_old[ch][OLDBUFSIZE+1+j] : inbuf[1+j];

    /* linear resample */
    if (linear) {
      outbuf[k] = floor(.5 +  (y2*x1-y1*x2) );
    } else {
      /* quadratic */
      x0 = x1+1;
      x3 = x1-2;
      y0 = ((j-1)<0) ? inbuf_old[ch][OLDBUFSIZE+(j-1)] : inbuf[j-1];
      y3 = ((j+2)<0) ? inbuf_old[ch][OLDBUFSIZE+(j+2)] : inbuf[j+2];
      value = floor(.5 +
			-y0*x1*x2*x3/6 + y1*x0*x2*x3/2 - y2*x0*x1*x3/2 +y3*x0*x1*x2/6
			);
      if (value > 32767) outbuf[k]=32767;
      else if (value < -32767) outbuf[k]=-32767;
      else outbuf[k]=value;

      /*
      printf("k=%i  new=%i   [ %i %i %i %i ]\n",k,outbuf[k],
	     y0,y1,y2,y3);
      */
    }
  }


  /* k = number of samples added to outbuf */
  /* last k sample used data from j,j+1, or j+1 overflowed buffer */
  /* remove num_used samples from inbuf: */
  *num_used = Min(len,j+2);
  itime[ch] += *num_used - k*gfp->resample_ratio;
  for (i=0;i<OLDBUFSIZE;i++)
    inbuf_old[ch][i]=inbuf[*num_used + i -OLDBUFSIZE];
  return k;
}




int fill_buffer(lame_global_flags *gfp,short int *outbuf,int desired_len,short int *inbuf,int len) {

⌨️ 快捷键说明

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