Final Project- Nathalie

So for my final project, I’ve created an audiovisual actualizer.

(Seriously watch the whole video; about 2/3 of the way through during the breakdown it gets really cool annnnd I just realized I was talking in the video; I forgot about that. My internet is a mess right now due to intermittent power outages; I’ll upload a different video that doesn’t have me gushing over my own project in the middle of it once it’s working again)

How it’s working: Music goes in through the audio jack, any music you want, off your laptop, off your phone, mp3 player -anything. It gets fed through an arduino FFT library, which does audio analysis on the frequencies. The results of that analysis are then mapped in 6 sections on the 24-pixel LED ring to various colors that change dramatically with the frequencies.

FullSizeRender

My inspiration for this was that, for a lot of my recent artistic career, I’ve been looking for a way to visualize synesthesia in a way that’s meaningful and understandable to someone who isn’t perpetually inside my head with it. Unfortunately, I don’t think I’ve succeeded; the only real way to make something look like what music actually looks like to me would probably be a tone/pitch analysis instead. That said, it still looks pretty darn cool. I think I learned more working on this project than I have all year in any class; I learned how to actually program, for one, without people sitting over my shoulder and telling me what to type next, or following a pattern I found on the internet. I learned a whole lot about audio analysis, and inadvertently about a decent portion of the math behind it (although I think I’ve forgotten most of that now), and I learned a lot about patience and improvisation when things don’t appear to be going the right way.

I also learned that sometimes really strange things happen with code that make your projects work even when nothing is plugged into them. But I’ll figure out why it does that eventually, I think.

freqactualizer

(sorry the diagram is a little funky; Fritzing doesn’t have any neopixel stuff in its libraries so I had to photoshop it in afterwards)

//example sketch modified from FFT library's examples
//example: fft_adc_serial
//butchered and frankensteined together 
//by yours truly


#define LOG_OUT 1 // use the log output function
#define FFT_N 64 // set to 256 point fft

#include  // include the library
#include  //includes FastLED library


#define LED_PIN     6 //pin attached to Neopixels
#define NUM_LEDS    24 //number of lights per Neopixel
#define LED_TYPE    WS2812 //type of LED
#define COLOR_ORDER RGB //these are pretty obv
CRGB leds[NUM_LEDS]; ///this is just important idk what it does

#define UPDATES_PER_SECOND 100  //how many times the LEDs refresh color per second

void setup() {
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS); //this is copied from FastLED's example codes
  //it's in all of them so I figure it's necessary. It looks necessary. 
  //I will readily admit my lack of comprehension to retain honesty.
  
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}


void loop() {


  cli();  // UDRE interrupt slows this way down on arduino1.
  for (int i = 0 ; i < 128 ; i += 2) { // save 256 samples
    while(!(ADCSRA & 0x10)); // wait for adc to be ready
    ADCSRA = 0xf5; // restart adc
    byte m = ADCL; // fetch adc data
    byte j = ADCH;
    int k = (j << 8) | m; // form into an int
    k -= 0x0200; // form into a signed int
    k <<= 6; // form into a 16b signed int
    fft_input[i] = k; // put real data into even bins
    fft_input[i+1] = 0; // set odd bins to 0
  }
  fft_window(); // window the data for better frequency response
  fft_reorder(); // reorder the data before doing the fft
  fft_run(); // process the data in the fft
  fft_mag_log(); // take the output of the fft
  sei();
  
  int numLedsToLight = 24;

  FastLED.clear();

  //using: start i = 3 because the first 3 bins pretty much never change and as such are unusable
  //groups of 4; 3456, 78910, 11-14, 15-18, 19-22, 23-26
  //only going up by 2s so 3-10, 11-18, 19-26, 27-34, 35-42, 43-50
  //3-10 blue group: high bound 87, low bound 44
  //11-18 teal group: high bound 52, low bound 8/19
  //19-26 pink group: high bound 42, low bound 0/8
  //27-34 purple group: high bound 38, low bound 0
  //35-42 green group: high bound 46, low bound 0
  //43-50 yellow group: high bound 37, low bound 0


  //blue, LEDs 0-3; bass
  for (int i = 3 ; i < 11 ; i=i+2) {      int val = fft_log_out[i];     if (val > 70){
      int blueR = 0;
      int blueG = map(val, 30,90, 0,5);
      int blueB = map(val, 30,90, 0,45);
      leds[i/2].setRGB(blueR, blueG, blueB);
    } 
    else if (val > 50){
      int blueR = 20;
      int blueG = map(val, 30,90, 0,3);
      int blueB = map(val, 30,90, 0,27);
      leds[i/2].setRGB(blueR, blueG, blueB);
    }
    else {
      int blueR = 35;
      int blueG = map(val, 30,90, 0,0);
      int blueB = map(val, 30,90, 0,15);
      leds[i/2].setRGB(blueR, blueG, blueB);
    }
  }

  //cyan, LEDs 4-7; lower medium
  for (int i = 11 ; i < 19 ; i=i+2) {      int val = fft_log_out[i];     if (val > 30){
      int cyanR = 0;
      int cyanG = map(val, 30,90, 0,25);
      int cyanB = map(val, 30,90, 0,25);
      leds[i/2].setRGB(cyanR, cyanG, cyanB);
    } 
    else if (val > 20){
      int cyanR = 17;
      int cyanG = map(val, 30,90, 0,20);
      int cyanB = map(val, 30,90, 0,13);
      leds[i/2].setRGB(cyanR, cyanG, cyanB);
    }
    else{
      int cyanR = 30;
      int cyanG = map(val, 30,90, 0,20);
      int cyanB = map(val, 30,90, 0,0);
      leds[i/2].setRGB(cyanR, cyanG, cyanB);
    }
  }
  
  //pink, LEDs 8-11; medium
  for (int i = 19 ; i < 27 ; i=i+2) {      int val = fft_log_out[i];     if (val > 30){
      int pinkR = map(val, 30,90, 0,45);
      int pinkG = 0;
      int pinkB = map(val, 30,90, 0,5);
      leds[i/2].setRGB(pinkR, pinkB, pinkG);
    } 
    else if (val >20) {
      int pinkR = map(val, 30,90, 0,27);
      int pinkG = 20;
      int pinkB = map(val, 30,90, 0,3);
      leds[i/2].setRGB(pinkR, pinkB, pinkG);
    }
    else{
      int pinkR = map(val, 30,90, 0,15);
      int pinkG = 35;
      int pinkB = map(val, 30,90, 0,0);
      leds[i/2].setRGB(pinkR, pinkB, pinkG);
    }
  }

  //purple, LEDs 12-16; higher medium
  for (int i = 27 ; i < 35 ; i=i+2) {      int val = fft_log_out[i];     if (val > 30){
      int purpleR = map(val, 30,90, 0,25);
      int purpleG = 0;
      int purpleB = map(val, 30,90, 0,25);
      leds[i/2].setRGB(purpleR, purpleG, purpleB);
    } 
    else if (val > 20) {
      int purpleR = map(val, 30,90, 0,13);
      int purpleG = 17;
      int purpleB = map(val, 30,90, 0,20);
      leds[i/2].setRGB(purpleR, purpleG, purpleB);
    }
    else{
      int purpleR = map(val, 30,90, 0,0);
      int purpleG = 30;
      int purpleB = map(val, 30,90, 0,20);
      leds[i/2].setRGB(purpleR, purpleG, purpleB);
    }
  }

  //green, LEDs 17-20; high, also one of these is the bass drum and I don't know why
  for (int i = 35 ; i < 43 ; i=i+2) {      int val = fft_log_out[i];     if (val > 33){
      int greenR = map(val, 30,90, 0,5);
      int greenG = map(val, 30,90, 0,45);
      int greenB = 0;
      leds[i/2].setRGB(greenR, greenG, greenB);
    } 
    else if (val > 22) {
      int greenR = map(val, 30,90, 0,3);
      int greenG = map(val, 30,90, 0,27);
      int greenB = 20;
      leds[i/2].setRGB(greenR, greenG, greenB);
    }
    else{
      int greenR = map(val, 30,90, 0,0);
      int greenG = map(val, 30,90, 0,15);
      int greenB = 35;
      leds[i/2].setRGB(greenR, greenG, greenB);
    }
  }

  //yellow, LEDs 20-23; highest
  for (int i = 43 ; i < 51 ; i=i+2) {      int val = fft_log_out[i];     if (val > 25){
      int yellowR = map(val, 30,90, 0,25);
      int yellowG = map(val, 30,90, 0,25);
      int yellowB = 0;
      leds[i/2].setRGB(yellowR, yellowG, yellowB);
    } 
    else if (val > 15){
      int yellowR = map(val, 30,90, 0,13);
      int yellowG = map(val, 30,90, 0,20);
      int yellowB = 17;
      leds[i/2].setRGB(yellowR, yellowG, yellowB);
    }
    else{
      int yellowR = map(val, 30,90, 0,0);
      int yellowG = map(val, 30,90, 0,20);
      int yellowB = 30;
      leds[i/2].setRGB(yellowR, yellowG, yellowB);
    }
  }

  FastLED.show();

  Serial.println("start");
  for (byte i = 0 ; i < FFT_N/2 ; i++) { 
    Serial.println(fft_log_out[i]); // send out the data to the serial port so I can see what it's doing
  }

}

Comments are closed.