diff options
Diffstat (limited to 'contrib/ffmpeg/libavcodec/resample2.c')
-rw-r--r-- | contrib/ffmpeg/libavcodec/resample2.c | 88 |
1 files changed, 70 insertions, 18 deletions
diff --git a/contrib/ffmpeg/libavcodec/resample2.c b/contrib/ffmpeg/libavcodec/resample2.c index 3ae0ba855..4209b9705 100644 --- a/contrib/ffmpeg/libavcodec/resample2.c +++ b/contrib/ffmpeg/libavcodec/resample2.c @@ -30,20 +30,31 @@ #include "common.h" #include "dsputil.h" -#if 1 +#ifndef CONFIG_RESAMPLE_HP #define FILTER_SHIFT 15 #define FELEM int16_t #define FELEM2 int32_t +#define FELEML int64_t #define FELEM_MAX INT16_MAX #define FELEM_MIN INT16_MIN -#else -#define FILTER_SHIFT 22 +#define WINDOW_TYPE 9 +#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE) +#define FILTER_SHIFT 30 #define FELEM int32_t #define FELEM2 int64_t +#define FELEML int64_t #define FELEM_MAX INT32_MAX #define FELEM_MIN INT32_MIN +#define WINDOW_TYPE 12 +#else +#define FILTER_SHIFT 0 + +#define FELEM double +#define FELEM2 double +#define FELEML double +#define WINDOW_TYPE 24 #endif @@ -69,9 +80,10 @@ static double bessel(double x){ double t=1; int i; + x= x*x/4; for(i=1; i<50; i++){ - t *= i; - v += pow(x*x/4, i)/(t*t); + t *= x/(i*i); + v += t; } return v; } @@ -80,7 +92,7 @@ static double bessel(double x){ * builds a polyphase filterbank. * @param factor resampling factor * @param scale wanted sum of coefficients for each filter - * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2->kaiser windowed sinc beta=16 + * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16 */ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){ int ph, i, v; @@ -93,7 +105,6 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun for(ph=0;ph<phase_count;ph++) { double norm = 0; - double e= 0; for(i=0;i<tap_count;i++) { x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor; if (x == 0) y = 1.0; @@ -109,9 +120,9 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun w = 2.0*x / (factor*tap_count) + M_PI; y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w); break; - case 2: + default: w = 2.0*x / (factor*tap_count*M_PI); - y *= bessel(16*sqrt(FFMAX(1-w*w, 0))); + y *= bessel(type*sqrt(FFMAX(1-w*w, 0))); break; } @@ -121,11 +132,49 @@ void av_build_filter(FELEM *filter, double factor, int tap_count, int phase_coun /* normalize so that an uniform color remains the same */ for(i=0;i<tap_count;i++) { - v = clip(lrintf(tab[i] * scale / norm + e), FELEM_MIN, FELEM_MAX); - filter[ph * tap_count + i] = v; - e += tab[i] * scale / norm - v; +#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE + filter[ph * tap_count + i] = tab[i] / norm; +#else + filter[ph * tap_count + i] = av_clip(lrintf(tab[i] * scale / norm), FELEM_MIN, FELEM_MAX); +#endif + } + } +#if 0 + { +#define LEN 1024 + int j,k; + double sine[LEN + tap_count]; + double filtered[LEN]; + double maxff=-2, minff=2, maxsf=-2, minsf=2; + for(i=0; i<LEN; i++){ + double ss=0, sf=0, ff=0; + for(j=0; j<LEN+tap_count; j++) + sine[j]= cos(i*j*M_PI/LEN); + for(j=0; j<LEN; j++){ + double sum=0; + ph=0; + for(k=0; k<tap_count; k++) + sum += filter[ph * tap_count + k] * sine[k+j]; + filtered[j]= sum / (1<<FILTER_SHIFT); + ss+= sine[j + center] * sine[j + center]; + ff+= filtered[j] * filtered[j]; + sf+= sine[j + center] * filtered[j]; + } + ss= sqrt(2*ss/LEN); + ff= sqrt(2*ff/LEN); + sf= 2*sf/LEN; + maxff= FFMAX(maxff, ff); + minff= FFMIN(minff, ff); + maxsf= FFMAX(maxsf, sf); + minsf= FFMIN(minsf, sf); + if(i%11==0){ + av_log(NULL, AV_LOG_ERROR, "i:%4d ss:%f ff:%13.6e-%13.6e sf:%13.6e-%13.6e\n", i, ss, maxff, minff, maxsf, minsf); + minff=minsf= 2; + maxff=maxsf= -2; + } } } +#endif } /** @@ -143,7 +192,7 @@ AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_size, c->filter_length= FFMAX((int)ceil(filter_size/factor), 1); c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM)); - av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, 1); + av_build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<<FILTER_SHIFT, WINDOW_TYPE); memcpy(&c->filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; @@ -219,21 +268,24 @@ int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int }else if(sample_index + c->filter_length > src_size){ break; }else if(c->linear){ - int64_t v=0; - int sub_phase= (frac<<8) / c->src_incr; + FELEM2 v2=0; for(i=0; i<c->filter_length; i++){ - int64_t coeff= filter[i]*(256 - sub_phase) + filter[i + c->filter_length]*sub_phase; - v += src[sample_index + i] * coeff; + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; } - val= v>>8; + val+=(v2-val)*(FELEML)frac / c->src_incr; }else{ for(i=0; i<c->filter_length; i++){ val += src[sample_index + i] * (FELEM2)filter[i]; } } +#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE + dst[dst_index] = av_clip(lrintf(val), -32768, 32767); +#else val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; +#endif frac += dst_incr_frac; index += dst_incr; |