// create an instance of the decoder // blocksize is fixed over the lifetime of this object for performance reasons decoder_impl(unsigned blocksize=8192): N(blocksize), halfN(blocksize/2) { #ifdef USE_FFTW3 // create FFTW buffers lt = (float*)fftwf_malloc(sizeof(float)*N); rt = (float*)fftwf_malloc(sizeof(float)*N); dst = (float*)fftwf_malloc(sizeof(float)*N); dftL = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N); dftR = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N); src = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N); loadL = fftwf_plan_dft_r2c_1d(N, lt, dftL,FFTW_MEASURE); loadR = fftwf_plan_dft_r2c_1d(N, rt, dftR,FFTW_MEASURE); store = fftwf_plan_dft_c2r_1d(N, src, dst,FFTW_MEASURE); #else // create lavc fft buffers lt = (float*)av_malloc(sizeof(FFTSample)*N); rt = (float*)av_malloc(sizeof(FFTSample)*N); dftL = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2); dftR = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2); src = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2); fftContextForward = (FFTContext*)av_malloc(sizeof(FFTContext)); memset(fftContextForward, 0, sizeof(FFTContext)); fftContextReverse = (FFTContext*)av_malloc(sizeof(FFTContext)); memset(fftContextReverse, 0, sizeof(FFTContext)); ff_fft_init(fftContextForward, 13, 0); ff_fft_init(fftContextReverse, 13, 1); #endif // resize our own buffers frontR.resize(N); frontL.resize(N); avg.resize(N); surR.resize(N); surL.resize(N); trueavg.resize(N); xfs.resize(N); yfs.resize(N); inbuf[0].resize(N); inbuf[1].resize(N); for (unsigned c=0;c<6;c++) { outbuf[c].resize(N); filter[c].resize(N); } sample_rate(48000); // generate the window function (square root of hann, b/c it is applied before and after the transform) wnd.resize(N); for (unsigned k=0;k<N;k++) wnd[k] = sqrt(0.5*(1-cos(2*PI*k/N))/N); current_buf = 0; memset(inbufs, 0, sizeof(inbufs)); memset(outbufs, 0, sizeof(outbufs)); // set the default coefficients surround_coefficients(0.8165,0.5774); phase_mode(0); separation(1,1); steering_mode(true); }
/** * init MDCT or IMDCT computation. */ int ff_mdct_init(MDCTContext *s, int nbits, int inverse) { int n, n4, i; double alpha; memset(s, 0, sizeof(*s)); n = 1 << nbits; s->nbits = nbits; s->n = n; n4 = n >> 2; s->tcos = av_malloc(n4 * sizeof(FFTSample)); if (!s->tcos) goto fail; s->tsin = av_malloc(n4 * sizeof(FFTSample)); if (!s->tsin) goto fail; for(i=0;i<n4;i++) { alpha = 2 * M_PI * (i + 1.0 / 8.0) / n; s->tcos[i] = -cos(alpha); s->tsin[i] = -sin(alpha); } if (ff_fft_init(&s->fft, s->nbits - 2, inverse) < 0) goto fail; return 0; fail: av_freep(&s->tcos); av_freep(&s->tsin); return -1; }
static int init_cook_mlt(COOKContext *q) { int j; float alpha; /* Allocate the buffers, could be replaced with a static [512] array if needed. */ q->mlt_size = q->samples_per_channel; q->mlt_window = av_malloc(sizeof(float)*q->mlt_size); q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2); q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2); q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2); /* Initialize the MLT window: simple sine window. */ alpha = M_PI / (2.0 * (float)q->mlt_size); for(j=0 ; j<q->mlt_size ; j++) { q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); } /* pre/post twiddle factors */ for (j=0 ; j<q->mlt_size/2 ; j++){ q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); q->mlt_postcos[j] = (float)sqrt(2.0/(float)q->mlt_size)*cos( ((float)j*M_PI) /q->mlt_size); //sqrt(2/MLT_size) = scalefactor } /* Initialize the FFT. */ ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0); av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n", av_log2(q->samples_per_channel)-1); return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos); }
static av_cold int imc_decode_init(AVCodecContext * avctx) { int i, j; IMCContext *q = avctx->priv_data; double r1, r2; q->decoder_reset = 1; for(i = 0; i < BANDS; i++) q->old_floor[i] = 1.0; /* Build mdct window, a simple sine window normalized with sqrt(2) */ ff_sine_window_init(q->mdct_sine_window, COEFFS); for(i = 0; i < COEFFS; i++) q->mdct_sine_window[i] *= sqrt(2.0); for(i = 0; i < COEFFS/2; i++){ q->post_cos[i] = cos(i / 256.0 * M_PI); q->post_sin[i] = sin(i / 256.0 * M_PI); r1 = sin((i * 4.0 + 1.0) / 1024.0 * M_PI); r2 = cos((i * 4.0 + 1.0) / 1024.0 * M_PI); if (i & 0x1) { q->pre_coef1[i] = (r1 + r2) * sqrt(2.0); q->pre_coef2[i] = -(r1 - r2) * sqrt(2.0); } else { q->pre_coef1[i] = -(r1 + r2) * sqrt(2.0); q->pre_coef2[i] = (r1 - r2) * sqrt(2.0); } q->last_fft_im[i] = 0; } /* Generate a square root table */ for(i = 0; i < 30; i++) { q->sqrt_tab[i] = sqrt(i); } /* initialize the VLC tables */ for(i = 0; i < 4 ; i++) { for(j = 0; j < 4; j++) { huffman_vlc[i][j].table = vlc_tables[vlc_offsets[i * 4 + j]]; huffman_vlc[i][j].table_allocated = vlc_offsets[i * 4 + j + 1] - vlc_offsets[i * 4 + j]; init_vlc(&huffman_vlc[i][j], 9, imc_huffman_sizes[i], imc_huffman_lens[i][j], 1, 1, imc_huffman_bits[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC); } } q->one_div_log2 = 1/log(2); ff_fft_init(&q->fft, 7, 1); dsputil_init(&q->dsp, avctx); avctx->sample_fmt = SAMPLE_FMT_S16; return 0; }
static inline void fft_init(FFTContext **s, int nbits, int inverse) { #if AVFFT *s = av_fft_init(nbits, inverse); #else ff_fft_init(*s, nbits, inverse); #endif }
FFTContext *av_fft_init(int nbits, int inverse) { FFTContext *s = av_mallocz(sizeof(*s)); if (s && ff_fft_init(s, nbits, inverse)) av_freep(&s); return s; }
FFTContext *av_fft_init(int nbits, int inverse) { FFTContext *s = av_malloc(sizeof(*s)); if (s) ff_fft_init(s, nbits, inverse); return s; }
static int imc_decode_init(AVCodecContext * avctx) { int i, j; IMCContext *q = avctx->priv_data; double r1, r2; q->decoder_reset = 1; for(i = 0; i < BANDS; i++) q->old_floor[i] = 1.0; /* Build mdct window, a simple sine window normalized with sqrt(2) */ for(i = 0; i < COEFFS; i++) q->mdct_sine_window[i] = sin((i + 0.5) / 512.0 * M_PI) * sqrt(2.0); for(i = 0; i < COEFFS/2; i++){ q->post_cos[i] = cos(i / 256.0 * M_PI); q->post_sin[i] = sin(i / 256.0 * M_PI); r1 = sin((i * 4.0 + 1.0) / 1024.0 * M_PI); r2 = cos((i * 4.0 + 1.0) / 1024.0 * M_PI); if (i & 0x1) { q->pre_coef1[i] = (r1 + r2) * sqrt(2.0); q->pre_coef2[i] = -(r1 - r2) * sqrt(2.0); } else { q->pre_coef1[i] = -(r1 + r2) * sqrt(2.0); q->pre_coef2[i] = (r1 - r2) * sqrt(2.0); } q->last_fft_im[i] = 0; } /* Generate a square root table */ for(i = 0; i < 30; i++) { q->sqrt_tab[i] = sqrt(i); } /* initialize the VLC tables */ for(i = 0; i < 4 ; i++) { for(j = 0; j < 4; j++) { init_vlc (&q->huffman_vlc[i][j], 9, imc_huffman_sizes[i], imc_huffman_lens[i][j], 1, 1, imc_huffman_bits[i][j], 2, 2, 1); } } q->one_div_log2 = 1/log(2); ff_fft_init(&q->fft, 7, 1); dsputil_init(&q->dsp, avctx); return 0; }
FFTContext *av_fft_init(int nbits, int inverse) { FFTContext *s = (FFTContext*)malloc(sizeof(*s)); if (s && ff_fft_init(s, nbits, inverse)) { free(s); s = 0; } return s; }
int main (void) { #define PRECISION 16 #define FFT_SIZE 1024 #define ftofix32(x) ((fixed32)((x) * (float)(1 << PRECISION) + ((x) < 0 ? -0.5 : 0.5))) #define itofix32(x) ((x) << PRECISION) #define fixtoi32(x) ((x) >> PRECISION) int j; const long N = FFT_SIZE; double r[FFT_SIZE] = {0.0}, i[FFT_SIZE] = {0.0}; long n; double t; double amp, phase; clock_t start, end; double exec_time = 0; FFTContext s; FFTComplex z[FFT_SIZE]; memset(z, 0, 64*sizeof(FFTComplex)); /* Generate saw-tooth test data */ for (n = 0; n < FFT_SIZE; n++) { t = (2 * M_PI * n)/N; /*z[n].re = 1.1 + sin( t) + 0.5 * sin(2.0 * t) + (1.0/3.0) * sin(3.0 * t) + 0.25 * sin(4.0 * t) + 0.2 * sin(5.0 * t) + (1.0/6.0) * sin(6.0 * t) + (1.0/7.0) * sin(7.0 * t) ;*/ z[n].re = ftofix32(cos(2*M_PI*n/64)); //printf("z[%d] = %f\n", n, z[n].re); //getchar(); } ff_fft_init(&s, 10, 1); //start = clock(); //for(n = 0; n < 1000000; n++) ff_fft_permute_c(&s, z); ff_fft_calc_c(&s, z); //end = clock(); //exec_time = (((double)end-(double)start)/CLOCKS_PER_SEC); for(j = 0; j < FFT_SIZE; j++) { printf("%8.4f\n", sqrt(pow(fixtof32(z[j].re),2)+ pow(fixtof32(z[j].im), 2))); //getchar(); } printf("muls = %d, adds = %d\n", muls, adds); //printf(" Time elapsed = %f\n", exec_time); //ff_fft_end(&s); }
/** * init MDCT or IMDCT computation. */ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale) { int n, n4, i; double alpha, theta; int tstep; memset(s, 0, sizeof(*s)); n = 1 << nbits; s->mdct_bits = nbits; s->mdct_size = n; n4 = n >> 2; s->mdct_permutation = FF_MDCT_PERM_NONE; if (ff_fft_init(s, s->mdct_bits - 2, inverse) < 0) goto fail; s->tcos = av_malloc_array(n/2, sizeof(FFTSample)); if (!s->tcos) goto fail; switch (s->mdct_permutation) { case FF_MDCT_PERM_NONE: s->tsin = s->tcos + n4; tstep = 1; break; case FF_MDCT_PERM_INTERLEAVE: s->tsin = s->tcos + 1; tstep = 2; break; default: goto fail; } theta = 1.0 / 8.0 + (scale < 0 ? n4 : 0); scale = sqrt(fabs(scale)); for(i=0;i<n4;i++) { alpha = 2 * M_PI * (i + theta) / n; #if FFT_FIXED_32 s->tcos[i*tstep] = lrint(-cos(alpha) * 2147483648.0); s->tsin[i*tstep] = lrint(-sin(alpha) * 2147483648.0); #else s->tcos[i*tstep] = FIX15(-cos(alpha) * scale); s->tsin[i*tstep] = FIX15(-sin(alpha) * scale); #endif } return 0; fail: ff_mdct_end(s); return -1; }
av_cold int ff_dct_init(DCTContext *s, int nbits, int inverse) { int n = 1 << nbits; s->nbits = nbits; s->inverse = inverse; s->data = (struct FFTComplex *) av_malloc(sizeof(FFTComplex) * 2 * n); if (!s->data) return -1; if (ff_fft_init(&s->fft, nbits+1, inverse) < 0) return -1; return 0; }
int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; int it, i, c; int do_speed = 0; int do_mdct = 0; int do_inverse = 0; FFTContext s1, *s = &s1; MDCTContext m1, *m = &m1; int fft_nbits, fft_size; fft_nbits = 9; for(;;) { c = getopt(argc, argv, "hsimn:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 's': do_speed = 1; break; case 'i': do_inverse = 1; break; case 'm': do_mdct = 1; break; case 'n': fft_nbits = atoi(optarg); break; } } fft_size = 1 << fft_nbits; tab = av_malloc(fft_size * sizeof(FFTComplex)); tab1 = av_malloc(fft_size * sizeof(FFTComplex)); tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); tab2 = av_malloc(fft_size * sizeof(FFTSample)); if (do_mdct) { if (do_inverse) av_log(NULL, AV_LOG_INFO,"IMDCT"); else av_log(NULL, AV_LOG_INFO,"MDCT"); ff_mdct_init(m, fft_nbits, do_inverse); } else { if (do_inverse) av_log(NULL, AV_LOG_INFO,"IFFT"); else av_log(NULL, AV_LOG_INFO,"FFT"); ff_fft_init(s, fft_nbits, do_inverse); fft_ref_init(fft_nbits, do_inverse); } av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); /* generate random data */ for(i=0;i<fft_size;i++) { tab1[i].re = frandom(); tab1[i].im = frandom(); } /* checking result */ av_log(NULL, AV_LOG_INFO,"Checking...\n"); if (do_mdct) { if (do_inverse) { imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); ff_imdct_calc(m, tab2, (float *)tab1); check_diff((float *)tab_ref, tab2, fft_size); } else { mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); ff_mdct_calc(m, tab2, (float *)tab1); check_diff((float *)tab_ref, tab2, fft_size / 2); } } else { memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); ff_fft_permute(s, tab); ff_fft_calc(s, tab); fft_ref(tab_ref, tab1, fft_nbits); check_diff((float *)tab_ref, (float *)tab, fft_size * 2); } /* do a speed test */ if (do_speed) { int64_t time_start, duration; int nb_its; av_log(NULL, AV_LOG_INFO,"Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; for(;;) { time_start = gettime(); for(it=0;it<nb_its;it++) { if (do_mdct) { if (do_inverse) { ff_imdct_calc(m, (float *)tab, (float *)tab1); } else { ff_mdct_calc(m, (float *)tab, (float *)tab1); } } else { memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); ff_fft_calc(s, tab); } } duration = gettime() - time_start; if (duration >= 1000000) break; nb_its *= 2; } av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", (double)duration / nb_its, (double)duration / 1000000.0, nb_its); } if (do_mdct) { ff_mdct_end(m); } else { ff_fft_end(s); } return 0; }
int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; int it, i, c; int do_speed = 0; int err = 1; enum tf_transform transform = TRANSFORM_FFT; int do_inverse = 0; FFTContext s1, *s = &s1; FFTContext m1, *m = &m1; RDFTContext r1, *r = &r1; DCTContext d1, *d = &d1; int fft_nbits, fft_size, fft_size_2; double scale = 1.0; AVLFG prng; av_lfg_init(&prng, 1); fft_nbits = 9; for(;;) { c = getopt(argc, argv, "hsimrdn:f:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 's': do_speed = 1; break; case 'i': do_inverse = 1; break; case 'm': transform = TRANSFORM_MDCT; break; case 'r': transform = TRANSFORM_RDFT; break; case 'd': transform = TRANSFORM_DCT; break; case 'n': fft_nbits = atoi(optarg); break; case 'f': scale = atof(optarg); break; } } fft_size = 1 << fft_nbits; fft_size_2 = fft_size >> 1; tab = av_malloc(fft_size * sizeof(FFTComplex)); tab1 = av_malloc(fft_size * sizeof(FFTComplex)); tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); tab2 = av_malloc(fft_size * sizeof(FFTSample)); switch (transform) { case TRANSFORM_MDCT: av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale); if (do_inverse) av_log(NULL, AV_LOG_INFO,"IMDCT"); else av_log(NULL, AV_LOG_INFO,"MDCT"); ff_mdct_init(m, fft_nbits, do_inverse, scale); break; case TRANSFORM_FFT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"IFFT"); else av_log(NULL, AV_LOG_INFO,"FFT"); ff_fft_init(s, fft_nbits, do_inverse); fft_ref_init(fft_nbits, do_inverse); break; case TRANSFORM_RDFT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"IDFT_C2R"); else av_log(NULL, AV_LOG_INFO,"DFT_R2C"); ff_rdft_init(r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); fft_ref_init(fft_nbits, do_inverse); break; case TRANSFORM_DCT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"DCT_III"); else av_log(NULL, AV_LOG_INFO,"DCT_II"); ff_dct_init(d, fft_nbits, do_inverse ? DCT_III : DCT_II); break; } av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); /* generate random data */ for (i = 0; i < fft_size; i++) { tab1[i].re = frandom(&prng); tab1[i].im = frandom(&prng); } /* checking result */ av_log(NULL, AV_LOG_INFO,"Checking...\n"); switch (transform) { case TRANSFORM_MDCT: if (do_inverse) { imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); ff_imdct_calc(m, tab2, (float *)tab1); err = check_diff((float *)tab_ref, tab2, fft_size, scale); } else { mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); ff_mdct_calc(m, tab2, (float *)tab1); err = check_diff((float *)tab_ref, tab2, fft_size / 2, scale); } break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); ff_fft_permute(s, tab); ff_fft_calc(s, tab); fft_ref(tab_ref, tab1, fft_nbits); err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 1.0); break; case TRANSFORM_RDFT: if (do_inverse) { tab1[ 0].im = 0; tab1[fft_size_2].im = 0; for (i = 1; i < fft_size_2; i++) { tab1[fft_size_2+i].re = tab1[fft_size_2-i].re; tab1[fft_size_2+i].im = -tab1[fft_size_2-i].im; } memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); tab2[1] = tab1[fft_size_2].re; ff_rdft_calc(r, tab2); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab2[i]; tab[i].im = 0; } err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 0.5); } else { for (i = 0; i < fft_size; i++) { tab2[i] = tab1[i].re; tab1[i].im = 0; } ff_rdft_calc(r, tab2); fft_ref(tab_ref, tab1, fft_nbits); tab_ref[0].im = tab_ref[fft_size_2].re; err = check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); } break; case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); ff_dct_calc(d, tab); if (do_inverse) { idct_ref(tab_ref, tab1, fft_nbits); } else { dct_ref(tab_ref, tab1, fft_nbits); } err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); break; } /* do a speed test */ if (do_speed) { int64_t time_start, duration; int nb_its; av_log(NULL, AV_LOG_INFO,"Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; for(;;) { time_start = gettime(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: if (do_inverse) { ff_imdct_calc(m, (float *)tab, (float *)tab1); } else { ff_mdct_calc(m, (float *)tab, (float *)tab1); } break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); ff_fft_calc(s, tab); break; case TRANSFORM_RDFT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); ff_rdft_calc(r, tab2); break; case TRANSFORM_DCT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); ff_dct_calc(d, tab2); break; } } duration = gettime() - time_start; if (duration >= 1000000) break; nb_its *= 2; } av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", (double)duration / nb_its, (double)duration / 1000000.0, nb_its); } switch (transform) { case TRANSFORM_MDCT: ff_mdct_end(m); break; case TRANSFORM_FFT: ff_fft_end(s); break; case TRANSFORM_RDFT: ff_rdft_end(r); break; case TRANSFORM_DCT: ff_dct_end(d); break; } av_free(tab); av_free(tab1); av_free(tab2); av_free(tab_ref); av_free(exptab); return err; }
int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; enum tf_transform transform = TRANSFORM_FFT; FFTContext m, s; #if FFT_FLOAT RDFTContext r; DCTContext d; #if CONFIG_LIBFFTW3 FFTWContext fftw; FFTWComplex *tab_fftw, *tab_fftw_copy; #endif /* CONFIG_LIBFFTW3 */ #endif /* FFT_FLOAT */ int it, i, err = 1; int do_speed = 0, do_inverse = 0; int fft_nbits = 9, fft_size; double scale = 1.0; AVLFG prng; av_lfg_init(&prng, 1); for (;;) { int c = getopt(argc, argv, "hsitmrdn:f:c:"); if (c == -1) break; switch (c) { case 'h': help(); return 1; case 's': do_speed = 1; break; case 'i': do_inverse = 1; break; #if CONFIG_LIBFFTW3 case 't': transform = TRANSFORM_FFTW; break; #endif /* CONFIG_LIBFFTW3 */ case 'm': transform = TRANSFORM_MDCT; break; case 'r': transform = TRANSFORM_RDFT; break; case 'd': transform = TRANSFORM_DCT; break; case 'n': fft_nbits = atoi(optarg); break; case 'f': scale = atof(optarg); break; case 'c': { unsigned cpuflags = av_get_cpu_flags(); if (av_parse_cpu_caps(&cpuflags, optarg) < 0) return 1; av_force_cpu_flags(cpuflags); break; } } } fft_size = 1 << fft_nbits; tab = av_malloc_array(fft_size, sizeof(FFTComplex)); tab1 = av_malloc_array(fft_size, sizeof(FFTComplex)); tab_ref = av_malloc_array(fft_size, sizeof(FFTComplex)); tab2 = av_malloc_array(fft_size, sizeof(FFTSample)); #if CONFIG_LIBFFTW3 && FFT_FLOAT tab_fftw = av_malloc_array(fft_size, sizeof(*tab_fftw)); tab_fftw_copy = av_malloc_array(fft_size, sizeof(*tab_fftw_copy)); if (!(tab_fftw && tab_fftw_copy)) goto cleanup_fftw; #endif /* CONFIG_LIBFFTW3 */ if (!(tab && tab1 && tab_ref && tab2)) goto cleanup; switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale); if (do_inverse) av_log(NULL, AV_LOG_INFO, "IMDCT"); else av_log(NULL, AV_LOG_INFO, "MDCT"); ff_mdct_init(&m, fft_nbits, do_inverse, scale); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IFFT"); else av_log(NULL, AV_LOG_INFO, "FFT"); ff_fft_init(&s, fft_nbits, do_inverse); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IFFTW"); else av_log(NULL, AV_LOG_INFO, "FFTW"); ff_fftw_init(&fftw, fft_size, do_inverse); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IDFT_C2R"); else av_log(NULL, AV_LOG_INFO, "DFT_R2C"); ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "DCT_III"); else av_log(NULL, AV_LOG_INFO, "DCT_II"); ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); break; # endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ default: av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); goto cleanup; } av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size); /* generate random data */ for (i = 0; i < fft_size; i++) { tab1[i].re = frandom(&prng); tab1[i].im = frandom(&prng); #if CONFIG_LIBFFTW3 && FFT_FLOAT tab_fftw[i][0] = tab1[i].re; tab_fftw[i][1] = tab1[i].im; #endif /* CONFIG_LIBFFTW3 */ } #if CONFIG_LIBFFTW3 && FFT_FLOAT memcpy(tab_fftw_copy, tab_fftw, fft_size * sizeof(*tab_fftw)); #endif /* checking result */ av_log(NULL, AV_LOG_INFO, "Checking...\n"); switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: if (do_inverse) { imdct_ref(&tab_ref->re, &tab1->re, fft_nbits); m.imdct_calc(&m, tab2, &tab1->re); err = check_diff(&tab_ref->re, tab2, fft_size, scale); } else { mdct_ref(&tab_ref->re, &tab1->re, fft_nbits); m.mdct_calc(&m, tab2, &tab1->re); err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale); } break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s.fft_permute(&s, tab); s.fft_calc(&s, tab); fft_ref(tab_ref, tab1, fft_nbits); err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: fftw.fft_calc(&fftw, tab_fftw); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab_fftw[i][0]; tab[i].im = tab_fftw[i][1]; } err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT #if CONFIG_RDFT case TRANSFORM_RDFT: { int fft_size_2 = fft_size >> 1; if (do_inverse) { tab1[0].im = 0; tab1[fft_size_2].im = 0; for (i = 1; i < fft_size_2; i++) { tab1[fft_size_2 + i].re = tab1[fft_size_2 - i].re; tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im; } memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); tab2[1] = tab1[fft_size_2].re; r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab2[i]; tab[i].im = 0; } err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5); } else { for (i = 0; i < fft_size; i++) { tab2[i] = tab1[i].re; tab1[i].im = 0; } r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); tab_ref[0].im = tab_ref[fft_size_2].re; err = check_diff(&tab_ref->re, tab2, fft_size, 1.0); } break; } #endif /* CONFIG_RDFT */ #if CONFIG_DCT case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); d.dct_calc(&d, &tab->re); if (do_inverse) idct_ref(&tab_ref->re, &tab1->re, fft_nbits); else dct_ref(&tab_ref->re, &tab1->re, fft_nbits); err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0); break; #endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ } /* do a speed test */ if (do_speed) { int64_t time_start, duration; int nb_its; av_log(NULL, AV_LOG_INFO, "Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; for (;;) { time_start = av_gettime_relative(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: if (do_inverse) m.imdct_calc(&m, &tab->re, &tab1->re); else m.mdct_calc(&m, &tab->re, &tab1->re); break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s.fft_permute(&s, tab); s.fft_calc(&s, tab); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: memcpy(tab_fftw, tab_fftw_copy, fft_size * sizeof(*tab_fftw)); fftw.fft_calc(&fftw, tab_fftw); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT case TRANSFORM_RDFT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); r.rdft_calc(&r, tab2); break; case TRANSFORM_DCT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); d.dct_calc(&d, tab2); break; #endif /* FFT_FLOAT */ } } duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; } av_log(NULL, AV_LOG_INFO, "time: %0.2f us/transform [total time=%0.2f s its=%d]\n", (double) duration / nb_its, (double) duration / 1000000.0, nb_its); } switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: ff_mdct_end(&m); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: ff_fft_end(&s); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: ff_fftw_deinit(&fftw); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: ff_rdft_end(&r); break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: ff_dct_end(&d); break; # endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ } #if CONFIG_LIBFFTW3 && FFT_FLOAT cleanup_fftw: av_freep(&tab_fftw); #endif /* CONFIG_LIBFFTW3 */ cleanup: av_freep(&tab); av_freep(&tab1); av_freep(&tab2); av_freep(&tab_ref); av_freep(&exptab); if (err) printf("Error: %d.\n", err); return !!err; }
/** * init MDCT or IMDCT computation. */ av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale) { int n, n4, i; double alpha, theta; int tstep; memset(s, 0, sizeof(*s)); n = 1 << nbits; s->mdct_bits = nbits; s->mdct_size = n; n4 = n >> 2; s->mdct_permutation = FF_MDCT_PERM_NONE; if (ff_fft_init(s, s->mdct_bits - 2, inverse) < 0) goto fail; s->imdct_calc = ff_imdct_calc_c; s->imdct_half = ff_imdct_half_c; s->mdct_calc = ff_mdct_calc_c; #if FFT_FLOAT if (ARCH_AARCH64) ff_mdct_init_aarch64(s); if (ARCH_ARM) ff_mdct_init_arm(s); if (ARCH_PPC) ff_mdct_init_ppc(s); if (ARCH_X86) ff_mdct_init_x86(s); s->mdct_calcw = s->mdct_calc; #else s->mdct_calcw = ff_mdct_calcw_c; if (ARCH_ARM) ff_mdct_fixed_init_arm(s); #endif s->tcos = av_malloc(n/2 * sizeof(FFTSample)); if (!s->tcos) goto fail; switch (s->mdct_permutation) { case FF_MDCT_PERM_NONE: s->tsin = s->tcos + n4; tstep = 1; break; case FF_MDCT_PERM_INTERLEAVE: s->tsin = s->tcos + 1; tstep = 2; break; default: goto fail; } theta = 1.0 / 8.0 + (scale < 0 ? n4 : 0); scale = sqrt(fabs(scale)); for(i=0;i<n4;i++) { alpha = 2 * M_PI * (i + theta) / n; s->tcos[i*tstep] = FIX15(-cos(alpha) * scale); s->tsin[i*tstep] = FIX15(-sin(alpha) * scale); } return 0; fail: ff_mdct_end(s); return -1; }
av_cold int ff_mdct15_init(MDCT15Context **ps, int inverse, int N, double scale) { MDCT15Context *s; double alpha, theta; int len2 = 15 * (1 << N); int len = 2 * len2; int i; /* Tested and verified to work on everything in between */ if ((N < 2) || (N > 13)) return AVERROR(EINVAL); s = av_mallocz(sizeof(*s)); if (!s) return AVERROR(ENOMEM); s->fft_n = N - 1; s->len4 = len2 / 2; s->len2 = len2; s->inverse = inverse; s->fft15 = fft15_c; s->mdct = mdct15; s->imdct_half = imdct15_half; if (ff_fft_init(&s->ptwo_fft, N - 1, s->inverse) < 0) goto fail; if (init_pfa_reindex_tabs(s)) goto fail; s->tmp = av_malloc_array(len, 2 * sizeof(*s->tmp)); if (!s->tmp) goto fail; s->twiddle_exptab = av_malloc_array(s->len4, sizeof(*s->twiddle_exptab)); if (!s->twiddle_exptab) goto fail; theta = 0.125f + (scale < 0 ? s->len4 : 0); scale = sqrt(fabs(scale)); for (i = 0; i < s->len4; i++) { alpha = 2 * M_PI * (i + theta) / len; s->twiddle_exptab[i].re = cosf(alpha) * scale; s->twiddle_exptab[i].im = sinf(alpha) * scale; } /* 15-point FFT exptab */ for (i = 0; i < 19; i++) { if (i < 15) { double theta = (2.0f * M_PI * i) / 15.0f; if (!s->inverse) theta *= -1; s->exptab[i].re = cosf(theta); s->exptab[i].im = sinf(theta); } else { /* Wrap around to simplify fft15 */ s->exptab[i] = s->exptab[i - 15]; } } /* 5-point FFT exptab */ s->exptab[19].re = cosf(2.0f * M_PI / 5.0f); s->exptab[19].im = sinf(2.0f * M_PI / 5.0f); s->exptab[20].re = cosf(1.0f * M_PI / 5.0f); s->exptab[20].im = sinf(1.0f * M_PI / 5.0f); /* Invert the phase for an inverse transform, do nothing for a forward transform */ if (s->inverse) { s->exptab[19].im *= -1; s->exptab[20].im *= -1; } if (ARCH_X86) ff_mdct15_init_x86(s); *ps = s; return 0; fail: ff_mdct15_uninit(&s); return AVERROR(ENOMEM); }