📄 util.c
字号:
sample_t *outbuf, int desired_len, sample_t *inbuf, int len, int *num_used, int ch) { lame_internal_flags *gfc=gfp->internal_flags; int BLACKSIZE; FLOAT offset,xvalue; int i,j=0,k; int filter_l; FLOAT fcn,intratio; FLOAT *inbuf_old; int bpc; /* number of convolution functions to pre-compute */ bpc = gfp->out_samplerate/gcd(gfp->out_samplerate,gfp->in_samplerate); if (bpc>BPC) bpc = BPC; intratio=( fabs(gfc->resample_ratio - floor(.5+gfc->resample_ratio)) < .0001 ); fcn = 1.00/gfc->resample_ratio; if (fcn>1.00) fcn=1.00; filter_l = gfp->quality < 7 ? 31 : 7; filter_l = 31; if (0==filter_l % 2 ) --filter_l;/* must be odd */ filter_l += intratio; /* unless resample_ratio=int, it must be even */ BLACKSIZE = filter_l+1; /* size of data needed for FIR */ if ( gfc->fill_buffer_resample_init == 0 ) { gfc->inbuf_old[0]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); gfc->inbuf_old[1]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); for (i=0; i<=2*bpc; ++i) gfc->blackfilt[i]=calloc(BLACKSIZE,sizeof(gfc->blackfilt[0][0])); gfc->itime[0]=0; gfc->itime[1]=0; /* precompute blackman filter coefficients */ for ( j = 0; j <= 2*bpc; j++ ) { FLOAT sum = 0.; offset = (j-bpc) / (2.*bpc); for ( i = 0; i <= filter_l; i++ ) sum += gfc->blackfilt[j][i] = blackman(i-offset,fcn,filter_l); for ( i = 0; i <= filter_l; i++ ) gfc->blackfilt[j][i] /= sum; } gfc->fill_buffer_resample_init = 1; } inbuf_old=gfc->inbuf_old[ch]; /* 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++) { FLOAT time0; int joff; time0 = k*gfc->resample_ratio; /* time of k'th output sample */ j = floor( time0 -gfc->itime[ch] ); /* check if we need more input data */ if ((filter_l + j - filter_l/2) >= len) break; /* blackman filter. by default, window centered at j+.5(filter_l%2) */ /* but we want a window centered at time0. */ offset = ( time0 -gfc->itime[ch] - (j + .5*(filter_l%2))); assert(fabs(offset)<=.501); /* find the closest precomputed window for this offset: */ joff = floor((offset*2*bpc) + bpc +.5); xvalue = 0.; for (i=0 ; i<=filter_l ; ++i) { int j2 = i+j-filter_l/2; sample_t y; assert(j2<len); assert(j2+BLACKSIZE >= 0); y = (j2<0) ? inbuf_old[BLACKSIZE+j2] : inbuf[j2];#define PRECOMPUTE#ifdef PRECOMPUTE xvalue += y*gfc->blackfilt[joff][i];#else xvalue += y*blackman(i-offset,fcn,filter_l); /* very slow! */#endif } outbuf[k]=xvalue; } /* k = number of samples added to outbuf */ /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2] */ /* how many samples of input data were used: */ *num_used = Min(len,filter_l+j-filter_l/2); /* adjust our input time counter. Incriment by the number of samples used, * then normalize so that next output sample is at time 0, next * input buffer is at time itime[ch] */ gfc->itime[ch] += *num_used - k*gfc->resample_ratio; /* save the last BLACKSIZE samples into the inbuf_old buffer */ if (*num_used >= BLACKSIZE) { for (i=0;i<BLACKSIZE;i++) inbuf_old[i]=inbuf[*num_used + i -BLACKSIZE]; }else{ /* shift in *num_used samples into inbuf_old */ int n_shift = BLACKSIZE-*num_used; /* number of samples to shift */ /* shift n_shift samples by *num_used, to make room for the * num_used new samples */ for (i=0; i<n_shift; ++i ) inbuf_old[i] = inbuf_old[i+ *num_used]; /* shift in the *num_used samples */ for (j=0; i<BLACKSIZE; ++i, ++j ) inbuf_old[i] = inbuf[j]; assert(j==*num_used); } return k; /* return the number samples created at the new samplerate */}/************************************************************************* Message Output************************************************************************/void lame_debugf (const lame_internal_flags *gfc, const char* format, ... ){ va_list args; va_start ( args, format ); if ( gfc->report.debugf != NULL ) { gfc->report.debugf( format, args ); } else { (void) vfprintf ( stderr, format, args ); fflush ( stderr ); /* an debug function should flush immediately */ } va_end ( args );}void lame_msgf (const lame_internal_flags *gfc, const char* format, ... ){ va_list args; va_start ( args, format ); if ( gfc->report.msgf != NULL ) { gfc->report.msgf( format, args ); } else { (void) vfprintf ( stderr, format, args ); fflush ( stderr ); /* we print to stderr, so me may want to flush */ } va_end ( args );}void lame_errorf (const lame_internal_flags *gfc, const char* format, ... ){ va_list args; va_start ( args, format ); if ( gfc->report.errorf != NULL ) { gfc->report.errorf( format, args ); } else { (void) vfprintf ( stderr, format, args ); fflush ( stderr ); /* an error function should flush immediately */ } va_end ( args );}/*********************************************************************** * * routines to detect CPU specific features like 3DNow, MMX, SSE * * donated by Frank Klemm * added Robert Hegemann 2000-10-10 * ***********************************************************************/int has_MMX ( void ){#ifdef HAVE_NASM extern int has_MMX_nasm ( void ); return has_MMX_nasm ();#else return 0; /* don't know, assume not */#endif} int has_3DNow ( void ){#ifdef HAVE_NASM extern int has_3DNow_nasm ( void ); return has_3DNow_nasm ();#else return 0; /* don't know, assume not */#endif} int has_SSE ( void ){#ifdef HAVE_NASM extern int has_SSE_nasm ( void ); return has_SSE_nasm ();#else return 0; /* don't know, assume not */#endif} int has_SSE2 ( void ){#ifdef HAVE_NASM extern int has_SSE2_nasm ( void ); return has_SSE2_nasm ();#else return 0; /* don't know, assume not */#endif} void disable_FPE(void) {/* extremly system dependent stuff, move to a lib to make the code readable *//*==========================================================================*/ /* * Disable floating point exceptions */#if defined(__FreeBSD__) && !defined(__alpha__) { /* 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)); /* DEBUGF("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)#if defined(_MSC_VER) { /* set affinity to a single CPU. Fix for EAC/lame on SMP systems from "Todd Richmond" <todd.richmond@openwave.com> */ SYSTEM_INFO si; GetSystemInfo(&si); SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask);#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 0x00000020 /* inexact (precision) */# define _EM_UNDERFLOW 0x00000010 /* underflow */# define _EM_OVERFLOW 0x00000008 /* overflow */# define _EM_ZERODIVIDE 0x00000004 /* zero divide */# define _EM_INVALID 0x00000001 /* invalid */ { unsigned int mask; _FPU_GETCW(mask); /* Set the FPU control word to abort on most FPEs */ mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); _FPU_SETCW(mask); }# elif defined(__linux__) {# 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 /* * 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 ); */ unsigned int mask; _FPU_GETCW(mask); mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM); _FPU_SETCW(mask); }#endif#endif /* ABORTFP */}#ifdef USE_FAST_LOG/*********************************************************************** * * Fast Log Approximation for log2, used to approximate every other log * (log10 and log) * maximum absolute error for log10 is around 10-6 * maximum *relative* error can be high when x is almost 1 because error/log10(x) tends toward x/e * * use it if typical RESULT values are > 1e-5 (for example if x>1.00001 or x<0.99999) * or if the relative precision in the domain around 1 is not important (result in 1 is exact and 0) * ***********************************************************************/#define LOG2_SIZE (512)#define LOG2_SIZE_L2 (9)static ieee754_float32_t log_table[LOG2_SIZE+1];void init_log_table(void){ int j; static int init = 0; /* Range for log2(x) over [1,2[ is [0,1[ */ assert((1<<LOG2_SIZE_L2)==LOG2_SIZE); if(!init) { for(j=0; j<LOG2_SIZE+1; j++) log_table[j] = log(1.0f+j/(ieee754_float32_t)LOG2_SIZE)/log(2.0f); } init = 1;}ieee754_float32_t fast_log2(ieee754_float32_t x){ ieee754_float32_t log2val, partial; union { ieee754_float32_t f; int i; } fi; int mantisse; fi.f = x; mantisse = fi.i & 0x7fffff; log2val = ((fi.i>>23) & 0xFF)-0x7f; partial = (mantisse & ((1<<(23-LOG2_SIZE_L2))-1)); partial *= 1.0f/((1<<(23-LOG2_SIZE_L2))); mantisse >>= (23-LOG2_SIZE_L2); /* log2val += log_table[mantisse]; without interpolation the results are not good */ log2val += log_table[mantisse] * (1.0f-partial) + log_table[mantisse+1]*partial; return log2val;}#else /* Don't use FAST_LOG */void init_log_table(void){}#endif/* end of util.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -