AUDIO VISUALIZER

This spectrum analyzer includes many innovations, such as the use of sub-pixeling to display intermediate brightnesses and the adaptive display of only the loudest frequencies to easily distinguish each piece of music.

Engineer

Asher B

Area of Interest

Aerospace Engineering

School

Fusion Academy

Grade

Incoming Sophomore

Final Project

For the completed project, I refined the Processing code to adapt to loud and quiet sounds, to display audio only above the minimum value, and to store values as a single byte of 0-255 (maximally efficient) rather than as an integer of 0-8 (an incredible waste of space). All that was needed was to enhance the Arduino code, making it able to take in a byte (say, 0x4a) and convert it into pixels (2 of 100% brightness and one of 33%) and apply this to every row for a far smoother visualization.

Final Code (Arduino)

#include <Adafruit_NeoPixel.h>
#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(256, PIN, NEO_GRB + NEO_KHZ800);
uint8_t val;
uint8_t i = 0;

void setup() {
  Serial.begin(57600);
  strip.begin();
  strip.show();
}

void loop() {
  while (i < 32) {
    if (Serial.available()) {
          val = Serial.read();
          clearRow(31-i);
          row255(31-i, val);
      i++;
    }
  }
  strip.show();
  i = 0;
}

void clearRow(uint8_t num) {
  int num8 = num*8;
  for (uint8_t i = 0; i<8; i++) {
    strip.setPixelColor(num8+i, 0);
  }
}

void row255(uint8_t num, uint8_t cap) {
  float G = max(min(pow(cap/255.0,2)*3,1),0);
  uint8_t S = int(48*pow((cap % 32)/32.0,2));
  uint8_t L = (cap – (cap % 32)) / 32;
  if (num % 2 == 0) {
    uint16_t num8 = num * 8;
    uint8_t i = 0;
    while (i<L) {
          strip.setPixelColor(i+num8, strip.Color(0,48*G,48));
          i++;
    }
    if (L != 8) {
          strip.setPixelColor(i+num8,strip.Color(0,S*G,S));
    }
  } else {
    uint16_t num8 = num * 8 + 7;
    uint8_t i = 0;
    while (i<L) {
          strip.setPixelColor(num8-i, strip.Color(0,48*G,48));
          i++;
    }
    if (L != 8) {
          strip.setPixelColor(num8-i,strip.Color(0,S*G,S));
    }
  }
}

Code for 2nd Milestone (Processing)

import processing.serial.*;
import processing.sound.*;
 
Serial usedPort;
FFT fft;
float scale = 1.0;
float minValue = 0.0;
int bands = 1 << 6;
int section = 1 << 5;
float[] sum = new float[bands];
float[] sec = new float[section];
float[] powr = new float[section];
 
public void setup() {
  usedPort = new Serial(this, Serial.list()[1], 57600);
  SoundFile sample = new SoundFile(this, “portal2.aiff”);
  sample.loop();
  fft = new FFT(this, bands);
  fft.input(sample);
  for (int i = 0; i < section; i++) {
    powr[i] = 1+0.6*i; //1+2*i
  }
  delay(120);
}
 
void draw() {
  sec = subset(sum, 0, section);
  minValue = 0.75*min(sec);
  scale = 240/max(max(sec)-minValue,0.05);
  fft.analyze();
  for (int i = 0; i < section; i++) {
    sum[i] += (fft.spectrum[i]*powr[i] – sum[i]) * 0.1;
    usedPort.write(byte(max(min(scale*(sum[i]-minValue),255),0)));
  }
  delay(17);
}
 

Second Milestone

My second milestone was by far the most difficult, as it involved sending the data from Processing to the Arduino. I used modified  Processing code from this tutorial (link) to get audio data, and this tutorial (link) to help connect it to the Arduino.

Code for 2nd Milestone (Arduino)

#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(256, PIN, NEO_GRB + NEO_KHZ800);

uint8_t val;
uint8_t i = 0;
uint32_t vol[] = {
  strip.Color(0,0,0),
  strip.Color(0,48,4),
  strip.Color(0,48,0),
  strip.Color(16,48,0),
  strip.Color(32,48,0),
  strip.Color(48,48,0),
  strip.Color(48,32,0),
  strip.Color(48,8,0),
  strip.Color(48,0,0),
  strip.Color(64,0,0)
};

void setup() {
  Serial.begin(57600);
  strip.begin();
  strip.show();
}

void loop() {
  while (i < 32) {
    if (Serial.available())
    {
      val = Serial.read();
      clearRow(31-i);
      row8(31-i, val);
      i++;
    }
  }
  strip.show();
  i = 0;
}

void clearRow(uint8_t num) {
  int num8 = num*8;
  for (uint8_t i = 0; i<8; i++) {
    strip.setPixelColor(num8+i, 0);
  }
}

void row8(uint8_t num, uint8_t cap) {
  if (num % 2 == 0) {
    int num8 = num*8;
    for (uint8_t i = 0; i<cap; i++) {
      strip.setPixelColor(i+num8, vol[cap]);
    }
  }
  else {
    int num8 = num * 8 + 7;
     for (uint8_t i = 0; i<cap; i++) {
      strip.setPixelColor(num8-i, vol[cap]);
    }
  }
}

Code for 2nd Milestone (Processing)

import processing.serial.*;
import processing.sound.*;
 
Serial usedPort;
FFT fft;
float scale = 1.0;
float minValue = 0.0;
int bands = 1 << 5;
float smoothingFactor = 0.1;
float[] sum = new float[bands];
 
public void setup() {
  usedPort = new Serial(this, Serial.list()[1], 57600);
  SoundFile sample = new SoundFile(this, “dvorak.aiff”);
  sample.loop();
  fft = new FFT(this, bands);
  fft.input(sample);
}
 
void draw() {
  fft.analyze();
  for (int i = 0; i < bands; i++) {
    sum[i] += (fft.spectrum[i] – sum[i]) * smoothingFactor;
  }
  for (int i = 0; i < 32; i++) {
    usedPort.write(byte(max(min(50*sum[i]*(1+i),8),0)));
  }
  delay(16);
}
 

First Milestone

My first milestone for this project was the connection of the LED matrix to the Arduino. I wrote two functions to light up certain rows of the matrix to a certain heights and colors. To the left is the fruit of these labors.

Code for 1st Milestone (Arduino)

#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(256, PIN, NEO_GRB + NEO_KHZ800);

int red[] = {

8, 7, 6, 5, 4, 3, 2, 1,
0, 8, 8, 7, 3, 5, 4, 4,
0, 1, 2, 3, 4, 5, 6, 7,
4, 8, 3, 7, 2, 6, 1, 5
};

void setup() {
  strip.begin();
  strip.show();
}

void loop() {
  for (uint16_t i = 0; i<32; i++) {
    red[i] = i % 8;
    clearRow(i);
    row(i, red[i]);
    strip.show();
    delay(10);
  }
  for (uint16_t i = 0; i<32; i++) {
    red[i] = i % 9;
    clearRow(i+1);
    rowc(i, red[i]);
    strip.show();
    delay(10);
  }
}

uint32_t vol[] = {
  strip.Color(0,48,4), 
  strip.Color(0,48,0), 
  strip.Color(16,48,0), 
  strip.Color(32,48,0), 
  strip.Color(48,48,0),
  strip.Color(48,32,0),
  strip.Color(48,8,0),
  strip.Color(48,0,0)
};

void clearRow(uint8_t num) {
  int num8 = num*8;
  for (uint16_t i = 0; i<8; i++) {
strip.setPixelColor(num8+i, strip.Color(0,0,0));
  }
}

void row(uint8_t num, uint8_t cap) {
  if (num % 2 == 0) {
    int num8 = num*8;
    for (uint16_t i = 0; i<cap; i++) {
      strip.setPixelColor(i+num8, vol[i]);
    }
  } else {
    int num8 = num * 8 + 7;
     for (uint16_t i = 0; i<cap; i++) {
      strip.setPixelColor(num8-i, vol[i]);
    }
  }
}

void rowc(uint8_t num, uint8_t cap) {
  if (num % 2 == 0) {
    int num8 = num*8;
    for (uint16_t i = 0; i<cap; i++) {
      strip.setPixelColor(i+num8, vol[cap]);
    }
  } else {
    int num8 = num * 8 + 7;
     for (uint16_t i = 0; i<cap; i++) {
      strip.setPixelColor(num8-i, vol[cap]);
    }
  }
}

breadboardforwebsite
FRITZING CIRCUIT DIAGRAM
arduino2

Start typing and press Enter to search

Bluestamp Engineering