Matthew Golino / Mbed 2 deprecated FinalProject

Dependencies:   mbed-dsp mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fftstuff.cpp Source File

fftstuff.cpp

00001 #include "fftstuff.h"
00002 #include <iostream>
00003 
00004 AnalogIn mic(p15);
00005 AnalogIn aux(p20);   
00006 bool auxControl = false;
00007 bool micControl = false;
00008 float redColor, greenColor, blueColor;
00009 // Integers used to cycle LED colors
00010 int rIdx = 0;
00011 int gIdx = 1;
00012 int bIdx = 2;
00013 Serial pc2(USBTX, USBRX);
00014 PwmOut grled(p23);
00015 PwmOut rrled(p22);
00016 PwmOut brled(p21);
00017 Ticker counter;
00018 int i = 0; 
00019 int flipCount = 0;
00020 ////////////////////////////////////////////////////////////////////////////////
00021 // CONFIGURATION
00022 // These values alter the behavior of the audio reaction.
00023 ////////////////////////////////////////////////////////////////////////////////
00024 int SLOWDOWN = 0;                       // Create an optical delay in spectrumLoop - useful when only one RGB led is used.
00025                                         // Only active when nonzero.
00026                                         // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency
00027                                         // window = a single color.
00028 int SAMPLE_RATE_HZ = 6000;              // Sample rate of the audio in hertz
00029 float SPECTRUM_MIN_DB = 30.0;           // Audio intensity (in decibels) that maps to low LED brightness => sensitive to quiet
00030 float SPECTRUM_MAX_DB = 100.0;           // Audio intensity (in decibels) that maps to high LED brightness => sensitive to loud
00031 const int FFT_SIZE = 32;               // Size of the FFT
00032 const int PIXEL_COUNT = 3;              // Number of pixels (1)R, (2)G, & (3)B for LED strip
00033 // END CONFIGURATION                    
00034 
00035 ////////////////////////////////////////////////////////////////////////////////
00036 // INTERNAL STATE
00037 // These shouldn't be modified unless you know what you're doing.
00038 ////////////////////////////////////////////////////////////////////////////////
00039 const static arm_cfft_instance_f32 *S;
00040 Ticker samplingTimer;
00041 float samples[FFT_SIZE*2];
00042 float magnitudes[FFT_SIZE];
00043 int sampleCounter = 0;
00044 float frequencyWindow[PIXEL_COUNT+1];
00045 float hues[PIXEL_COUNT];
00046 // END INTERNAL STATE
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 // SAMPLING FUNCTIONS
00050 ////////////////////////////////////////////////////////////////////////////////
00051 // Read from the ADC and store the sample data
00052 void samplingCallback()
00053 {
00054     i++;
00055     if(auxControl) {       // Read aux input (pin 20)
00056        samples[sampleCounter] = (1023 * aux) - 511.0f;
00057     }
00058     else if(micControl) {  // Read mic input (pin 15)
00059         samples[sampleCounter] = (1023 * mic) - 511.0f;     
00060     }
00061     // Complex FFT functions require a coefficient for the imaginary part of the input.
00062     // Since we only have real data, set this coefficient to zero.
00063     samples[sampleCounter+1] = 0.0;
00064     // Update sample buffer position and stop after the buffer is filled
00065     sampleCounter += 2;
00066     if (sampleCounter >= FFT_SIZE*2) {
00067         samplingTimer.detach();
00068     }
00069 }   // End samplingCallBack
00070 
00071 // Begin sampling audio
00072 void samplingBegin()
00073 {
00074     // Reset sample buffer position and start callback at necessary rate.
00075     sampleCounter = 0;
00076     samplingTimer.attach_us(&samplingCallback, 1000000/SAMPLE_RATE_HZ);
00077 }
00078 
00079 // Check if sampling is done before performing FFT
00080 bool samplingIsDone()
00081 {
00082     return sampleCounter >= FFT_SIZE*2;
00083 }   // End samplingIsDone
00084 // END SAMPLING FUNCTIONS
00085 
00086 ////////////////////////////////////////////////////////////////////////////////
00087 // FFT FUNCTIONS
00088 // Used for performing FFT on audio signal
00089 /////////////////////////////////////////////////////////////////////////////////
00090 // Initialize FFT Size
00091 void initFFT() 
00092 {
00093     switch (FFT_SIZE) { // Call appropriate FFT
00094         case 16:
00095             S = & arm_cfft_sR_f32_len16;
00096             break;
00097         case 32:
00098             S = & arm_cfft_sR_f32_len32;
00099             break;
00100         case 64:
00101             S = & arm_cfft_sR_f32_len64;
00102             break;
00103         case 128:
00104             S = & arm_cfft_sR_f32_len128;
00105             break;
00106         case 256:
00107             S = & arm_cfft_sR_f32_len256;
00108             break;
00109         case 512:
00110             S = & arm_cfft_sR_f32_len512;
00111             break;
00112         case 1024:
00113             S = & arm_cfft_sR_f32_len1024;
00114             break;
00115         case 2048:
00116             S = & arm_cfft_sR_f32_len2048;
00117             break;
00118         case 4096:
00119             S = & arm_cfft_sR_f32_len4096;
00120             break;
00121     }
00122 }   // End initFFT
00123 
00124 // Setup the frequency windowing size given sampling rate 
00125 void spectrumSetup()
00126 {
00127     // Set the frequency window values by evenly dividing the possible frequency
00128     float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT);
00129     for (int i = 0; i < PIXEL_COUNT+1; ++i) {
00130         frequencyWindow[i] = i*windowSize;
00131     }
00132 }   // End spectrumSetup
00133 
00134 // Convert a frequency to the appropriate FFT bin it will fall within
00135 int frequencyToBin(float frequency)
00136 {
00137     float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
00138     return int(frequency / binFrequency);
00139 }
00140 
00141 // Compute the average magnitude of a target frequency window vs. all other frequencies
00142 void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean) 
00143 {
00144     *windowMean = 0;
00145     *otherMean = 0;
00146     // Notice the first magnitude bin is skipped because it represents the average power of the signal
00147     for (int i = 1; i < FFT_SIZE/2; ++i) {
00148         // Sum values
00149         if (i >= lowBin && i <= highBin) {
00150             *windowMean += magnitudes[i];
00151         } else {
00152             *otherMean += magnitudes[i];
00153         }
00154     }
00155     // Average values
00156     *windowMean /= (highBin - lowBin) + 1;
00157     *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
00158 }
00159 
00160 // Update LED RGB values based on intensity of frequency window
00161 void spectrumLoop()
00162 {
00163     
00164     // Update each LED color based on the audio intensity of each frequency window
00165     float max = 0.0f;
00166     static int SLrpt = 0; 
00167     static int SLpixcnt = 0;
00168     int SLpixend = 0;
00169     float intensity, otherMean;
00170     if(SLOWDOWN != 0)
00171     {
00172         if(SLOWDOWN >= 1000)
00173         {
00174             if(SLOWDOWN <= (1000 + PIXEL_COUNT-1))
00175             {
00176                 SLpixcnt = SLOWDOWN - 1000;
00177                 SLrpt = 0;
00178                 SLpixend = SLpixcnt + 1;
00179             }
00180             else
00181                 SLOWDOWN = 0;
00182         }
00183         else
00184         {
00185             SLrpt++;
00186             if (SLrpt >= SLOWDOWN)
00187             {
00188                 SLrpt = 0;
00189                 SLpixcnt = SLpixcnt < PIXEL_COUNT-1 ? ++SLpixcnt : 0;
00190             }
00191             SLpixend = SLpixcnt + 1;
00192         }
00193     }
00194     else
00195     { 
00196         SLpixcnt = 0;
00197         SLrpt = 0;
00198         SLpixend = PIXEL_COUNT;
00199     }
00200     
00201     for (int i = SLpixcnt; i < SLpixend; ++i) {
00202         windowMean(magnitudes,
00203                    frequencyToBin(frequencyWindow[i]),
00204                    frequencyToBin(frequencyWindow[i+1]),
00205                    &intensity,
00206                    &otherMean);
00207         // Convert intensity to decibels.
00208         intensity = 20.0*log10(intensity);
00209         //pc2.printf("INTENSITY1: %f\n\r", intensity);
00210         // Scale the intensity and clamp between 0 and 1.0.
00211         intensity -= SPECTRUM_MIN_DB;
00212         //intensity = intensity < 0.0 ? 0.0 : intensity;
00213         intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
00214         intensity = intensity > 1.0 ? 1.0 : intensity;
00215         //pc2.printf("INTENSITY2: %f\n\r", intensity);
00216         
00217         
00218         if(intensity > max){
00219             max = intensity;
00220         }
00221         
00222         
00223         hues[i]=intensity;
00224     }
00225     //cout << "AUX VALUE" << mic << "\n\r" << endl;
00226     //cout << "/n HUES: " << hues[0] << " " << hues[1] << " " << hues[2] << "\n\r" << endl;
00227     redColor= hues[rIdx];
00228     greenColor= hues[gIdx];
00229     blueColor= hues[bIdx]; 
00230     
00231     //pc2.printf("writing colors\n\r");
00232     //pc2.printf("!!!red %f, green %f, blue %f!!!\n\n\n\r", redColor, greenColor, blueColor);
00233     rrled = hues[rIdx]/max;
00234     grled= hues[gIdx]/max;
00235     brled= hues[bIdx]/max; 
00236     // possible add Threading to make this function wait rather than SLOWDOWN
00237 }
00238 
00239 ////////////////////////////////////////////////////////////////////////////////
00240 // TIMING THREADS
00241 ////////////////////////////////////////////////////////////////////////////////
00242 // Cycle given frequency window controlling an LED color
00243 ////*****************************************
00244 void flip() // add input argument for FFT processing
00245 {
00246         rIdx++;
00247         gIdx++;
00248         bIdx++;
00249         if(rIdx > 2){
00250             rIdx = 0;   
00251         }    
00252         if(gIdx > 2){
00253             gIdx = 0;
00254         }
00255         if(bIdx > 2){
00256             bIdx = 0;    
00257         }
00258         // 4s wait time 
00259 }
00260 ////*****************************************
00261 
00262 void runFFT(bool input, float colors[]) 
00263 {
00264      //counter.attach(&flip, 4.0);
00265      // Initialize frequency window size
00266     spectrumSetup();
00267     //pc2.printf("hi");
00268     if (input == true){
00269         micControl = true;
00270         auxControl = false;
00271     }
00272     else{
00273         micControl = false;
00274         auxControl = true;    
00275     }
00276         
00277     
00278     // Begin sampling audio
00279     samplingBegin();
00280     //pc2.printf("sampling began\n");
00281     // Init arm_ccft_32
00282     initFFT();
00283     
00284     //6000 HZ = check back for readable every 1/2 second
00285     i = 0;
00286     while(i< 3000){
00287         if (samplingIsDone()) {
00288             // Run FFT on sample data.
00289             arm_cfft_f32(S, samples, 0, 1);
00290             // Calculate magnitude of complex numbers output by the FFT.
00291             arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE);
00292             spectrumLoop();
00293             // Restart audio sampling.
00294             samplingBegin();
00295         }
00296     }   
00297             
00298     colors[0] = redColor;
00299     colors[1] = greenColor;
00300     colors[2] = blueColor;
00301     flipCount++;
00302     //shift colors around every 4 seconds
00303     if (flipCount >= 8){
00304        flipCount = 0;
00305        flip();
00306     }
00307        
00308        
00309 }
00310 // END FFT FUNCTIONS
00311 
00312