A Graphic Equaliser using 2 Analog inputs and an Fast Fourier Transform

Dependencies:   mbed

Committer:
User_4574
Date:
Thu Mar 18 15:15:33 2010 +0000
Revision:
0:b771a5301e43

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
User_4574 0:b771a5301e43 1 /*
User_4574 0:b771a5301e43 2 * This is not my code and I do not take credit for it.
User_4574 0:b771a5301e43 3 * http://www.mit.edu/~emin/source_code/fft/index.html
User_4574 0:b771a5301e43 4 */
User_4574 0:b771a5301e43 5
User_4574 0:b771a5301e43 6 #define SIN_2PI_16 0.38268343236508978
User_4574 0:b771a5301e43 7 #define SIN_4PI_16 0.707106781186547460
User_4574 0:b771a5301e43 8 #define SIN_6PI_16 0.923879532511286740
User_4574 0:b771a5301e43 9 #define C_P_S_2PI_16 1.30656296487637660
User_4574 0:b771a5301e43 10 #define C_M_S_2PI_16 0.54119610014619690
User_4574 0:b771a5301e43 11 #define C_P_S_6PI_16 1.3065629648763766
User_4574 0:b771a5301e43 12 #define C_M_S_6PI_16 -0.54119610014619690
User_4574 0:b771a5301e43 13
User_4574 0:b771a5301e43 14 /* INPUT: float input[16], float output[16] */
User_4574 0:b771a5301e43 15 /* OUTPUT: none */
User_4574 0:b771a5301e43 16 /* EFFECTS: Places the 16 point fft of input in output in a strange */
User_4574 0:b771a5301e43 17 /* order using 10 real multiplies and 79 real adds. */
User_4574 0:b771a5301e43 18 /* Re{F[0]}= out0 */
User_4574 0:b771a5301e43 19 /* Im{F[0]}= 0 */
User_4574 0:b771a5301e43 20 /* Re{F[1]}= out8 */
User_4574 0:b771a5301e43 21 /* Im{F[1]}= out12 */
User_4574 0:b771a5301e43 22 /* Re{F[2]}= out4 */
User_4574 0:b771a5301e43 23 /* Im{F[2]}= -out6 */
User_4574 0:b771a5301e43 24 /* Re{F[3]}= out11 */
User_4574 0:b771a5301e43 25 /* Im{F[3]}= -out15 */
User_4574 0:b771a5301e43 26 /* Re{F[4]}= out2 */
User_4574 0:b771a5301e43 27 /* Im{F[4]}= -out3 */
User_4574 0:b771a5301e43 28 /* Re{F[5]}= out10 */
User_4574 0:b771a5301e43 29 /* Im{F[5]}= out14 */
User_4574 0:b771a5301e43 30 /* Re{F[6]}= out5 */
User_4574 0:b771a5301e43 31 /* Im{F[6]}= -out7 */
User_4574 0:b771a5301e43 32 /* Re{F[7]}= out9 */
User_4574 0:b771a5301e43 33 /* Im{F[7]}= -out13 */
User_4574 0:b771a5301e43 34 /* Re{F[8]}= out1 */
User_4574 0:b771a5301e43 35 /* Im{F[8]}=0 */
User_4574 0:b771a5301e43 36 /* F[9] through F[15] can be found by using the formula */
User_4574 0:b771a5301e43 37 /* Re{F[n]}=Re{F[(16-n)mod16]} and Im{F[n]}= -Im{F[(16-n)mod16]} */
User_4574 0:b771a5301e43 38
User_4574 0:b771a5301e43 39 /* Note using temporary variables to store intermediate computations */
User_4574 0:b771a5301e43 40 /* in the butterflies might speed things up. When the current version */
User_4574 0:b771a5301e43 41 /* needs to compute a=a+b, and b=a-b, I do a=a+b followed by b=a-b-b. */
User_4574 0:b771a5301e43 42 /* So practically everything is done in place, but the number of adds */
User_4574 0:b771a5301e43 43 /* can be reduced by doinc c=a+b followed by b=a-b. */
User_4574 0:b771a5301e43 44
User_4574 0:b771a5301e43 45 /* The algorithm behind this program is to find F[2k] and F[4k+1] */
User_4574 0:b771a5301e43 46 /* seperately. To find F[2k] we take the 8 point Real FFT of x[n]+x[n+8] */
User_4574 0:b771a5301e43 47 /* for n from 0 to 7. To find F[4k+1] we take the 4 point Complex FFT of */
User_4574 0:b771a5301e43 48 /* exp(-2*pi*j*n/16)*{x[n] - x[n+8] + j(x[n+12]-x[n+4])} for n from 0 to 3.*/
User_4574 0:b771a5301e43 49
User_4574 0:b771a5301e43 50 void fft(float input[16],float output[16] ) {
User_4574 0:b771a5301e43 51 float temp, out0, out1, out2, out3, out4, out5, out6, out7, out8;
User_4574 0:b771a5301e43 52 float out9,out10,out11,out12,out13,out14,out15;
User_4574 0:b771a5301e43 53
User_4574 0:b771a5301e43 54 out0=input[0]+input[8]; /* output[0 through 7] is the data that we */
User_4574 0:b771a5301e43 55 out1=input[1]+input[9]; /* take the 8 point real FFT of. */
User_4574 0:b771a5301e43 56 out2=input[2]+input[10];
User_4574 0:b771a5301e43 57 out3=input[3]+input[11];
User_4574 0:b771a5301e43 58 out4=input[4]+input[12];
User_4574 0:b771a5301e43 59 out5=input[5]+input[13];
User_4574 0:b771a5301e43 60 out6=input[6]+input[14];
User_4574 0:b771a5301e43 61 out7=input[7]+input[15];
User_4574 0:b771a5301e43 62
User_4574 0:b771a5301e43 63
User_4574 0:b771a5301e43 64
User_4574 0:b771a5301e43 65 out8=input[0]-input[8]; /* inputs 8,9,10,11 are */
User_4574 0:b771a5301e43 66 out9=input[1]-input[9]; /* the Real part of the */
User_4574 0:b771a5301e43 67 out10=input[2]-input[10]; /* 4 point Complex FFT inputs.*/
User_4574 0:b771a5301e43 68 out11=input[3]-input[11];
User_4574 0:b771a5301e43 69 out12=input[12]-input[4]; /* outputs 12,13,14,15 are */
User_4574 0:b771a5301e43 70 out13=input[13]-input[5]; /* the Imaginary pars of */
User_4574 0:b771a5301e43 71 out14=input[14]-input[6]; /* the 4 point Complex FFT inputs.*/
User_4574 0:b771a5301e43 72 out15=input[15]-input[7];
User_4574 0:b771a5301e43 73
User_4574 0:b771a5301e43 74 /*First we do the "twiddle factor" multiplies for the 4 point CFFT */
User_4574 0:b771a5301e43 75 /*Note that we use the following handy trick for doing a complex */
User_4574 0:b771a5301e43 76 /*multiply: (e+jf)=(a+jb)*(c+jd) */
User_4574 0:b771a5301e43 77 /* e=(a-b)*d + a*(c-d) and f=(a-b)*d + b*(c+d) */
User_4574 0:b771a5301e43 78
User_4574 0:b771a5301e43 79 /* C_M_S_2PI/16=cos(2pi/16)-sin(2pi/16) when replaced by macroexpansion */
User_4574 0:b771a5301e43 80 /* C_P_S_2PI/16=cos(2pi/16)+sin(2pi/16) when replaced by macroexpansion */
User_4574 0:b771a5301e43 81 /* (SIN_2PI_16)=sin(2pi/16) when replaced by macroexpansion */
User_4574 0:b771a5301e43 82 temp=(out13-out9)*(SIN_2PI_16);
User_4574 0:b771a5301e43 83 out9=out9*(C_P_S_2PI_16)+temp;
User_4574 0:b771a5301e43 84 out13=out13*(C_M_S_2PI_16)+temp;
User_4574 0:b771a5301e43 85
User_4574 0:b771a5301e43 86 out14*=(SIN_4PI_16);
User_4574 0:b771a5301e43 87 out10*=(SIN_4PI_16);
User_4574 0:b771a5301e43 88 out14=out14-out10;
User_4574 0:b771a5301e43 89 out10=out14+out10+out10;
User_4574 0:b771a5301e43 90
User_4574 0:b771a5301e43 91 temp=(out15-out11)*(SIN_6PI_16);
User_4574 0:b771a5301e43 92 out11=out11*(C_P_S_6PI_16)+temp;
User_4574 0:b771a5301e43 93 out15=out15*(C_M_S_6PI_16)+temp;
User_4574 0:b771a5301e43 94
User_4574 0:b771a5301e43 95 /* The following are the first set of two point butterfiles */
User_4574 0:b771a5301e43 96 /* for the 4 point CFFT */
User_4574 0:b771a5301e43 97
User_4574 0:b771a5301e43 98 out8+=out10;
User_4574 0:b771a5301e43 99 out10=out8-out10-out10;
User_4574 0:b771a5301e43 100
User_4574 0:b771a5301e43 101 out12+=out14;
User_4574 0:b771a5301e43 102 out14=out12-out14-out14;
User_4574 0:b771a5301e43 103
User_4574 0:b771a5301e43 104 out9+=out11;
User_4574 0:b771a5301e43 105 out11=out9-out11-out11;
User_4574 0:b771a5301e43 106
User_4574 0:b771a5301e43 107 out13+=out15;
User_4574 0:b771a5301e43 108 out15=out13-out15-out15;
User_4574 0:b771a5301e43 109
User_4574 0:b771a5301e43 110 /*The followin are the final set of two point butterflies */
User_4574 0:b771a5301e43 111 output[1]=out8+out9;
User_4574 0:b771a5301e43 112 output[7]=out8-out9;
User_4574 0:b771a5301e43 113
User_4574 0:b771a5301e43 114 output[9]=out12+out13;
User_4574 0:b771a5301e43 115 output[15]=out13-out12;
User_4574 0:b771a5301e43 116
User_4574 0:b771a5301e43 117 output[5]=out10+out15; /* implicit multiplies by */
User_4574 0:b771a5301e43 118 output[13]=out14-out11; /* a twiddle factor of -j */
User_4574 0:b771a5301e43 119 output[3]=out10-out15; /* implicit multiplies by */
User_4574 0:b771a5301e43 120 output[11]=-out14-out11; /* a twiddle factor of -j */
User_4574 0:b771a5301e43 121
User_4574 0:b771a5301e43 122
User_4574 0:b771a5301e43 123 /* What follows is the 8-point FFT of points output[0-7] */
User_4574 0:b771a5301e43 124 /* This 8-point FFT is basically a Decimation in Frequency FFT */
User_4574 0:b771a5301e43 125 /* where we take advantage of the fact that the initial data is real*/
User_4574 0:b771a5301e43 126
User_4574 0:b771a5301e43 127 /* First set of 2-point butterflies */
User_4574 0:b771a5301e43 128
User_4574 0:b771a5301e43 129 out0=out0+out4;
User_4574 0:b771a5301e43 130 out4=out0-out4-out4;
User_4574 0:b771a5301e43 131 out1=out1+out5;
User_4574 0:b771a5301e43 132 out5=out1-out5-out5;
User_4574 0:b771a5301e43 133 out2+=out6;
User_4574 0:b771a5301e43 134 out6=out2-out6-out6;
User_4574 0:b771a5301e43 135 out3+=out7;
User_4574 0:b771a5301e43 136 out7=out3-out7-out7;
User_4574 0:b771a5301e43 137
User_4574 0:b771a5301e43 138 /* Computations to find X[0], X[4], X[6] */
User_4574 0:b771a5301e43 139
User_4574 0:b771a5301e43 140 output[0]=out0+out2;
User_4574 0:b771a5301e43 141 output[4]=out0-out2;
User_4574 0:b771a5301e43 142 out1+=out3;
User_4574 0:b771a5301e43 143 output[12]=out3+out3-out1;
User_4574 0:b771a5301e43 144
User_4574 0:b771a5301e43 145 output[0]+=out1; /* Real Part of X[0] */
User_4574 0:b771a5301e43 146 output[8]=output[0]-out1-out1; /*Real Part of X[4] */
User_4574 0:b771a5301e43 147 /* out2 = Real Part of X[6] */
User_4574 0:b771a5301e43 148 /* out3 = Imag Part of X[6] */
User_4574 0:b771a5301e43 149
User_4574 0:b771a5301e43 150 /* Computations to find X[5], X[7] */
User_4574 0:b771a5301e43 151
User_4574 0:b771a5301e43 152 out5*=SIN_4PI_16;
User_4574 0:b771a5301e43 153 out7*=SIN_4PI_16;
User_4574 0:b771a5301e43 154 out5=out5-out7;
User_4574 0:b771a5301e43 155 out7=out5+out7+out7;
User_4574 0:b771a5301e43 156
User_4574 0:b771a5301e43 157 output[14]=out6-out7; /* Imag Part of X[5] */
User_4574 0:b771a5301e43 158 output[2]=out5+out4; /* Real Part of X[7] */
User_4574 0:b771a5301e43 159 output[6]=out4-out5; /*Real Part of X[5] */
User_4574 0:b771a5301e43 160 output[10]=-out7-out6; /* Imag Part of X[7] */
User_4574 0:b771a5301e43 161 }