iOS Accelerate low-pass FFT filter mirroring result -


i trying port existing fft based low-pass filter ios using accelerate vdsp framework.

it seems fft works expected first 1/4 of sample. after results seem wrong, , more odd mirrored (with last half of signal mirroring of first half).

you can see results test application below. first plotted original sampled data, example of expected filtered results (filtering out signal higher 15hz), results of current fft code (note desired results , example fft result @ different scale original data):

fft results

the actual code low-pass filter follows:

double *lowpassfiltervector(double *accell, uint32_t samplecount, double lowpassfreq, double samplerate ) {     double stride = 1;      int ln = log2f(samplecount);     int n = 1 << ln;      // fft of whole data set, pad out array next highest power of 2.     int fullpadn = n * 2;     double *padaccell = malloc(sizeof(double) * fullpadn);     memset(padaccell, 0, sizeof(double) * fullpadn);     memcpy(padaccell, accell, sizeof(double) * samplecount);      ln = log2f(fullpadn);     n = 1 << ln;      int nover2 = n/2;      dspdoublesplitcomplex a;     a.realp = (double *)malloc(sizeof(double) * nover2);     a.imagp = (double *)malloc(sizeof(double) * nover2);      // can reused, including here simplicity.     fftsetupd setupreal = vdsp_create_fftsetupd(ln, fft_radix2);      vdsp_ctozd((dspdoublecomplex*)padaccell,2,&a,1,nover2);      // use fft frequency counts     vdsp_fft_zripd(setupreal, &a, stride, ln, fft_forward);       const double factor = 0.5f;     vdsp_vsmuld(a.realp, 1, &factor, a.realp, 1, nover2);     vdsp_vsmuld(a.imagp, 1, &factor, a.imagp, 1, nover2);     a.realp[nover2] = a.imagp[0];     a.imagp[0] = 0.0f;     a.imagp[nover2] = 0.0f;      // set frequencies above target 0.      // tells bin frequencies on minimum desired correspond     nsinteger binlocation = (lowpassfreq * n) / samplerate;      // add 2 because bin 0 holds special fft meta data, bins start @ "1" - , want filter out on target frequency     ( nsinteger = binlocation+2; < nover2; i++ )     {         a.realp[i] = 0;     }      // clear out imaginary parts     bzero(a.imagp, (nover2) * sizeof(double));     //a.imagp[0] = a.realp[nover2];       // shift of values     vdsp_fft_zripd(setupreal, &a, stride, ln, fft_inverse);      double *filteredaccell = (double *)malloc(sizeof(double) * fullpadn);      // converts complex vector 2d array     vdsp_ztocd(&a, stride, (dspdoublecomplex*)filteredaccell, 2, nover2);      //  have scale results account apple's fft library algorithm, see:     // http://developer.apple.com/library/ios/#documentation/performance/conceptual/vdsp_programming_guide/usingfouriertransforms/usingfouriertransforms.html#//apple_ref/doc/uid/tp40005147-ch202-15952     double scale = (float)1.0f / fullpadn;//(2.0f * (float)n);     vdsp_vsmuld(filteredaccell, 1, &scale, filteredaccell, 1, fullpadn);      // tracks results of conversion     printf("\ninput & output:\n");     (int k = 0; k < samplecount; k++)     {         printf("%3d\t%6.2f\t%6.2f\t%6.2f\n", k, accell[k], padaccell[k], filteredaccell[k]);     }       // acceleration data replaced in-place.     return filteredaccell; } 

in original code library handling non power-of-two sizes of input data; in accelerate code padding out input nearest power of two. in case of sample test below original sample data 1000 samples it's padded 1024. don't think affect results include sake of possible differences.

if want experiment solution, can download sample project generates graphs here (in ffttest folder):

fft example project code

thanks insight, i've not worked fft's before feel missing critical.

if want strictly real (not complex) result, data before ifft must conjugate symmetric. if don't want result mirror symmetric, don't 0 imaginary component before ifft. merely zeroing bins before ifft creates filter huge amount of ripple in passband.

the accelerate framework supports more fft lengths powers of 2.


Comments

Popular posts from this blog

c# - Is it possible to remove an existing registration from Autofac container builder? -

c++ - Warning : overflow in implicit constant conversion -