ref: 039a67b371bc56d66bdb4e066209f7bfeda51d81
dir: /libcelt/tests/real-fft-test.c/
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "kiss_fftr.h" #include "_kiss_fft_guts.h" #include <stdio.h> #include <string.h> #define CELT_C #include "../libcelt/stack_alloc.h" #include "../libcelt/kiss_fft.c" #include "../libcelt/kiss_fftr.c" #ifdef FIXED_DEBUG long long celt_mips=0; #endif int ret=0; static kiss_fft_scalar rand_scalar(void) { return (rand()%32767)-16384; } static double snr_compare( kiss_fft_cpx * vec1,kiss_fft_scalar * vec2, int n) { int k; double sigpow=1e-10, noisepow=1e-10, err,snr; vec1[0].i = vec1[n].r; for (k=0;k<n;++k) { sigpow += (double)vec1[k].r * (double)vec1[k].r + (double)vec1[k].i * (double)vec1[k].i; err = (double)vec1[k].r - (double)vec2[2*k]; /*printf ("%f %f\n", (double)vec1[k].r, (double)vec2[2*k]);*/ noisepow += err * err; err = (double)vec1[k].i - (double)vec2[2*k+1]; /*printf ("%f %f\n", (double)vec1[k].i, (double)vec2[2*k+1]);*/ noisepow += err * err; } snr = 10*log10( sigpow / noisepow ); if (snr<60) { printf( "** poor snr: %f **\n", snr); ret = 1; } return snr; } static double snr_compare_scal( kiss_fft_scalar * vec1,kiss_fft_scalar * vec2, int n) { int k; double sigpow=1e-10, noisepow=1e-10, err,snr; for (k=0;k<n;++k) { sigpow += (double)vec1[k] * (double)vec1[k]; err = (double)vec1[k] - (double)vec2[k]; noisepow += err * err; } snr = 10*log10( sigpow / noisepow ); if (snr<60) { printf( "\npoor snr: %f\n", snr); ret = 1; } return snr; } #ifdef RADIX_TWO_ONLY #define NFFT 1024 #else #define NFFT 8*3*5 #endif #ifndef NUMFFTS #define NUMFFTS 10000 #endif int main(void) { int i; kiss_fft_cpx cin[NFFT]; kiss_fft_cpx cout[NFFT]; kiss_fft_scalar fin[NFFT]; kiss_fft_scalar sout[NFFT]; kiss_fft_cfg kiss_fft_state; kiss_fftr_cfg kiss_fftr_state; kiss_fft_scalar rin[NFFT+2]; kiss_fft_scalar rout[NFFT+2]; kiss_fft_scalar zero; ALLOC_STACK; memset(&zero,0,sizeof(zero) ); // ugly way of setting short,int,float,double, or __m128 to zero for (i=0;i<NFFT;++i) { rin[i] = rand_scalar(); #if defined(FIXED_POINT) && defined(DOUBLE_PRECISION) rin[i] *= 32768; #endif cin[i].r = rin[i]; cin[i].i = zero; } kiss_fft_state = opus_fft_alloc(NFFT,0,0); kiss_fftr_state = kiss_fftr_alloc(NFFT,0,0); opus_fft(kiss_fft_state,cin,cout); kiss_fftr(kiss_fftr_state,rin,sout); printf( "nfft=%d, inverse=%d, snr=%g\n", NFFT,0, snr_compare(cout,sout,(NFFT/2)) ); memset(cin,0,sizeof(cin)); cin[0].r = rand_scalar(); cin[NFFT/2].r = rand_scalar(); for (i=1;i< NFFT/2;++i) { //cin[i].r = (kiss_fft_scalar)(rand()-RAND_MAX/2); cin[i].r = rand_scalar(); cin[i].i = rand_scalar(); } // conjugate symmetry of real signal for (i=1;i< NFFT/2;++i) { cin[NFFT-i].r = cin[i].r; cin[NFFT-i].i = - cin[i].i; } #ifdef FIXED_POINT #ifdef DOUBLE_PRECISION for (i=0;i< NFFT;++i) { cin[i].r *= 32768; cin[i].i *= 32768; } #endif for (i=0;i< NFFT;++i) { cin[i].r /= NFFT; cin[i].i /= NFFT; } #endif fin[0] = cin[0].r; fin[1] = cin[NFFT/2].r; for (i=1;i< NFFT/2;++i) { fin[2*i] = cin[i].r; fin[2*i+1] = cin[i].i; } opus_ifft(kiss_fft_state,cin,cout); kiss_fftri(kiss_fftr_state,fin,rout); /* printf(" results from inverse opus_fft : (%f,%f), (%f,%f), (%f,%f), (%f,%f), (%f,%f) ...\n " , (float)cout[0].r , (float)cout[0].i , (float)cout[1].r , (float)cout[1].i , (float)cout[2].r , (float)cout[2].i , (float)cout[3].r , (float)cout[3].i , (float)cout[4].r , (float)cout[4].i ); printf(" results from inverse kiss_fftr: %f,%f,%f,%f,%f ... \n" ,(float)rout[0] ,(float)rout[1] ,(float)rout[2] ,(float)rout[3] ,(float)rout[4]); */ for (i=0;i<NFFT;++i) { sout[i] = cout[i].r; } printf( "nfft=%d, inverse=%d, snr=%g\n", NFFT,1, snr_compare_scal(rout,sout,NFFT) ); free(kiss_fft_state); free(kiss_fftr_state); return ret; }