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

📄 lame.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:
  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)
{

  /*
   *  Disable floating point exepctions
   */
#ifdef __FreeBSD__
# include <floatingpoint.h>
  {
  /* seet floating point mask to the Linux default */
  fp_except_t mask;
  mask=fpgetmask();
  /* if bit is set, we get SIGFPE on that error! */
  fpsetmask(mask & ~(FP_X_INV|FP_X_DZ));
  /*  fprintf(stderr,"FreeBSD mask is 0x%x\n",mask); */
  }
#endif
#if defined(__riscos__) && !defined(ABORTFP)
  /* Disable FPE's under RISC OS */
  /* if bit is set, we disable trapping that error! */
  /*   _FPE_IVO : invalid operation */
  /*   _FPE_DVZ : divide by zero */
  /*   _FPE_OFL : overflow */
  /*   _FPE_UFL : underflow */
  /*   _FPE_INX : inexact */
  DisableFPETraps( _FPE_IVO | _FPE_DVZ | _FPE_OFL );
#endif


  /*
   *  Debugging stuff
   *  The default is to ignore FPE's, unless compiled with -DABORTFP
   *  so add code below to ENABLE FPE's.
   */

#if defined(ABORTFP) && !defined(__riscos__)
#if defined(_MSC_VER)
  {
	#include <float.h>
	unsigned int mask;
	mask=_controlfp( 0, 0 );
	mask&=~(_EM_OVERFLOW|_EM_UNDERFLOW|_EM_ZERODIVIDE|_EM_INVALID);
	mask=_controlfp( mask, _MCW_EM );
	}
#elif defined(__CYGWIN__)
#  define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
#  define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))

#  define _EM_INEXACT     0x00000001 /* inexact (precision) */
#  define _EM_UNDERFLOW   0x00000002 /* underflow */
#  define _EM_OVERFLOW    0x00000004 /* overflow */
#  define _EM_ZERODIVIDE  0x00000008 /* zero divide */
#  define _EM_INVALID     0x00000010 /* invalid */
  {
    unsigned int mask;
    _FPU_GETCW(mask);
    /* Set the FPU control word to abort on most FPEs */
    mask &= ~(_EM_UNDERFLOW | _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID);
    _FPU_SETCW(mask);
  }
# else
  {
#  include <fpu_control.h>
#ifndef _FPU_GETCW
#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw))
#endif
#ifndef _FPU_SETCW
#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw))
#endif
    unsigned int mask;
    _FPU_GETCW(mask);
    /* Set the Linux mask to abort on most FPE's */
    /* if bit is set, we _mask_ SIGFPE on that error! */
    /*  mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM );*/
    mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM );
    _FPU_SETCW(mask);
  }
#endif
#endif /* ABORTFP && !__riscos__ */



  /* 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->gtkflag=0;
  gfp->quality=5;
  gfp->input_format=sf_unknown;

  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->mode = MPG_MD_JOINT_STEREO;
  gfp->mode_fixed=0;
  gfp->force_ms=0;
  gfp->brate=0;
  gfp->copyright=0;
  gfp->original=1;
  gfp->extension=0;
  gfp->error_protection=0;
  gfp->emphasis=0;
  gfp->in_samplerate=1000*44.1;
  gfp->out_samplerate=0;
  gfp->num_channels=2;
  gfp->num_samples=MAX_U_32_NUM;

  gfp->inPath=NULL;
  gfp->outPath=NULL;
  id3tag.used=0;

}



/*****************************************************************/
/* 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 + -