Næþ'n Lasseter
/
GraphicEqFFT
A Graphic Equaliser using 2 Analog inputs and an Fast Fourier Transform
Revision 0:b771a5301e43, committed 2010-03-18
- Comitter:
- User_4574
- Date:
- Thu Mar 18 15:15:33 2010 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fft.cpp Thu Mar 18 15:15:33 2010 +0000 @@ -0,0 +1,161 @@ +/* + * This is not my code and I do not take credit for it. + * http://www.mit.edu/~emin/source_code/fft/index.html + */ + +#define SIN_2PI_16 0.38268343236508978 +#define SIN_4PI_16 0.707106781186547460 +#define SIN_6PI_16 0.923879532511286740 +#define C_P_S_2PI_16 1.30656296487637660 +#define C_M_S_2PI_16 0.54119610014619690 +#define C_P_S_6PI_16 1.3065629648763766 +#define C_M_S_6PI_16 -0.54119610014619690 + +/* INPUT: float input[16], float output[16] */ +/* OUTPUT: none */ +/* EFFECTS: Places the 16 point fft of input in output in a strange */ +/* order using 10 real multiplies and 79 real adds. */ +/* Re{F[0]}= out0 */ +/* Im{F[0]}= 0 */ +/* Re{F[1]}= out8 */ +/* Im{F[1]}= out12 */ +/* Re{F[2]}= out4 */ +/* Im{F[2]}= -out6 */ +/* Re{F[3]}= out11 */ +/* Im{F[3]}= -out15 */ +/* Re{F[4]}= out2 */ +/* Im{F[4]}= -out3 */ +/* Re{F[5]}= out10 */ +/* Im{F[5]}= out14 */ +/* Re{F[6]}= out5 */ +/* Im{F[6]}= -out7 */ +/* Re{F[7]}= out9 */ +/* Im{F[7]}= -out13 */ +/* Re{F[8]}= out1 */ +/* Im{F[8]}=0 */ +/* F[9] through F[15] can be found by using the formula */ +/* Re{F[n]}=Re{F[(16-n)mod16]} and Im{F[n]}= -Im{F[(16-n)mod16]} */ + +/* Note using temporary variables to store intermediate computations */ +/* in the butterflies might speed things up. When the current version */ +/* needs to compute a=a+b, and b=a-b, I do a=a+b followed by b=a-b-b. */ +/* So practically everything is done in place, but the number of adds */ +/* can be reduced by doinc c=a+b followed by b=a-b. */ + +/* The algorithm behind this program is to find F[2k] and F[4k+1] */ +/* seperately. To find F[2k] we take the 8 point Real FFT of x[n]+x[n+8] */ +/* for n from 0 to 7. To find F[4k+1] we take the 4 point Complex FFT of */ +/* exp(-2*pi*j*n/16)*{x[n] - x[n+8] + j(x[n+12]-x[n+4])} for n from 0 to 3.*/ + +void fft(float input[16],float output[16] ) { + float temp, out0, out1, out2, out3, out4, out5, out6, out7, out8; + float out9,out10,out11,out12,out13,out14,out15; + + out0=input[0]+input[8]; /* output[0 through 7] is the data that we */ + out1=input[1]+input[9]; /* take the 8 point real FFT of. */ + out2=input[2]+input[10]; + out3=input[3]+input[11]; + out4=input[4]+input[12]; + out5=input[5]+input[13]; + out6=input[6]+input[14]; + out7=input[7]+input[15]; + + + + out8=input[0]-input[8]; /* inputs 8,9,10,11 are */ + out9=input[1]-input[9]; /* the Real part of the */ + out10=input[2]-input[10]; /* 4 point Complex FFT inputs.*/ + out11=input[3]-input[11]; + out12=input[12]-input[4]; /* outputs 12,13,14,15 are */ + out13=input[13]-input[5]; /* the Imaginary pars of */ + out14=input[14]-input[6]; /* the 4 point Complex FFT inputs.*/ + out15=input[15]-input[7]; + + /*First we do the "twiddle factor" multiplies for the 4 point CFFT */ + /*Note that we use the following handy trick for doing a complex */ + /*multiply: (e+jf)=(a+jb)*(c+jd) */ + /* e=(a-b)*d + a*(c-d) and f=(a-b)*d + b*(c+d) */ + + /* C_M_S_2PI/16=cos(2pi/16)-sin(2pi/16) when replaced by macroexpansion */ + /* C_P_S_2PI/16=cos(2pi/16)+sin(2pi/16) when replaced by macroexpansion */ + /* (SIN_2PI_16)=sin(2pi/16) when replaced by macroexpansion */ + temp=(out13-out9)*(SIN_2PI_16); + out9=out9*(C_P_S_2PI_16)+temp; + out13=out13*(C_M_S_2PI_16)+temp; + + out14*=(SIN_4PI_16); + out10*=(SIN_4PI_16); + out14=out14-out10; + out10=out14+out10+out10; + + temp=(out15-out11)*(SIN_6PI_16); + out11=out11*(C_P_S_6PI_16)+temp; + out15=out15*(C_M_S_6PI_16)+temp; + + /* The following are the first set of two point butterfiles */ + /* for the 4 point CFFT */ + + out8+=out10; + out10=out8-out10-out10; + + out12+=out14; + out14=out12-out14-out14; + + out9+=out11; + out11=out9-out11-out11; + + out13+=out15; + out15=out13-out15-out15; + + /*The followin are the final set of two point butterflies */ + output[1]=out8+out9; + output[7]=out8-out9; + + output[9]=out12+out13; + output[15]=out13-out12; + + output[5]=out10+out15; /* implicit multiplies by */ + output[13]=out14-out11; /* a twiddle factor of -j */ + output[3]=out10-out15; /* implicit multiplies by */ + output[11]=-out14-out11; /* a twiddle factor of -j */ + + + /* What follows is the 8-point FFT of points output[0-7] */ + /* This 8-point FFT is basically a Decimation in Frequency FFT */ + /* where we take advantage of the fact that the initial data is real*/ + + /* First set of 2-point butterflies */ + + out0=out0+out4; + out4=out0-out4-out4; + out1=out1+out5; + out5=out1-out5-out5; + out2+=out6; + out6=out2-out6-out6; + out3+=out7; + out7=out3-out7-out7; + + /* Computations to find X[0], X[4], X[6] */ + + output[0]=out0+out2; + output[4]=out0-out2; + out1+=out3; + output[12]=out3+out3-out1; + + output[0]+=out1; /* Real Part of X[0] */ + output[8]=output[0]-out1-out1; /*Real Part of X[4] */ + /* out2 = Real Part of X[6] */ + /* out3 = Imag Part of X[6] */ + + /* Computations to find X[5], X[7] */ + + out5*=SIN_4PI_16; + out7*=SIN_4PI_16; + out5=out5-out7; + out7=out5+out7+out7; + + output[14]=out6-out7; /* Imag Part of X[5] */ + output[2]=out5+out4; /* Real Part of X[7] */ + output[6]=out4-out5; /*Real Part of X[5] */ + output[10]=-out7-out6; /* Imag Part of X[7] */ +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Mar 18 15:15:33 2010 +0000 @@ -0,0 +1,71 @@ +/* + * This is my code. It takes 16 samples of the analog in pins and writes the values back to the serial port. + * Nathan Lasseter 2010 + */ + +#include "mbed.h" +#include "TextLCD.h" + +extern void fft(float inarr[16], float outarr[16]); //look for fft at link not compile time + +//Serial pc(USBTX,USBRX); ///dev/ttyACM0 is locked on university pc's +Serial pc(p9,p10); //So I use /dev/ttyS0 instead +BusOut bargraph(p21,p22,p23,p24,p25,p26,p27,p28,p29,p30); //Dot matrix bargraphs horizontal bus +BusOut graphs(p11,p12,p13,p14,p15,p16,p17,p18); //Dot matrix bargraphs vertical bus +AnalogIn left(p19); //Left channel input +AnalogIn right(p20); //Right channel input + +void outputmatrix(float avg, int which) { //This is the simple dot matrix driver. + switch (which) { //Select a bargraph + case 8: graphs = 0xFF; //8: off + case 0: graphs = 0xFE; //0-7 are right to left. They turn on a bargraph by going low. + case 1: graphs = 0xFC; + case 2: graphs = 0xF8; + case 3: graphs = 0xF0; + case 4: graphs = 0xE0; + case 5: graphs = 0xC0; + case 6: graphs = 0x80; + case 7: graphs = 0x00; + } + if (avg > 0.9) { bargraph=0x3FF; return; } //Same principle, but set a value on the graph. + if (avg > 0.8) { bargraph=0x1FF; return; } + if (avg > 0.7) { bargraph=0x0FF; return; } + if (avg > 0.6) { bargraph=0x07F; return; } + if (avg > 0.5) { bargraph=0x03F; return; } + if (avg > 0.4) { bargraph=0x01F; return; } + if (avg > 0.3) { bargraph=0x00F; return; } + if (avg > 0.2) { bargraph=0x007; return; } + if (avg > 0.1) { bargraph=0x003; return; } + if (avg > 0.0) { bargraph=0x001; return; } + bargraph=0x000; //Default to all off +} + +int main() { //Main code + while(1) { + int i; +/* float leftin[16], leftout[16]; //While technically it can support 16 bands over each of 2 channels... + float rightin[16], rightout[16]; + for(i=0;i<16;i++) leftin[i] = left; + for(i=0;i<16;i++) rightin[i] = right; + fft(leftin, leftout); + fft(rightin, rightout); */ + float in[16], out[16], avg[8]; //I only use 8 on one channel + for(i=0;i<16;i++) in[i] = (left + right) / 2; //So I average the two + fft(in, out); + for(i=0;i<8;i++) avg[i] = (out[2*i] + out[(2*i)+1]) / 2; //And then average pairs of bands +/* pc.printf("%f %f %f %f %f %f %f %f\t%f %f %f %f %f %f %f %f\n", + leftout[0], leftout[1], leftout[2], leftout[3], + leftout[4], leftout[5], leftout[6], leftout[7], + leftout[8], leftout[9], leftout[10], leftout[11], + leftout[12], leftout[13], leftout[14], leftout[15]); + pc.printf("%f %f %f %f %f %f %f %f\t%f %f %f %f %f %f %f %f\n\n", + rightout[0], rightout[1], rightout[2], rightout[3], + rightout[4], rightout[5], rightout[6], rightout[7], + rightout[8], rightout[9], rightout[10], rightout[11], + rightout[12], rightout[13], rightout[14], rightout[15]); */ + pc.printf("%f %f %f %f\t%f %f %f %f\r\n", //Then print the values to the uart + avg[0], avg[1], avg[2], avg[3], + avg[4], avg[5], avg[6], avg[7]); + for(i=0;i<8;i++) outputmatrix(avg[i], i); //And display on the bargrpahs + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Mar 18 15:15:33 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0