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

📄 lame.c

📁 MP3编码的完整实现(源代码和使用例子都有)
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* 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) {
  int j;
  j=Min(desired_len,len);
  memcpy( (char *) outbuf,(char *)inbuf,sizeof(short int)*j);
  return j;
}




/*
 * THE MAIN LAME ENCODING INTERFACE
 * mt 3/00
 *
 * input pcm data, output (maybe) mp3 frames.
 * This routine handles all buffering, resampling and filtering for you.
 * The required mp3buffer_size can be computed from num_samples,
 * samplerate and encoding rate, but here is a worst case estimate:
 *
 * mp3buffer_size in bytes = 1.25*num_samples + 7200
 *
 * return code = number of bytes output in mp3buffer.  can be 0
*/
int lame_encode_buffer(lame_global_flags *gfp,
   short int buffer_l[], short int buffer_r[],int nsamples,
   char *mp3buf, int mp3buf_size)
{
  static int frame_buffered=0;
  int mp3size=0,ret,i,ch,mf_needed;

  short int *in_buffer[2];
  in_buffer[0] = buffer_l;
  in_buffer[1] = buffer_r;

  /* some sanity checks */
  assert(ENCDELAY>=MDCTDELAY);
  assert(BLKSIZE-FFTOFFSET >= 0);
  mf_needed = BLKSIZE+gfp->framesize-FFTOFFSET;
  assert(MFSIZE>=mf_needed);

  /* The reason for
   *       int mf_samples_to_encode = ENCDELAY + 288;
   * ENCDELAY = internal encoder delay.  And then we have to add 288
   * because of the 50% MDCT overlap.  A 576 MDCT granule decodes to
   * 1152 samples.  To synthesize the 576 samples centered under this granule
   * we need the previous granule for the first 288 samples (no problem), and
   * the next granule for the next 288 samples (not possible if this is last
   * granule).  So we need to pad with 288 samples to make sure we can
   * encode the 576 samples we are interested in.
   */
  if (gfp->frameNum==0 && !frame_buffered) {
    memset((char *) mfbuf, 0, sizeof(mfbuf));
    frame_buffered=1;
    mf_samples_to_encode = ENCDELAY+288;
    mf_size=ENCDELAY-MDCTDELAY;  /* we pad input with this many 0's */
  }
  if (gfp->frameNum==1) {
    /* reset, for the next time frameNum==0 */
    frame_buffered=0;
  }

  if (gfp->num_channels==2  && gfp->stereo==1) {
    /* downsample to mono */
    for (i=0; i<nsamples; ++i) {
      in_buffer[0][i]=((int)in_buffer[0][i]+(int)in_buffer[1][i])/2;
      in_buffer[1][i]=0;
    }
  }


  while (nsamples > 0) {
    int n_in=0;
    int n_out=0;
    /* copy in new samples */
    for (ch=0; ch<gfp->stereo; ch++) {
      if (gfp->resample_ratio!=1)  {
	n_out=fill_buffer_resample(gfp,&mfbuf[ch][mf_size],gfp->framesize,
					  in_buffer[ch],nsamples,&n_in,ch);
      } else {
	n_out=fill_buffer(gfp,&mfbuf[ch][mf_size],gfp->framesize,in_buffer[ch],nsamples);
	n_in = n_out;
      }
      in_buffer[ch] += n_in;
    }


    nsamples -= n_in;
    mf_size += n_out;
    assert(mf_size<=MFSIZE);
    mf_samples_to_encode += n_out;

    if (mf_size >= mf_needed) {
      /* encode the frame */
      ret = lame_encode_frame(gfp,mfbuf[0],mfbuf[1],mf_size,mp3buf,mp3buf_size);
      if (ret == -1) {
	/* fatel error: mp3buffer was too small */
	return -1;
      }
      mp3buf += ret;
      mp3size += ret;
      /* shift out old samples */
      mf_size -= gfp->framesize;
      mf_samples_to_encode -= gfp->framesize;
      for (ch=0; ch<gfp->stereo; ch++)
	for (i=0; i<mf_size; i++)
	  mfbuf[ch][i]=mfbuf[ch][i+gfp->framesize];
    }
  }
  assert(nsamples==0);
  return mp3size;
}




int lame_encode_buffer_interleaved(lame_global_flags *gfp,
   short int buffer[], int nsamples, char *mp3buf, int mp3buf_size)
{
  static int frame_buffered=0;
  int mp3size=0,ret,i,ch,mf_needed;

  /* some sanity checks */
  assert(ENCDELAY>=MDCTDELAY);
  assert(BLKSIZE-FFTOFFSET >= 0);
  mf_needed = BLKSIZE+gfp->framesize-FFTOFFSET;
  assert(MFSIZE>=mf_needed);

  if (gfp->num_channels == 1) {
    return lame_encode_buffer(gfp,buffer, NULL ,nsamples,mp3buf,mp3buf_size);
  }

  if (gfp->resample_ratio!=1)  {
    short int *buffer_l;
    short int *buffer_r;
    buffer_l=malloc(sizeof(short int)*nsamples);
    buffer_r=malloc(sizeof(short int)*nsamples);
    if (buffer_l == NULL || buffer_r == NULL) {
      return -1;
    }
    for (i=0; i<nsamples; i++) {
      buffer_l[i]=buffer[2*i];
      buffer_r[i]=buffer[2*i+1];
    }
    ret = lame_encode_buffer(gfp,buffer_l,buffer_r,nsamples,mp3buf,mp3buf_size);
    free(buffer_l);
    free(buffer_r);
    return ret;
  }


  if (gfp->frameNum==0 && !frame_buffered) {
    memset((char *) mfbuf, 0, sizeof(mfbuf));
    frame_buffered=1;
    mf_samples_to_encode = ENCDELAY+288;
    mf_size=ENCDELAY-MDCTDELAY;  /* we pad input with this many 0's */
  }
  if (gfp->frameNum==1) {
    /* reset, for the next time frameNum==0 */
    frame_buffered=0;
  }

  if (gfp->num_channels==2  && gfp->stereo==1) {
    /* downsample to mono */
    for (i=0; i<nsamples; ++i) {
      buffer[2*i]=((int)buffer[2*i]+(int)buffer[2*i+1])/2;
      buffer[2*i+1]=0;
    }
  }


  while (nsamples > 0) {
    int n_out;
    /* copy in new samples */
    n_out = Min(gfp->framesize,nsamples);
    for (i=0; i<n_out; ++i) {
      mfbuf[0][mf_size+i]=buffer[2*i];
      mfbuf[1][mf_size+i]=buffer[2*i+1];
    }
    buffer += 2*n_out;

    nsamples -= n_out;
    mf_size += n_out;
    assert(mf_size<=MFSIZE);
    mf_samples_to_encode += n_out;

    if (mf_size >= mf_needed) {
      /* encode the frame */
      ret = lame_encode_frame(gfp,mfbuf[0],mfbuf[1],mf_size,mp3buf,mp3buf_size);
      if (ret == -1) {
	/* fatel error: mp3buffer was too small */
	return -1;
      }
      mp3buf += ret;
      mp3size += ret;

      /* shift out old samples */
      mf_size -= gfp->framesize;
      mf_samples_to_encode -= gfp->framesize;
      for (ch=0; ch<gfp->stereo; ch++)
	for (i=0; i<mf_size; i++)
	  mfbuf[ch][i]=mfbuf[ch][i+gfp->framesize];
    }
  }
  assert(nsamples==0);
  return mp3size;
}














/* old LAME interface */
/* With this interface, it is the users responsibilty to keep track of the
 * buffered, unencoded samples.  Thus mf_samples_to_encode is not incremented.
 *
 * lame_encode() is also used to flush the PCM input buffer by
 * lame_encode_finish()
 */
int lame_encode(lame_global_flags *gfp, short int in_buffer[2][1152],char *mp3buf,int size){
  int imp3,save;
  save = mf_samples_to_encode;
  imp3= lame_encode_buffer(gfp,in_buffer[0],in_buffer[1],576*gfp->mode_gr,
        mp3buf,size);
  mf_samples_to_encode = save;
  return imp3;
}

/* initialize mp3 encoder */
void lame_init(lame_global_flags *gfp,int nFreq,int nChanel,int nLeave)
{

  /* Global flags.  set defaults here */
  gfp->allow_diff_short		= 0;
  gfp->ATHonly			= 0;
  gfp->noATH			= 0;
  gfp->bWriteVbrTag		= 1;
  gfp->cwlimit			= 0;
  gfp->disable_reservoir	= 0;
  gfp->experimentalX		= 0;
  gfp->experimentalY		= 0;
  gfp->experimentalZ		= 0;
  gfp->frameNum			= 0;
    gfp->input_format		= sf_wave;
  
  gfp->filter_type		= 0;
  gfp->lowpassfreq		= 0;
  gfp->highpassfreq		= 0;
  gfp->lowpasswidth		= -1;
  gfp->highpasswidth		= -1;
  gfp->lowpass1			= 0;
  gfp->lowpass2			= 0;
  gfp->highpass1		= 0;
  gfp->highpass2		= 0;
  gfp->lowpass_band		= 32;
  gfp->highpass_band		= -1;
  
  gfp->no_short_blocks		= 0;
  gfp->resample_ratio		= 1;
  gfp->padding_type		= 2;
  gfp->padding			= 0;
  gfp->swapbytes		= 0;
  gfp->silent			= 0;
  gfp->totalframes		= 0;
  gfp->VBR			= 0;
  gfp->VBR_q			= 4;
  gfp->VBR_min_bitrate_kbps	= 0;
  gfp->VBR_max_bitrate_kbps	= 0;
  gfp->VBR_min_bitrate		= 1;
  gfp->VBR_max_bitrate		= 13;
  
  //修改	
  gfp->version			= 1;   /* =1   Default: MPEG-1 */
  gfp->in_samplerate		= nFreq;
  gfp->out_samplerate		= nFreq;
  gfp->num_channels		= nChanel;
  
  gfp->mode			= 1;
  gfp->mode_fixed		= 0;
  gfp->force_ms			= 0;
   gfp->copyright		= 0;
  gfp->original			= 1;
  gfp->extension		= 0;
  gfp->error_protection		= 0;
  gfp->emphasis			= 0;
  gfp->num_samples		= 0xFFFFFFFF;
  
  gfp->inPath			= NULL;
  gfp->outPath			= NULL;
  //  id3tag.used		= 0;
  
  //以标准的mp3音频质量格式初始化
  gfp->VBR_min_bitrate_kbps	= 32;	//最小位率
  gfp->VBR_max_bitrate_kbps	= 256;	//最大位率
  
  gfp->brate			= 128;	//正常位率
  gfp->lowpassfreq		= -1;
  gfp->highpassfreq		= -1;
  gfp->VBR_q			=  0;
  gfp->VBR_min_bitrate_kbps	= 112;
  gfp->VBR_max_bitrate_kbps	= 320;
  gfp->mode			= 0; 
  gfp->mode_fixed		= 1; 
  gfp->quality			= nLeave;//质量等级
  

}



/*****************************************************************/
/* flush internal mp3 buffers,                                   */
/*****************************************************************/
int lame_encode_finish(lame_global_flags *gfp,char *mp3buffer, int mp3buffer_size)
{
  int imp3,mp3count,mp3buffer_size_remaining;
  short int buffer[2][1152];
  memset((char *)buffer,0,sizeof(buffer));
  mp3count = 0;

  while (mf_samples_to_encode > 0) {

    mp3buffer_size_remaining = mp3buffer_size - mp3count;
    /* if user specifed buffer size = 0, dont check size */
    if (mp3buffer_size == 0) mp3buffer_size_remaining=0;  
    imp3=lame_encode(gfp,buffer,mp3buffer,mp3buffer_size_remaining);

    if (imp3 == -1) {
      /* fatel error: mp3buffer too small */
      desalloc_buffer(&bs);    /* Deallocate all buffers */
      return -1;
    }
    mp3buffer += imp3;
    mp3count += imp3;
    mf_samples_to_encode -= gfp->framesize;
  }


  gfp->frameNum--;
  if (!gfp->gtkflag && !gfp->silent) {
      timestatus(gfp->out_samplerate,gfp->frameNum,gfp->totalframes,gfp->framesize);
#ifdef BRHIST
      if (disp_brhist)
	{
	  brhist_add_count();
	  brhist_disp();
	  brhist_disp_total(gfp);
	}
#endif
      fprintf(stderr,"\n");
      fflush(stderr);
  }


  III_FlushBitstream();
  mp3buffer_size_remaining = mp3buffer_size - mp3count;
  /* if user specifed buffer size = 0, dont check size */
  if (mp3buffer_size == 0) mp3buffer_size_remaining=0;  

  imp3= copy_buffer(mp3buffer,mp3buffer_size_remaining,&bs);
  if (imp3 == -1) {
    /* fatel error: mp3buffer too small */
    desalloc_buffer(&bs);    /* Deallocate all buffers */
    return -1;
  }

  mp3count += imp3;
  desalloc_buffer(&bs);    /* Deallocate all buffers */
  return mp3count;
}


/*****************************************************************/
/* write VBR Xing header, and ID3 tag, if asked for               */
/*****************************************************************/
void lame_mp3_tags(lame_global_flags *gfp)
{
  if (gfp->bWriteVbrTag)
    {
      /* Calculate relative quality of VBR stream
       * 0=best, 100=worst */
      int nQuality=gfp->VBR_q*100/9;
      /* Write Xing header again */
      PutVbrTag(gfp->outPath,nQuality,1-gfp->version);
    }


  /* write an ID3 tag  */
  if(id3tag.used) {
    id3_buildtag(&id3tag);
    id3_writetag(gfp->outPath, &id3tag);
  }
}


void lame_version(lame_global_flags *gfp,char *ostring) {
  strncpy(ostring,get_lame_version(),20);
}

⌨️ 快捷键说明

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