Audio Reactive Infinity Mirror

Dependencies:   mbed-dsp mbed-rtos mbed

Infinity Mirror Project Page https://developer.mbed.org/users/mgolino/notebook/infinity-mirror/

Committer:
mgolino
Date:
Sat Dec 12 01:22:30 2015 +0000
Revision:
0:85385a11b2da
Audio Reactive Infinity Mirror

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mgolino 0:85385a11b2da 1 #include "fftstuff.h"
mgolino 0:85385a11b2da 2 #include <iostream>
mgolino 0:85385a11b2da 3
mgolino 0:85385a11b2da 4 AnalogIn mic(p15);
mgolino 0:85385a11b2da 5 AnalogIn aux(p20);
mgolino 0:85385a11b2da 6 bool auxControl = false;
mgolino 0:85385a11b2da 7 bool micControl = false;
mgolino 0:85385a11b2da 8 float redColor, greenColor, blueColor;
mgolino 0:85385a11b2da 9 // Integers used to cycle LED colors
mgolino 0:85385a11b2da 10 int rIdx = 0;
mgolino 0:85385a11b2da 11 int gIdx = 1;
mgolino 0:85385a11b2da 12 int bIdx = 2;
mgolino 0:85385a11b2da 13 Serial pc2(USBTX, USBRX);
mgolino 0:85385a11b2da 14 PwmOut grled(p23);
mgolino 0:85385a11b2da 15 PwmOut rrled(p22);
mgolino 0:85385a11b2da 16 PwmOut brled(p21);
mgolino 0:85385a11b2da 17 Ticker counter;
mgolino 0:85385a11b2da 18 int i = 0;
mgolino 0:85385a11b2da 19 int flipCount = 0;
mgolino 0:85385a11b2da 20 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 21 // CONFIGURATION
mgolino 0:85385a11b2da 22 // These values alter the behavior of the audio reaction.
mgolino 0:85385a11b2da 23 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 24 int SLOWDOWN = 0; // Create an optical delay in spectrumLoop - useful when only one RGB led is used.
mgolino 0:85385a11b2da 25 // Only active when nonzero.
mgolino 0:85385a11b2da 26 // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency
mgolino 0:85385a11b2da 27 // window = a single color.
mgolino 0:85385a11b2da 28 int SAMPLE_RATE_HZ = 6000; // Sample rate of the audio in hertz
mgolino 0:85385a11b2da 29 float SPECTRUM_MIN_DB = 30.0; // Audio intensity (in decibels) that maps to low LED brightness => sensitive to quiet
mgolino 0:85385a11b2da 30 float SPECTRUM_MAX_DB = 100.0; // Audio intensity (in decibels) that maps to high LED brightness => sensitive to loud
mgolino 0:85385a11b2da 31 const int FFT_SIZE = 32; // Size of the FFT
mgolino 0:85385a11b2da 32 const int PIXEL_COUNT = 3; // Number of pixels (1)R, (2)G, & (3)B for LED strip
mgolino 0:85385a11b2da 33 // END CONFIGURATION
mgolino 0:85385a11b2da 34
mgolino 0:85385a11b2da 35 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 36 // INTERNAL STATE
mgolino 0:85385a11b2da 37 // These shouldn't be modified unless you know what you're doing.
mgolino 0:85385a11b2da 38 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 39 const static arm_cfft_instance_f32 *S;
mgolino 0:85385a11b2da 40 Ticker samplingTimer;
mgolino 0:85385a11b2da 41 float samples[FFT_SIZE*2];
mgolino 0:85385a11b2da 42 float magnitudes[FFT_SIZE];
mgolino 0:85385a11b2da 43 int sampleCounter = 0;
mgolino 0:85385a11b2da 44 float frequencyWindow[PIXEL_COUNT+1];
mgolino 0:85385a11b2da 45 float hues[PIXEL_COUNT];
mgolino 0:85385a11b2da 46 // END INTERNAL STATE
mgolino 0:85385a11b2da 47
mgolino 0:85385a11b2da 48 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 49 // SAMPLING FUNCTIONS
mgolino 0:85385a11b2da 50 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 51 // Read from the ADC and store the sample data
mgolino 0:85385a11b2da 52 void samplingCallback()
mgolino 0:85385a11b2da 53 {
mgolino 0:85385a11b2da 54 i++;
mgolino 0:85385a11b2da 55 if(auxControl) { // Read aux input (pin 20)
mgolino 0:85385a11b2da 56 samples[sampleCounter] = (1023 * aux) - 511.0f;
mgolino 0:85385a11b2da 57 }
mgolino 0:85385a11b2da 58 else if(micControl) { // Read mic input (pin 15)
mgolino 0:85385a11b2da 59 samples[sampleCounter] = (1023 * mic) - 511.0f;
mgolino 0:85385a11b2da 60 }
mgolino 0:85385a11b2da 61 // Complex FFT functions require a coefficient for the imaginary part of the input.
mgolino 0:85385a11b2da 62 // Since we only have real data, set this coefficient to zero.
mgolino 0:85385a11b2da 63 samples[sampleCounter+1] = 0.0;
mgolino 0:85385a11b2da 64 // Update sample buffer position and stop after the buffer is filled
mgolino 0:85385a11b2da 65 sampleCounter += 2;
mgolino 0:85385a11b2da 66 if (sampleCounter >= FFT_SIZE*2) {
mgolino 0:85385a11b2da 67 samplingTimer.detach();
mgolino 0:85385a11b2da 68 }
mgolino 0:85385a11b2da 69 } // End samplingCallBack
mgolino 0:85385a11b2da 70
mgolino 0:85385a11b2da 71 // Begin sampling audio
mgolino 0:85385a11b2da 72 void samplingBegin()
mgolino 0:85385a11b2da 73 {
mgolino 0:85385a11b2da 74 // Reset sample buffer position and start callback at necessary rate.
mgolino 0:85385a11b2da 75 sampleCounter = 0;
mgolino 0:85385a11b2da 76 samplingTimer.attach_us(&samplingCallback, 1000000/SAMPLE_RATE_HZ);
mgolino 0:85385a11b2da 77 }
mgolino 0:85385a11b2da 78
mgolino 0:85385a11b2da 79 // Check if sampling is done before performing FFT
mgolino 0:85385a11b2da 80 bool samplingIsDone()
mgolino 0:85385a11b2da 81 {
mgolino 0:85385a11b2da 82 return sampleCounter >= FFT_SIZE*2;
mgolino 0:85385a11b2da 83 } // End samplingIsDone
mgolino 0:85385a11b2da 84 // END SAMPLING FUNCTIONS
mgolino 0:85385a11b2da 85
mgolino 0:85385a11b2da 86 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 87 // FFT FUNCTIONS
mgolino 0:85385a11b2da 88 // Used for performing FFT on audio signal
mgolino 0:85385a11b2da 89 /////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 90 // Initialize FFT Size
mgolino 0:85385a11b2da 91 void initFFT()
mgolino 0:85385a11b2da 92 {
mgolino 0:85385a11b2da 93 switch (FFT_SIZE) { // Call appropriate FFT
mgolino 0:85385a11b2da 94 case 16:
mgolino 0:85385a11b2da 95 S = & arm_cfft_sR_f32_len16;
mgolino 0:85385a11b2da 96 break;
mgolino 0:85385a11b2da 97 case 32:
mgolino 0:85385a11b2da 98 S = & arm_cfft_sR_f32_len32;
mgolino 0:85385a11b2da 99 break;
mgolino 0:85385a11b2da 100 case 64:
mgolino 0:85385a11b2da 101 S = & arm_cfft_sR_f32_len64;
mgolino 0:85385a11b2da 102 break;
mgolino 0:85385a11b2da 103 case 128:
mgolino 0:85385a11b2da 104 S = & arm_cfft_sR_f32_len128;
mgolino 0:85385a11b2da 105 break;
mgolino 0:85385a11b2da 106 case 256:
mgolino 0:85385a11b2da 107 S = & arm_cfft_sR_f32_len256;
mgolino 0:85385a11b2da 108 break;
mgolino 0:85385a11b2da 109 case 512:
mgolino 0:85385a11b2da 110 S = & arm_cfft_sR_f32_len512;
mgolino 0:85385a11b2da 111 break;
mgolino 0:85385a11b2da 112 case 1024:
mgolino 0:85385a11b2da 113 S = & arm_cfft_sR_f32_len1024;
mgolino 0:85385a11b2da 114 break;
mgolino 0:85385a11b2da 115 case 2048:
mgolino 0:85385a11b2da 116 S = & arm_cfft_sR_f32_len2048;
mgolino 0:85385a11b2da 117 break;
mgolino 0:85385a11b2da 118 case 4096:
mgolino 0:85385a11b2da 119 S = & arm_cfft_sR_f32_len4096;
mgolino 0:85385a11b2da 120 break;
mgolino 0:85385a11b2da 121 }
mgolino 0:85385a11b2da 122 } // End initFFT
mgolino 0:85385a11b2da 123
mgolino 0:85385a11b2da 124 // Setup the frequency windowing size given sampling rate
mgolino 0:85385a11b2da 125 void spectrumSetup()
mgolino 0:85385a11b2da 126 {
mgolino 0:85385a11b2da 127 // Set the frequency window values by evenly dividing the possible frequency
mgolino 0:85385a11b2da 128 float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT);
mgolino 0:85385a11b2da 129 for (int i = 0; i < PIXEL_COUNT+1; ++i) {
mgolino 0:85385a11b2da 130 frequencyWindow[i] = i*windowSize;
mgolino 0:85385a11b2da 131 }
mgolino 0:85385a11b2da 132 } // End spectrumSetup
mgolino 0:85385a11b2da 133
mgolino 0:85385a11b2da 134 // Convert a frequency to the appropriate FFT bin it will fall within
mgolino 0:85385a11b2da 135 int frequencyToBin(float frequency)
mgolino 0:85385a11b2da 136 {
mgolino 0:85385a11b2da 137 float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
mgolino 0:85385a11b2da 138 return int(frequency / binFrequency);
mgolino 0:85385a11b2da 139 }
mgolino 0:85385a11b2da 140
mgolino 0:85385a11b2da 141 // Compute the average magnitude of a target frequency window vs. all other frequencies
mgolino 0:85385a11b2da 142 void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean)
mgolino 0:85385a11b2da 143 {
mgolino 0:85385a11b2da 144 *windowMean = 0;
mgolino 0:85385a11b2da 145 *otherMean = 0;
mgolino 0:85385a11b2da 146 // Notice the first magnitude bin is skipped because it represents the average power of the signal
mgolino 0:85385a11b2da 147 for (int i = 1; i < FFT_SIZE/2; ++i) {
mgolino 0:85385a11b2da 148 // Sum values
mgolino 0:85385a11b2da 149 if (i >= lowBin && i <= highBin) {
mgolino 0:85385a11b2da 150 *windowMean += magnitudes[i];
mgolino 0:85385a11b2da 151 } else {
mgolino 0:85385a11b2da 152 *otherMean += magnitudes[i];
mgolino 0:85385a11b2da 153 }
mgolino 0:85385a11b2da 154 }
mgolino 0:85385a11b2da 155 // Average values
mgolino 0:85385a11b2da 156 *windowMean /= (highBin - lowBin) + 1;
mgolino 0:85385a11b2da 157 *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
mgolino 0:85385a11b2da 158 }
mgolino 0:85385a11b2da 159
mgolino 0:85385a11b2da 160 // Update LED RGB values based on intensity of frequency window
mgolino 0:85385a11b2da 161 void spectrumLoop()
mgolino 0:85385a11b2da 162 {
mgolino 0:85385a11b2da 163
mgolino 0:85385a11b2da 164 // Update each LED color based on the audio intensity of each frequency window
mgolino 0:85385a11b2da 165 float max = 0.0f;
mgolino 0:85385a11b2da 166 static int SLrpt = 0;
mgolino 0:85385a11b2da 167 static int SLpixcnt = 0;
mgolino 0:85385a11b2da 168 int SLpixend = 0;
mgolino 0:85385a11b2da 169 float intensity, otherMean;
mgolino 0:85385a11b2da 170 if(SLOWDOWN != 0)
mgolino 0:85385a11b2da 171 {
mgolino 0:85385a11b2da 172 if(SLOWDOWN >= 1000)
mgolino 0:85385a11b2da 173 {
mgolino 0:85385a11b2da 174 if(SLOWDOWN <= (1000 + PIXEL_COUNT-1))
mgolino 0:85385a11b2da 175 {
mgolino 0:85385a11b2da 176 SLpixcnt = SLOWDOWN - 1000;
mgolino 0:85385a11b2da 177 SLrpt = 0;
mgolino 0:85385a11b2da 178 SLpixend = SLpixcnt + 1;
mgolino 0:85385a11b2da 179 }
mgolino 0:85385a11b2da 180 else
mgolino 0:85385a11b2da 181 SLOWDOWN = 0;
mgolino 0:85385a11b2da 182 }
mgolino 0:85385a11b2da 183 else
mgolino 0:85385a11b2da 184 {
mgolino 0:85385a11b2da 185 SLrpt++;
mgolino 0:85385a11b2da 186 if (SLrpt >= SLOWDOWN)
mgolino 0:85385a11b2da 187 {
mgolino 0:85385a11b2da 188 SLrpt = 0;
mgolino 0:85385a11b2da 189 SLpixcnt = SLpixcnt < PIXEL_COUNT-1 ? ++SLpixcnt : 0;
mgolino 0:85385a11b2da 190 }
mgolino 0:85385a11b2da 191 SLpixend = SLpixcnt + 1;
mgolino 0:85385a11b2da 192 }
mgolino 0:85385a11b2da 193 }
mgolino 0:85385a11b2da 194 else
mgolino 0:85385a11b2da 195 {
mgolino 0:85385a11b2da 196 SLpixcnt = 0;
mgolino 0:85385a11b2da 197 SLrpt = 0;
mgolino 0:85385a11b2da 198 SLpixend = PIXEL_COUNT;
mgolino 0:85385a11b2da 199 }
mgolino 0:85385a11b2da 200
mgolino 0:85385a11b2da 201 for (int i = SLpixcnt; i < SLpixend; ++i) {
mgolino 0:85385a11b2da 202 windowMean(magnitudes,
mgolino 0:85385a11b2da 203 frequencyToBin(frequencyWindow[i]),
mgolino 0:85385a11b2da 204 frequencyToBin(frequencyWindow[i+1]),
mgolino 0:85385a11b2da 205 &intensity,
mgolino 0:85385a11b2da 206 &otherMean);
mgolino 0:85385a11b2da 207 // Convert intensity to decibels.
mgolino 0:85385a11b2da 208 intensity = 20.0*log10(intensity);
mgolino 0:85385a11b2da 209 //pc2.printf("INTENSITY1: %f\n\r", intensity);
mgolino 0:85385a11b2da 210 // Scale the intensity and clamp between 0 and 1.0.
mgolino 0:85385a11b2da 211 intensity -= SPECTRUM_MIN_DB;
mgolino 0:85385a11b2da 212 //intensity = intensity < 0.0 ? 0.0 : intensity;
mgolino 0:85385a11b2da 213 intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
mgolino 0:85385a11b2da 214 intensity = intensity > 1.0 ? 1.0 : intensity;
mgolino 0:85385a11b2da 215 //pc2.printf("INTENSITY2: %f\n\r", intensity);
mgolino 0:85385a11b2da 216
mgolino 0:85385a11b2da 217
mgolino 0:85385a11b2da 218 if(intensity > max){
mgolino 0:85385a11b2da 219 max = intensity;
mgolino 0:85385a11b2da 220 }
mgolino 0:85385a11b2da 221
mgolino 0:85385a11b2da 222
mgolino 0:85385a11b2da 223 hues[i]=intensity;
mgolino 0:85385a11b2da 224 }
mgolino 0:85385a11b2da 225 //cout << "AUX VALUE" << mic << "\n\r" << endl;
mgolino 0:85385a11b2da 226 //cout << "/n HUES: " << hues[0] << " " << hues[1] << " " << hues[2] << "\n\r" << endl;
mgolino 0:85385a11b2da 227 redColor= hues[rIdx];
mgolino 0:85385a11b2da 228 greenColor= hues[gIdx];
mgolino 0:85385a11b2da 229 blueColor= hues[bIdx];
mgolino 0:85385a11b2da 230
mgolino 0:85385a11b2da 231 //pc2.printf("writing colors\n\r");
mgolino 0:85385a11b2da 232 //pc2.printf("!!!red %f, green %f, blue %f!!!\n\n\n\r", redColor, greenColor, blueColor);
mgolino 0:85385a11b2da 233 rrled = hues[rIdx]/max;
mgolino 0:85385a11b2da 234 grled= hues[gIdx]/max;
mgolino 0:85385a11b2da 235 brled= hues[bIdx]/max;
mgolino 0:85385a11b2da 236 // possible add Threading to make this function wait rather than SLOWDOWN
mgolino 0:85385a11b2da 237 }
mgolino 0:85385a11b2da 238
mgolino 0:85385a11b2da 239 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 240 // TIMING THREADS
mgolino 0:85385a11b2da 241 ////////////////////////////////////////////////////////////////////////////////
mgolino 0:85385a11b2da 242 // Cycle given frequency window controlling an LED color
mgolino 0:85385a11b2da 243 ////*****************************************
mgolino 0:85385a11b2da 244 void flip() // add input argument for FFT processing
mgolino 0:85385a11b2da 245 {
mgolino 0:85385a11b2da 246 rIdx++;
mgolino 0:85385a11b2da 247 gIdx++;
mgolino 0:85385a11b2da 248 bIdx++;
mgolino 0:85385a11b2da 249 if(rIdx > 2){
mgolino 0:85385a11b2da 250 rIdx = 0;
mgolino 0:85385a11b2da 251 }
mgolino 0:85385a11b2da 252 if(gIdx > 2){
mgolino 0:85385a11b2da 253 gIdx = 0;
mgolino 0:85385a11b2da 254 }
mgolino 0:85385a11b2da 255 if(bIdx > 2){
mgolino 0:85385a11b2da 256 bIdx = 0;
mgolino 0:85385a11b2da 257 }
mgolino 0:85385a11b2da 258 // 4s wait time
mgolino 0:85385a11b2da 259 }
mgolino 0:85385a11b2da 260 ////*****************************************
mgolino 0:85385a11b2da 261
mgolino 0:85385a11b2da 262 void runFFT(bool input, float colors[])
mgolino 0:85385a11b2da 263 {
mgolino 0:85385a11b2da 264 //counter.attach(&flip, 4.0);
mgolino 0:85385a11b2da 265 // Initialize frequency window size
mgolino 0:85385a11b2da 266 spectrumSetup();
mgolino 0:85385a11b2da 267 //pc2.printf("hi");
mgolino 0:85385a11b2da 268 if (input == true){
mgolino 0:85385a11b2da 269 micControl = true;
mgolino 0:85385a11b2da 270 auxControl = false;
mgolino 0:85385a11b2da 271 }
mgolino 0:85385a11b2da 272 else{
mgolino 0:85385a11b2da 273 micControl = false;
mgolino 0:85385a11b2da 274 auxControl = true;
mgolino 0:85385a11b2da 275 }
mgolino 0:85385a11b2da 276
mgolino 0:85385a11b2da 277
mgolino 0:85385a11b2da 278 // Begin sampling audio
mgolino 0:85385a11b2da 279 samplingBegin();
mgolino 0:85385a11b2da 280 //pc2.printf("sampling began\n");
mgolino 0:85385a11b2da 281 // Init arm_ccft_32
mgolino 0:85385a11b2da 282 initFFT();
mgolino 0:85385a11b2da 283
mgolino 0:85385a11b2da 284 //6000 HZ = check back for readable every 1/2 second
mgolino 0:85385a11b2da 285 i = 0;
mgolino 0:85385a11b2da 286 while(i< 3000){
mgolino 0:85385a11b2da 287 if (samplingIsDone()) {
mgolino 0:85385a11b2da 288 // Run FFT on sample data.
mgolino 0:85385a11b2da 289 arm_cfft_f32(S, samples, 0, 1);
mgolino 0:85385a11b2da 290 // Calculate magnitude of complex numbers output by the FFT.
mgolino 0:85385a11b2da 291 arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE);
mgolino 0:85385a11b2da 292 spectrumLoop();
mgolino 0:85385a11b2da 293 // Restart audio sampling.
mgolino 0:85385a11b2da 294 samplingBegin();
mgolino 0:85385a11b2da 295 }
mgolino 0:85385a11b2da 296 }
mgolino 0:85385a11b2da 297
mgolino 0:85385a11b2da 298 colors[0] = redColor;
mgolino 0:85385a11b2da 299 colors[1] = greenColor;
mgolino 0:85385a11b2da 300 colors[2] = blueColor;
mgolino 0:85385a11b2da 301 flipCount++;
mgolino 0:85385a11b2da 302 //shift colors around every 4 seconds
mgolino 0:85385a11b2da 303 if (flipCount >= 8){
mgolino 0:85385a11b2da 304 flipCount = 0;
mgolino 0:85385a11b2da 305 flip();
mgolino 0:85385a11b2da 306 }
mgolino 0:85385a11b2da 307
mgolino 0:85385a11b2da 308
mgolino 0:85385a11b2da 309 }
mgolino 0:85385a11b2da 310 // END FFT FUNCTIONS
mgolino 0:85385a11b2da 311
mgolino 0:85385a11b2da 312