Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed-dsp mbed-rtos mbed
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
Generated on Fri Jul 15 2022 09:15:25 by
1.7.2