click and hold mouse to show back album cover, click space bar to cycle through facts
xxxxxxxxxx
//Collaborators: Vinny Pirolli and Lia Cociorva
//Our project is an interactive music video experience. The main features of the piece include the Britney Spears "Everytime"
//music video itself playing on the screen along with an audio clip of the song, accompanied by lyrics that change size
//depending on the current volume output of the song.
//The piece also includes an animation of bouncing balls, meant to represent feelings of sadness and drifting/falling
//that Britney's song evokes (also seen in the blue color scheme).
//There are various interactive elements of the piece, including a compilation of facts about the song
//that the user can toggle through using the space bar, the ability to change the song's relative volume using the up and down arrow keys,
//as well as the album cover following the user's mouse, which changes to the back cover when the mouse is held down.
//Finally, the piece includes a real-time visualization of the song's audio frequencies. When the user changes the volume output
//of the song using the arrow keys, rather than by using the standard volume keys, they can see how the
//audio visualizations change depending on how the volume changes.
//The way we decided to split up the work was that Vinny would work on mostly the visual components, and
//Lia would work on mostly the audio components.
//Vinny wrote the code for the video display, the compilation of facts, the "Lyrics" tab that updates the lyrics,
//and the album cover interaction. Lia wrote the code for the frequency visualization, the lyrics size-changing feature
//and text fonts, and the volume changing interaction. The bouncing balls animation was inspired by the work of oofmstdve
//(https://openprocessing.org/sketch/1061787) and we both edited it to fit our vision. Enjoy!
//variables needed for bouncing ball animation
var balls = [];
var speed;
var ballSize;
var ballCount = 30;
var gInc=10;
var bInc=10;
//variables needed for video/image display and audio
var song;
var vid;
var albumFront;
var albumBack;
var vol = 0.5
//variables needed for facts compilation and lyrics text
var facts = ["Everytime by Britney Spears, released on November 12th, 2003","Certified Gold in 7 countries","Sold 500,000+ copies","From Britney's 4th album 'In the Zone'"];
var currentText = "";
var lyricFont;
var factsFont;
var index=0;
function preload(){
//load up the audio, video, and image files, as well as the text fonts
song = loadSound("everytime.mp3");
vid = createVideo('musicvideo.mov');
lyricFont = loadFont ('longskinny.ttf');
factsFont = loadFont ('arlrdbd.ttf');
albumFront = loadImage("itz.png");
albumBack = loadImage("backcover.jpg");
}
function setup() {
//display and video setup
createCanvas(windowWidth,windowHeight);
vid.volume(0);
vid.hide();
vid.loop();
textAlign(CENTER);
//song setup
song.setVolume(vol);
song.loop();
//setup frequency visualizer
fft = new p5.FFT();
//setup for volume-dependent font size
amplitude = new p5.Amplitude();
//setup for bouncing balls animation
for (let a = 0; a < ballCount; a++) {
speed = random(-1, 3); // random ball speeds
ballSize = random(50, 100); // random ball sizes
while (speed > -2 && speed < 2) {
speed = random(-1, 3); //prevents very slow speeds
}
balls[a] = new Ball(ballSize, speed); //creates new ball
}
}
function draw(){
background("skyblue");
image(vid,720,330); // displays music video
imageMode(CENTER);
image(albumFront,mouseX,mouseY,200,200); // displays album cover
if (mouseIsPressed === true) {
if (mouseButton === LEFT) {
image(albumBack, mouseX, mouseY, 220, 200); //switches image from front to back when mouse is pressed
}
}
//frequency graph along the bottom of screen composed of thin vertical rectangles
noStroke();
fill(0,0,255);
let spectrum = fft.analyze();
for (let i = 0; i < spectrum.length; i++){
let x = map(i, 0, spectrum.length, 0, width);
let h = -height + map(spectrum[i], 0, 255, height, 0);
rect(x, height, width / spectrum.length, h)
}
//dynamic line "wave" audio visualization formed using the shape feature
noFill();
stroke("darkBlue");
strokeWeight(3);
let waveform = fft.waveform();
beginShape();
for (let i = 0; i < waveform.length; i++){
let x = map(i, 0, waveform.length, 0, width);
let y = map( waveform[i], -1, 1, 0, height*1.5);
vertex(x,y);
}
endShape();
//creating text for song facts
push();
strokeWeight(3);
fill('lightCyan');
textSize(25);
textFont(factsFont);
text(facts[index], width/2, height/8);
pop();
//create and animate the bouncing balls
for (let b = 0; b < ballCount; b++) {
balls[b].create();
balls[b].move();
}
//creating lyrics and making their font size depend on audio amplitude
push();
updateText(); //calls function in other tab (Lyrics
let level = amplitude.getLevel();
let fontSize = map(level, 0, 1, 30, 400);
textFont(lyricFont);
textSize(fontSize);
stroke(0);
fill('lightCyan');
strokeWeight(3);
text(currentText, width/2,height/1.1);
pop();
}
function keyTyped() {
if (key === ' ') { //toggles through list of facts when space bar is pressed
index = index +1;
if (index == facts.length){ //recycles through list of facts when user reaches the end
index = 0;
}
}
}
function keyPressed(){
if (keyIsDown(UP_ARROW) == true && vol < 1) { //increases internal volume when up arrow pressed
song.setVolume(vol += 0.05)
}
else if (keyIsDown(DOWN_ARROW) == true && vol > 0.000000006) { //decreases internal volume when down arrow pressed
song.setVolume(vol -= 0.05)
}
}
class Ball {
constructor(w, sc) {
this.sx = sc;
this.sy = sc;
this.w = w;
this.x = (random(this.w / 2, width - (this.w / 2))); //sets random x and y position to start
this.y = (random(this.w / 2, height - (this.w / 2)));
this.r = 0; //no red value keeps the random colors all cool (greens and blues)
this.g = random(120, 200); //ensures that green value is high, but less than blue overall
this.b = random(150, 255); //ensures that blue value is high
}
create() {
fill(this.r, this.g, this.b); //sets color
stroke("darkBlue"); //outline
ellipse(this.x, this.y, this.w); //creates balls
}
move(){
this.x = this.x + this.sx; //moves x in positive direction
this.y = this.y + this.sy; //moves y in positive direction
if (this.x < this.w / 2) { //creates bounce illusion by changing direction
this.sx = -this.sx;
}
if (this.x > width - this.w / 2) {
this.sx = -this.sx;
}
if (this.y < this.w / 2) {
this.sy = -this.sy;
}
if (this.y > height - this.w / 2) {
this.sy = -this.sy;
}
}
}