📄 lame.c
字号:
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 + -