Mercurial > hg > qm-dsp
diff ext/kissfft/test/twotonetest.c @ 409:1f1999b0f577
Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Tue, 21 Jul 2015 07:34:15 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/kissfft/test/twotonetest.c Tue Jul 21 07:34:15 2015 +0100 @@ -0,0 +1,94 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "kiss_fft.h" +#include "kiss_fftr.h" +#include <limits.h> + + +static +double two_tone_test( int nfft, int bin1,int bin2) +{ + kiss_fftr_cfg cfg = NULL; + kiss_fft_cpx *kout = NULL; + kiss_fft_scalar *tbuf = NULL; + + int i; + double f1 = bin1*2*M_PI/nfft; + double f2 = bin2*2*M_PI/nfft; + double sigpow=0; + double noisepow=0; +#if FIXED_POINT==32 + long maxrange = LONG_MAX; +#else + long maxrange = SHRT_MAX;/* works fine for float too*/ +#endif + + cfg = kiss_fftr_alloc(nfft , 0, NULL, NULL); + tbuf = KISS_FFT_MALLOC(nfft * sizeof(kiss_fft_scalar)); + kout = KISS_FFT_MALLOC(nfft * sizeof(kiss_fft_cpx)); + + /* generate a signal with two tones*/ + for (i = 0; i < nfft; i++) { +#ifdef USE_SIMD + tbuf[i] = _mm_set1_ps( (maxrange>>1)*cos(f1*i) + + (maxrange>>1)*cos(f2*i) ); +#else + tbuf[i] = (maxrange>>1)*cos(f1*i) + + (maxrange>>1)*cos(f2*i); +#endif + } + + kiss_fftr(cfg, tbuf, kout); + + for (i=0;i < (nfft/2+1);++i) { +#ifdef USE_SIMD + double tmpr = (double)*(float*)&kout[i].r / (double)maxrange; + double tmpi = (double)*(float*)&kout[i].i / (double)maxrange; +#else + double tmpr = (double)kout[i].r / (double)maxrange; + double tmpi = (double)kout[i].i / (double)maxrange; +#endif + double mag2 = tmpr*tmpr + tmpi*tmpi; + if (i!=0 && i!= nfft/2) + mag2 *= 2; /* all bins except DC and Nyquist have symmetric counterparts implied*/ + + /* if there is power in one of the expected bins, it is signal, otherwise noise*/ + if ( i!=bin1 && i != bin2 ) + noisepow += mag2; + else + sigpow += mag2; + } + kiss_fft_cleanup(); + /*printf("TEST %d,%d,%d noise @ %fdB\n",nfft,bin1,bin2,10*log10(noisepow/sigpow +1e-30) );*/ + return 10*log10(sigpow/(noisepow+1e-50) ); +} + +int main(int argc,char ** argv) +{ + int nfft = 4*2*2*3*5; + if (argc>1) nfft = atoi(argv[1]); + + int i,j; + double minsnr = 500; + double maxsnr = -500; + double snr; + for (i=0;i<nfft/2;i+= (nfft>>4)+1) { + for (j=i;j<nfft/2;j+=(nfft>>4)+7) { + snr = two_tone_test(nfft,i,j); + if (snr<minsnr) { + minsnr=snr; + } + if (snr>maxsnr) { + maxsnr=snr; + } + } + } + snr = two_tone_test(nfft,nfft/2,nfft/2); + if (snr<minsnr) minsnr=snr; + if (snr>maxsnr) maxsnr=snr; + + printf("TwoToneTest: snr ranges from %ddB to %ddB\n",(int)minsnr,(int)maxsnr); + printf("sizeof(kiss_fft_scalar) = %d\n",(int)sizeof(kiss_fft_scalar) ); + return 0; +}