-
-
Save AmesianX/5d4beee4175af7abfebb8c8cca5b7fb4 to your computer and use it in GitHub Desktop.
My FFT implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <math.h> | |
| #define FOREVER while(1){ (void)0; } | |
| #define PI 3.141592654f | |
| //this marco only usable by FFT_Compute() function assuming we already have var realComp, imagineComp defined | |
| //four inputs: real is real component value, imagine is imaginary component value | |
| //kn is muplication of time domain sample location n and frequency domain sample location k | |
| // sum is total number of samples in current stage (stageNumber*2) | |
| #define EXP_NEG_TWOPI_JAY_N_K_OVER_N(real, imagine, kn,sum) { realComp = real*cos(-2.0f*PI*kn/(float)sum)-imagine*sin(-2.0f*PI*kn/(float)sum); \ | |
| imagineComp = imagine*cos(-2.0f*PI*kn/(float)sum)+real*sin(-2.0f*PI*kn/(float)sum);} | |
| typedef unsigned int UINT; | |
| //given a M (M<32) bits number(0 - 2^M) revert bits | |
| void reverseInPlace(UINT * input, UINT m) | |
| { | |
| UINT out = 0, scrape = 0, k; | |
| for (k=m; k>=1; k--) { | |
| //right shift till see the leftmost bit | |
| scrape =(*input)>>(k-1) & 0x00000001; | |
| //out is assembled bit by bit from leftmost to rightmost with respect to original number | |
| out += ((scrape == 0) ? 0 : (1<<(m-k))); | |
| } | |
| *input = out; | |
| } | |
| //FFT_Compute accepts two float array of length 2^m each represent Complex Number array in time domain, real component in realArray | |
| //imaginary component in imagineArray, Output Arrays in frequency domain are stored in place repectively | |
| //computational complexity O(nlogn), n is the length of arrays | |
| void FFT_Compute(float *realArray, float *imagineArray, int m) | |
| { | |
| //two temp variables used in computation | |
| float realComp, imagineComp; | |
| //length of our array is 2^m | |
| UINT len = 0x00000001 << (m); | |
| UINT k=0, j=0, temp, magicMask; | |
| //scrambleIndex array only used in stage 0 | |
| UINT *scrambleIndex; | |
| //temp variable used for storing intermediate results | |
| float *realTemp, *imgTemp; | |
| if (m >= 32) { | |
| printf("We don't support bit length greater than 31"); | |
| return; | |
| } | |
| scrambleIndex = (UINT *)malloc(sizeof(UINT) * len); | |
| realTemp = (float *)malloc(sizeof(float) * len); | |
| imgTemp = (float *)malloc(sizeof(float) * len); | |
| for (k=0; k<len; k++) { | |
| temp = k; | |
| reverseInPlace(&temp, m); | |
| scrambleIndex[k] = temp; | |
| } | |
| //compute output for each stage, intermediate result stored in place | |
| //j is the stage number, k is the index to sample location | |
| //stage zero is a bit special cannot be written in general loop | |
| //the following loop just for stage 0 | |
| for (k=0; k<len; k++) { | |
| realTemp[k] = realArray[scrambleIndex[k]]; | |
| imgTemp[k] = imagineArray[scrambleIndex[k]]; | |
| //here we only have zero | |
| /* dont need following since Weight is Identity Matrix | |
| EXP_NEG_TWOPI_JAY_N_K_OVER_N(realTemp[k], imgTemp[k], 0, len) | |
| if ((k&0x00000001) != 0) //odd number need to multiply weight | |
| { | |
| realTemp[k] = realComp; | |
| imgTemp[k] = imagineComp; | |
| } */ | |
| } //copy to output array finish stage 0 | |
| for (k=0; k<len; k++) { | |
| realArray[k] = realTemp[k]; | |
| imagineArray[k] = imgTemp[k]; | |
| } | |
| //now start from stage 1 til finish | |
| for (j=1; j<=m; j++) { | |
| //first sum then apply weight | |
| //magicMask to get butterfly location | |
| magicMask = (0x00000001<<(j-1)); | |
| //compute each sample location in freq domain | |
| for (k=0; k<len; k++) { | |
| //adding counter part of sum instead of comparison (<) may also use & (eg. k&magicMask == 0? 1: -1) | |
| realTemp[k] = ( k < (k^magicMask) ? 1.f :-1.f) * realArray[k] + realArray[k^magicMask]; | |
| imgTemp[k] = ( k < (k^magicMask) ? 1.f :-1.f) * imagineArray[k] + imagineArray[k^magicMask]; | |
| //applying weight only odd subsequence needs weight | |
| //donot apply weight in last stage | |
| if (j!=m && (k > (k^(magicMask<<1)))) { | |
| //apply weight -- by left shift then right shift, we can zero out j leftmost bits | |
| EXP_NEG_TWOPI_JAY_N_K_OVER_N(realTemp[k], imgTemp[k], ((k<<(32-j))>>(32-j)), (magicMask<<2)); | |
| realTemp[k] = realComp; | |
| imgTemp[k] = imagineComp; | |
| } | |
| } | |
| //copy result over finish this stage | |
| for (k=0; k<len; k++) { | |
| realArray[k] = realTemp[k]; | |
| imagineArray[k] = imgTemp[k]; | |
| } | |
| } | |
| free(scrambleIndex); | |
| free(realTemp); | |
| free(imgTemp); | |
| } | |
| /* | |
| Direct fourier transform for comparison purpose | |
| used for verify our Implementation is correct | |
| */ | |
| int DFT(int dir,int m,float *x1,float *y1) | |
| { | |
| long i,k; | |
| float arg; | |
| float cosarg,sinarg; | |
| float *x2,*y2; | |
| x2 = (float *)malloc(m*sizeof(float)); | |
| y2 = (float *)malloc(m*sizeof(float)); | |
| if (x2 == NULL || y2 == NULL) | |
| return(-1); | |
| for (i=0;i<m;i++) { | |
| x2[i] = 0; | |
| y2[i] = 0; | |
| arg = - dir * 2.0 * 3.141592654 * (float)i / (float)m; | |
| for (k=0;k<m;k++) { | |
| cosarg = cos(k * arg); | |
| sinarg = sin(k * arg); | |
| x2[i] += (x1[k] * cosarg - y1[k] * sinarg); | |
| y2[i] += (x1[k] * sinarg + y1[k] * cosarg); | |
| } | |
| } | |
| /* Copy the data back */ | |
| dir = 1; | |
| if (dir == 1) { | |
| for (i=0;i<m;i++) { | |
| x1[i] = x2[i]; | |
| y1[i] = y2[i]; | |
| } | |
| } else { | |
| for (i=0;i<m;i++) { | |
| x1[i] = x2[i]; | |
| y1[i] = y2[i]; | |
| } | |
| } | |
| free(x2); | |
| free(y2); | |
| return(0); | |
| } | |
| void main() | |
| { | |
| float testReal[32], testImagine[32]; | |
| int bitCount = 5, i, length = 32; | |
| for (i=0; i<length; i++) { | |
| testReal[i] = sin(2.0f*PI*(float)i/(float)length); | |
| testImagine[i] = 0; | |
| } | |
| printf("usage: %d(input number) %d(total bit count)\n"); | |
| FFT_Compute(testReal, testImagine, bitCount); | |
| //DFT(1, length, testReal, testImagine); | |
| for (i=0; i<length; i++) { | |
| printf("Complex Number for sample %d: Real = %f Imaginary = %f\n", i, testReal[i], testImagine[i]); | |
| } | |
| FOREVER | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment