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