// Musical Data Visualization // Justin M. Jeffers //This project was created to show the importance of lyric in song. As hip hop becomes more and more popular, the more I notice how the lyrical content is less focuced on. // So for this project I decided to create a processing sketch that populats the lyrics of the song while it is being played. Along with the lyrics, there is a visual interaction // between the line sketches, and the music. // Import minim library for sound import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.analysis.BeatDetect; float currTime = 0; float activateTime = 0; float [] activeArray = {9000,15000,21000,27000,32000,35000,38000,40200,44000,46300,51000,54000,57000,59000,62000,64000,67200,69000,72000,75000,78000, 80000,83000,87000,90500,94000,99000,104000,105000,108000,117000,179000,181000,183000,185000,187000,188000,189000,192000,194000,196000,199000,202000,205000,208000,209000,212000,214000,216000,220000, 222000,226000,247000,249500,249700}; int size = 22; float x = 100; float y = 0; float [] yvals = new float [54]; float [] speed = new float [54]; float gravity = 0.03; Minim minim; AudioPlayer player; AudioMetaData meta; BeatDetect beat; int timeSize; float sampleRate; int r = 200; float rad = 70; FFT fft; void setup() { size(displayWidth, displayHeight); //size(600, 400); minim = new Minim(this); player = minim.loadFile("Shipwrecked.wav"); meta = player.getMetaData(); beat = new BeatDetect(); player.play(); background(-1); noCursor(); fft = new FFT(player.bufferSize(), player.sampleRate()); for (int i=0; i<yvals.length; i++){ yvals[i] = 0.0; speed[i] = 0.0; } } void draw() { String lines [] = loadStrings("Sr.txt"); fft.forward(player.mix); beat.detect(player.mix); translate(width/2, 300); for(int i = 0; i < player.left.size() - 1; i++) { fill(100); ellipse((width/2)-20,displayHeight*1, displayWidth - 300 + (i+10), 250 + player.left.get(i+1)*200); } fill(99,191,174,90); if (beat.isOnset()) rad = rad*2; else rad = 50; ellipse(0, 0, 2*rad, 2*rad); stroke(99,191,174,50); if (beat.isOnset()) rad = rad*.9; else rad = 50; ellipse(0, 0, 8*rad, 8*rad); stroke(99,191,174,80); //Bsize measure Buffersize, and is used to adjust the size of sphere line sketch. int bsize = player.bufferSize(); for (int i = 0; i < bsize - 1; i+=5) { float x = (r)*cos(i*400*PI/bsize); float y = (r)*sin(i*400*PI/bsize); float x2 = (r + player.left.get(i)*900)*cos(i*2*PI/bsize); float y2 = (r + player.left.get(i)*900)*sin(i*2*PI/bsize); line(x, y, x2, y2); stroke(255,70); fill(21,115,98,90); } beginShape(); stroke(-1, 50); // Bsize is used here to adjust the other line sketches. for (int i = 0; i < bsize; i+=30) { float x2 = (r + player.left.get(i)*800)*cos(i*80*PI/bsize); float y2 = (r + player.left.get(i)*800)*sin(i*80*PI/bsize); vertex(x2, y2); pushStyle(); stroke(-1); strokeWeight(2); point(x2, y2); popStyle(); stroke(21,115,98,80); } endShape(); stroke(97,164,134,10); fill(220,238,242); textSize(size); textAlign(CENTER); // activate time starts timer at begining of sketch, and loop is used to determine when to drop each line of lyrics. All lines were set to a specific time in the "activeArray" above. activateTime = millis(); translate(0, -300); for(int p=0; p<yvals.length; p++){ if(activateTime > activeArray[p]){ yvals[p] += speed[p]; speed[p]+= gravity; text(lines[p],0,yvals[p]); } } } void showMeta() { int time = meta.length(); textSize(50); textAlign(CENTER); text( (int)(time/1000-millis()/1000)/60 + ":"+ (time/1000-millis()/1000)%60, -7, 21); } boolean flag =false; void mousePressed() { if (dist(mouseX, mouseY, width/2, height/2)<150) flag =!flag; } // boolean sketchFullScreen() { return true; }