# Sara Frankel – Final Project

``````// Sara Frankel
// Final Project
// sfrankel
// Section A

var liftYourself;
var shostyTen;
var liftArray;
var fft;
var greatestWave;
var isPlaying;
var greatestOverall = 0;
var isLiftYourself;

}

function setup(){
var cnv = createCanvas(400, 400);
cnv.mouseClicked(togglePlay); //plays the canvas when clicked
fft = new p5.FFT();
liftYourself.amp(0.2);
shostyTen.amp(1);
isPlaying = false;
isLiftYourself = true;
}

function draw(){
background(0);
var spectrum = fft.analyze(); //uses FFT to use the "spectrum" of sound (i.e. the eyebrows)
var waveform = fft.waveform(); //uses FFT to use the waveform of the sound (i.e. the squiggled hair)
noStroke();

//draw variable to keep track of the greatest wave to give the "pulse" effect
greatestWave = 0;
for (i = 0; i < waveform.length; i++) {
if(waveform[i] > greatestWave) {
greatestWave = waveform[i];
}
}
//takes greatest overal wave value and stores it as greatest wave
if(greatestWave > greatestOverall){
greatestOverall = greatestWave;
}

//uses map use the value of the greatest wave of the sound and put it on a scale for color
fill(map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 0, 0));

//draws the "hair" of the eyebrow when turned on
//left eyebrow
for (var i = 0; i < spectrum.length; i++){
var x = map(i, 0, spectrum.length, 0, width / 3); //maps i on the length of the spectrum variable
var h = -height + map(spectrum[i], 0, 255, height, 0); //maps position in the spectrum array to allow height
rect(x + width * 0.75 - 50, height / 4 + 35, width / spectrum.length, h / 4);
}
//right eyebrow
for (var i = 0; i < spectrum.length; i++){
var x = map(i, 0, spectrum.length, width / 3, 0);
var h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x + 15, height / 4 + 20, width / spectrum.length, h / 4);
}

//draws base of eyebrows
stroke(255);
line(width / 4, height / 4 + 20, width / 4 + 50, height / 4 + 20);
line(width * 0.75 - 50, height / 4 + 35, width * 0.75, height / 4 + 35);

noFill();
//draw eyeballs
var y = map(greatestWave, -1, 1, 0, height); //allows for the eyes and head to pulse
ellipse(width / 4 + 20, height / 4 + 60, y / 3, y / 3);
ellipse(width * 0.75 - 20, height * 0.25 + 60, y / 6, y / 6);
ellipse(width / 2, height / 2, y * 1.5, y * 1.5);

//calls that if the audio is playing, the color of hair and eyes change to the music
if(isPlaying) {
fill(map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 255, 0));
stroke(map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 255, 0));
} else {
noFill();
stroke(255);
}

//uses drawHairAtAngle function to draw the hair on the head that follows the pulse of the head (stays in spot with music)
drawHairAtAngle(-14 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-12 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-10 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-8 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-6 * PI / 18, y * 0.75, waveform);
drawHairAtAngle(-4 * PI / 18, y * 0.75, waveform);

//allows eyes to follow mouse, drawing eyeballs
var eX = map(mouseX, 0, y, -1, 1);
var eY = map(mouseY, 0, y, -1, 1);
ellipse(eX + width / 4 + 20, eY + height / 4 + 60, 40, 40);
ellipse(eX / 2 + width * 0.75 - 20, eY / 2 + height * 0.25 + 60, 20, 20);

//states that if playing, the color of the mouth and eyebrows change color
if(isPlaying) {
stroke(map(greatestWave, 0, greatestOverall, 255, 0), map(greatestWave, 0, greatestOverall, 0, 255), map(greatestWave, 0, greatestOverall, 0, 0));
} else {
stroke(255);
}

//draws mouth
for (var i = 0; i < waveform.length; i++){
var x = map(i, 0, waveform.length, width/4, width * 0.75);
var y = map(waveform[i], -1, 1, 0, height);
line(width / 2, y + 50, x, height / 2 + 50);
}

//displays instructions of the canvas and which song is playing
stroke(255);
noFill();
text('Click to play or pause - Press space to change song', 60, 15);
if(isLiftYourself) {
text("Kanye West - Lift Yourself", width - 150, height - 10);
} else {
text('Dmitri Shostakovich - Symphony No. 10 Second Movement', width - 360, height - 10);
}
}

// fade liftYourself if mouse is over canvas
function togglePlay() {
//if statement that allows for each song to play and not overlap another and still alows for the click to play/stop to work
if(isLiftYourself){
if (liftYourself.isPlaying()) {
liftYourself.pause();
isPlaying = false;
} else {
shostyTen.pause();
liftYourself.loop();
isPlaying = true;
}
} else {
if (shostyTen.isPlaying()) {
shostyTen.pause();
isPlaying = false;
} else {
liftYourself.pause();
shostyTen.loop();
isPlaying = true;
}
}
}

//object that helps to draw the hair along the head
function drawHairAtAngle(angle, rad, waveform) {
beginShape();
for (var i = 0; i < waveform.length; i++) {
//uses map to place the hairs along the radius of the circle evenly spaced
var hairY = map(i, 0, waveform.length, sin(angle) * rad + height / 2, sin(angle) * (rad) + height / 2 - 25);
var hairX = map(waveform[i], -0.5, 0.5, cos(angle) * (rad - 25) + width / 2, cos(angle) * (rad + 25) + width / 2);
vertex(hairX, hairY);
}
endShape();
}

//function to switch songs if space bar is clicked
function keyTyped() {
if(key === ' ') {
isLiftYourself = !isLiftYourself;
togglePlay();
}
}

``````

For this project, I decided to visualize music. My first vision at this project was something more abstract, but as I was creating the project I felt it to be more fun to have a face. This face visualizes music in the sense that all aspects of it “dance” to the music. The eyebrows raise, the hair squiggles, and the mouth draws lines to give the effect of singing. What I wanted to prove in this project is that not only is Kanye West “boppable” to, but so can classical music. The image posted below is a screen shot taken from the Shostakovich.

The instructions for this project are:
To play click the canvas
To change the song click space
To dance along (with the eyes) move the mouse!

Hope you enjoy!

if code does not work correctly, here is the zip.file for it!