LED Sound Instrument
Physical Computing Midterm Project
SVA Interaction Design MFA
Aastha Bhargava, Effy Zhang, and Mikey Chen
For our mid term project my partners Mikey, Effy and I decided to play around with sound and light applying the fundamentals of physical computing. We created a lighting instrument which displayed different colours based on sound input from an external source.
During the three weeks we spent working on this project, we tested various LED strips and sound sensors to use for this project (ultimately we used Processing for sound input ). We also learned of FFT (Fast Fourier Transform) which is an algorithm used to convert time to frequency – something we required to make the instrument light up in sync with the music’s beat.
We faced a lot of challenges in the duration of this project both with the code and the model.
The initial model we built for the instrument had a tiny holes for the LEDs instead of the slits we later designed. Although the former ensured consistency with the placement of the LEDs, we miscalculated leaving room for all the wires when we brought the individual parts together.
Overview
Computer microphone senses music played from an external source and sends data to Processing
Processing FFT library analysis this data and modifies the same to be readable for Arduino
Arduino receives the data from Processing, analysis the data distribution, sets range, color, time and then sends these values to the addressable LED strip
The code is then uploaded to the LED strip.
Materials Used:
Sound sensor : Our computer’s microphone
Arduino Board : Arduino Leonardo
LED : WS2812B NeoPixel RGB LED Weather Proof Strip (addressable LED strip)
Plastic
Paper
Wire
Breadboard
5V Power Source
Code:
For Processing:
//3D Spectrogram with Microphone Input //Modified by kylejanzen 2011 - http://kylejanzen.wordpress.com //Based on script wwritten by John Locke 2011 - http://gracefulspoon.com //Output .DXF file at any time by pressing “r” on the keyboard import processing.serial.*; import processing.dxf.*; import ddf.minim.analysis.*; import ddf.minim.*; FFT fftLin; FFT fftLog; Waveform audio3D; Minim minim; AudioInput microphone; Serial myPort; float val; boolean record; PFont font; float jitter; float camzoom; float maxX = 0;float maxY = 0;float maxZ = 0; float minX = 0;float minY = 0;float minZ = 0; void setup() { size(1250,750,P3D); //screen proportions String portName = Serial.list()[1]; myPort = new Serial(this, portName, 9600); noStroke(); minim = new Minim(this); microphone = minim.getLineIn(Minim.STEREO, 4096); //repeat the song background(255); fftLog = new FFT(microphone.bufferSize(),microphone.sampleRate()); fftLog.logAverages(1,2); //adjust numbers to adjust spacing; float w = float (width/fftLog.avgSize()); float x = w; float y = 0; float z = 50; float radius = 10; audio3D = new Waveform(x,y,z,radius); } void draw() { background(0); directionalLight(126,126,126,sin(radians(frameCount)),cos(radians(frameCount)),1); ambientLight(102,102,102); if (frameCount>200) { for(int i = 0; i < fftLog.avgSize(); i++){ float zoom = 1; jitter = (fftLog.getAvg(i)*2); PVector foc = new PVector(audio3D.x+jitter, audio3D.y+jitter, 0); PVector cam = new PVector(zoom, zoom, -zoom); camera(foc.x+cam.x+50,foc.y+cam.y+50,foc.z+cam.z,foc.x,foc.y,foc.z,0,0,1); // int tempJ = round(jitter*500); // println(“rounded ->”+ tempJ); // myPort.write(tempJ); } int tempJ = round(jitter*5000); println(tempJ); myPort.write(tempJ); } //play the song fftLog.forward(microphone.mix); audio3D.update(); audio3D.textdraw(); if(record) { beginRaw(DXF, “output.dxf”); } audio3D.plotTrace(); if(record) { endRaw(); record = false; println(“hello,world!”); } } void stop() { // always close Minim audio classes when you finish with them microphone.close(); // always stop Minim before exiting minim.stop(); super.stop(); } class Waveform { float x,y,z; float radius; PVector[] pts = new PVector[fftLog.avgSize()]; PVector[] trace = new PVector[0]; Waveform(float incomingX, float incomingY, float incomingZ, float incomingRadius) { x = incomingX; y = incomingY; z = incomingZ; radius = incomingRadius; } void update() { plot(); } void plot() { for(int i = 0; i < fftLog.avgSize(); i++) { int w = int(width/fftLog.avgSize()); x = i*w; y = frameCount*5; z = height/4-fftLog.getAvg(i)*4; //change multiplier to reduces height default ‘10’ stroke(0); point(x, y, z); pts[i] = new PVector(x, y, z); //increase size of array trace by length+1 trace = (PVector[]) expand(trace, trace.length+1); //always get the next to last trace[trace.length-1] = new PVector(pts[i].x, pts[i].y, pts[i].z); } } void textdraw() { for(int i =0; i<fftLog.avgSize(); i++){ pushMatrix(); translate(pts[i].x, pts[i].y, pts[i].z); rotateY(PI/2); rotateZ(PI/2); fill(255,200); text(round(fftLog.getAvg(i)*100),0,0,0); popMatrix(); } } void plotTrace() { stroke(255,80); int inc = fftLog.avgSize(); for(int i=1; i<trace.length-inc; i++) { if(i%inc != 0) { beginShape(TRIANGLE_STRIP); float value = (trace[i].z*100); float m = map(value, -500, 20000, 0, 255); fill(m*2, 125, -m*2, 140); vertex(trace[i].x, trace[i].y, trace[i].z); vertex(trace[i-1].x, trace[i-1].y, trace[i-1].z); vertex(trace[i+inc].x, trace[i+inc].y, trace[i+inc].z); vertex(trace[i-1+inc].x, trace[i-1+inc].y, trace[i-1+inc].z); endShape(CLOSE); } } } }
For Arduino:
#include <Adafruit_NeoPixel.h> #define PIN 6 Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800); // Parameter 1 = number of pixels in strip shown as 60. Parameter 2 = pin number defined above as 6 char val;// Data received from the serial port int b; void setup() { strip.begin(); strip.show(); // Initialize all pixels to ‘off’ Serial.begin(9600); } void loop() { if (Serial.available()) { // If data is available to read, val = Serial.read(); // read it and store it in val b=val; } if (b< 20) { for (int i=0; i <= 20; i++){ strip.setPixelColor(i,0,0,0); strip.show(); } delay (5); } if (b> 20) { for (int i=0; i <= 20;i++){ //Blink up if (i%2==0){ strip.setPixelColor(i,249,4,86); // Shorcking pink strip.show();} } delay (15); for (int i=0; i <= 20;i++){ //Blink off strip.setPixelColor( i,0,0,0); // p1 strip.show(); } delay (15); } if(b> 30) { for (int i=0; i <= 20;i++){ if (i%2==1){ strip.setPixelColor( i,161,0,205); // purple strip.show();} } delay (15); for (int i=0; i <= 20;i++){ //Blink off strip.setPixelColor( i,0,0,0); // p1 strip.show(); } delay (15); } if(b> 60) { for (int i=0; i <= 5;i++){ strip.setPixelColor(i,0,0,0); // Teal strip.show();} for (int i=6; i <= 15;i++){ strip.setPixelColor(i,4,180,183); // Teal strip.show();} delay (50); for (int i=16; i <= 20;i++){ strip.setPixelColor(i,0,0,0); // Teal strip.show();} delay (15); } if(b> 100) { for (int i=0; i <= 5;i++){ strip.setPixelColor(i,4,180,183); //blue strip.show();} for (int i=6; i <= 15;i++){ strip.setPixelColor(i,89,211,122); //green strip.show();} for (int i=16; i <= 20;i++){ strip.setPixelColor(i,4,180,183); //blue strip.show();} delay (100); } }
Leave a Reply