Click to make music!
sketch/*
Elena Deng and Dani Delgado
Section E
edeng1 and ddelgad1
Final Project
*/
//variables to load sounds into
var ellipseSound;
var arcSound;
var squareSound;
var triSound;
var bgs;
//create the slider to control bg noise pan
var sliderPan;
//variables to inciment the bg
var volInc;
var pitchInc;
//stores the amount of mouse clicks
var mouseClick = 0;
//variables for the bg graphic based on amplitude
var amp;
var volhistory = [];
var objects = []; //sets the array for objects
var bright = 1; //sets the brightness of the screen+background
var xe = []; //sets the x pos array for the centroid
var ye = []; //sets the y pos array for the centroid
function preload() {
//load all of the sounds into the file
ellipseSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/ellipseDrip.mp3");
squareSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/bloopSquare.mp3");
arcSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/bong.mp3");
triSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/ding.mp3");
bgs = loadSound("https://courses.ideate.cmu.edu/15-104/f2018/wp-content/uploads/2018/12/whiteNoise.mp3");
}
function setup() {
createCanvas(640, 480);
frameRate(14);
angleMode(DEGREES);
//play bg sound
bgs.loop();
bgs.setVolume(1.5);
//get amplitude
amp = new p5.Amplitude();
//create pan slider
sliderPan = createSlider(-1, 1, 0, 0.01);
sliderPan.size(640, AUTO);
for (var i = 0; i < 7; i++) { //sets the centroid points
var t = map(i, 0, 7, 0, TWO_PI);
xe.push(width / 2 + 75 * cos(t));
ye.push(height / 2 + 75 * sin(t));
}
}
function draw() {
background(10, 10, bright); //everytime the mouse is pressed, background brightness increases/decreases
bright = bright - 5;
if (mouseIsPressed) {
bright = 110;
}
//pan slider
bgs.pan(sliderPan.value());
//get bgs amplitude and apply it the the graphic
//the graphic is made from a "begin and end shape" method
//and mapping of amps is made in a forloop
var vol = amp.getLevel();
volhistory.push(vol);
push();
frameRate(40);
translate(width / 2, height / 2);
//create the outer circle
beginShape();
strokeWeight(5);
stroke(20, 20, -bright, 80);
noFill();
for (var i = 0; i < 360; i++) {
var r = (map (volhistory[i], 0, 1, 10, 100)) * 18;
var x = r * cos(i);
var y = r * sin(i);
vertex(x, y);
}
endShape();
//create the inner circle
beginShape();
strokeWeight(0.5);
stroke(80, 80, -bright);
noFill();
for (var i = 0; i < 360; i++) {
var r = (map(volhistory[i], 0, 1, 10, 100)) * 17;
var x = r * cos(i);
var y = r * sin(i);
vertex(x, y);
}
endShape();
if (volhistory.length > 360) {
volhistory.splice(0, 1);
}
pop();
for (var i = 0; i < objects.length; i++) { //sets the order of the objects
if (objects[i].type == "circle") {
drawCir(objects[i]);
}
if (objects[i].type == "rect") {
drawRect(objects[i]);
}
if (objects[i].type == "tri") {
var change = random(0, 2)
drawTri(objects[i].x, objects[i].y, objects[i].s + change);
}
if (objects[i].type == "centroid") {
drawCentroid();
}
}
}
function mousePressed() {
//variables for sounds made to easily reset the mouse clicks
var firstSound = mouseClick < 10;
var secondSound = mouseClick >= 10 & mouseClick <= 20;
var thirdSound = mouseClick > 20 & mouseClick <= 30;
var fourthSound = mouseClick > 30 & mouseClick <= 40;
//images and sounds are based on mouse clicks
if (firstSound) {
//this code is to play the sounds
//only allows a sound effect to be triggered if it's not playing
//that way theres no overlap of sounds
if(!ellipseSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 5, 0.09);
pitchInc = map(mouseX, 0, 640, 0.25, 1.25);
ellipseSound.play();
ellipseSound.setVolume(volInc);
ellipseSound.rate(pitchInc);
}
//pan the sounds based on mouse click
//you'll hear it in every other ear every other click
if (mouseClick % 2) {
ellipseSound.pan(-1.0);
} else {
ellipseSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createCir(mouseX, mouseY)); //creates the circle for the first ten mouse clicks
}
if (secondSound) {
if(!squareSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 8, 1.5);
pitchInc = map(mouseX, 0, 640, 0.25, 1.75);
squareSound.play();
squareSound.setVolume(volInc);
squareSound.rate(pitchInc);
// if (mouseClick % 2){
// squareSound.pan(-1.0);
// } else {
// sqaureSound.pan(1.0);
// }
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createRect(mouseX, mouseY)); //creates the square/rect for the next ten mouse clicks
}
if (thirdSound) {
if(!triSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 7, 0.5);
pitchInc = map(mouseX, 0, 640, 0.5, 1.75);
triSound.play();
triSound.setVolume(volInc);
triSound.rate(pitchInc);
}
if (mouseClick % 2) {
triSound.pan(-1.0);
} else {
triSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
objects.push(createTri(mouseX, mouseY, random(1, 2))); //creates the diamond for the next ten mouse clicks
}
if (fourthSound) {
if(!arcSound.isPlaying()) {
volInc = map(mouseY, 0, 480, 8, 0.5);
pitchInc = map(mouseX, 0, 640, 0.25, 1.25);
arcSound.play();
arcSound.setVolume(volInc);
arcSound.rate(pitchInc);
}
if (mouseClick % 2) {
arcSound.pan(-1.0);
} else {
arcSound.pan(1.0);
}
if (objects.length >= 7) {
objects.shift();
}
xe.push(mouseX);
ye.push(mouseY);
objects.push(createCentroid()); //creates the centroid for the next ten mouse clicks
}
if (mouseClick > 40) {
mouseClick = firstSound; //mouseClicks resets the cycle
}
//increment the mouse clicks
mouseClick ++;
}
function createCir(bx,by) { //creates the circle
return {x:bx, y:by, type: "circle", oDiam: 0};
}
function drawCir(cir) { //draws the circle
for (var i = 0; i < 10; i++) {
var diam = cir.oDiam - 70 * i; //adjusts the drip spacing effect
if (diam > 0) {
var fade = map(diam, 0, width / 2, 100, 255); //sets the color
strokeWeight(map(diam, 0, width, 12, 1)); //stroke weight decreases as circle gets larger
stroke(fade, fade / 1.3, fade / 2, 85);
noFill();
ellipse(cir.x, cir.y, diam / 2); //draws ellipse
}
}
cir.oDiam = cir.oDiam + 2; //increases size of the circle
if (cir.oDiam > height / 2) { //once circle is larger than height/2 then the circle enlargement speed decreases
cir.oDiam -= 1.25;
}
}
function createRect(bx,by,bs) {
return {x:bx, y:by, s:bs, type: "rect", oRect: 210}
}
function drawRect(square) {
noStroke();
rectMode(CENTER);
for (var i = 0; i < 6; i++) {
var recta = square.oRect - 100 * i; //sets the frequency/size of squares
if (recta < 0) {
var fade = map(recta, 0, width / 2, 255, 180); //maps the color
strokeWeight(10)
stroke(fade, fade / 1.3, fade / 2); //sets the color fade
noFill();
rect(square.x, square.y, recta / 2, recta / 2); //draws the square
}
}
square.oRect = square.oRect - random(-2, -4); //shrinks square at random rates
}
function createTri(bx, by, bs) { //creates the diamond
return {x:bx, y:by, s:bs, type: "tri"}
}
function drawTri(bx, by, bs) { //draws the diamond
var smashorpass = random(-1, 10); //sets the random rate at which the shapes twinkle
var smashthenpass = random(-1, 5);
noStroke();
//draws the first diamond
fill(map(by, 0, height, 200, 255), map(by, 0, height, 120, 225), map(by, 0, height, 40, 85));
quad(bx - 10 + bs - smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by - 30 + bs - smashthenpass, bx + 10 + smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by + 30 + bs + smashthenpass);
strokeWeight(2); //draws the second diamond outline
stroke(255, 230, 215, 70);
noFill();
quad(bx - 15 + bs - smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by - 35 + bs - smashthenpass, bx + 15 + smashorpass, by + bs + random(-4, 4), bx + bs + random(-4, 4), by + 35 + bs + smashthenpass);
}
function createCentroid() { //creates the centroid
return {type: "centroid"};
}
function drawCentroid() { //draws the centroid
noStroke();
fill(map(ye, 0, height, 200, 255), map(ye, 0, height, 120, 225), map(ye, 0, height, 40, 85));
// moving the components of the centroid
var nPoints = xe.length;
for (var i = 0; i < nPoints; i++) {
xe[i] += (noise(i * 1 + millis() / 500.0) - .5) * 10;
ye[i] += (noise(i * 2 + millis() / 500.0) - .5) * 10;
ellipse(xe[i], ye[i], 30, 30);
}
// draw the dots on the outside
for (var i = 0; i < nPoints; i++) {
ellipse(xe[i], ye[i], 1, 1);
}
// finding the average of the dots (x,y)
var xAverage = 0;
var yAverage = 0;
for (var i = 0; i < nPoints; i++) {
xAverage += xe[i];
yAverage += ye[i];
}
xAverage /= nPoints;
yAverage /= nPoints;
// draws line from center to the points
strokeWeight(4);
stroke(255, 255, 255, 10);
for (var i = 0; i < nPoints; i++) {
line(xe[i], ye[i], xAverage, yAverage);
}
// Draw the centroid
stroke(0);
strokeWeight(2);
ellipse(xAverage, yAverage, 10, 10);
}
For our final project, we wanted to create a “digital instrument” which synthesizes user interaction, sound, and generative visuals. We decided to start with a simple background which not only contains a graphic that reacts to the amplitude of the played music, but also flashes brighter when the user clicks in. From there, we added different graphics and corresponding sound effects to increase visual and audio interest. These graphics all have unique movements and correlate to the sound, while the sound effects change based on the mouseX and mouse Y position. As the user clicks, they’ll explore a range of different sounds and shapes that are placed on a loop which resets after every 40 clicks. Also, as they click, the sounds’s panning will change with every other click (e.x. click once, sound effect will play in one ear and click again, it’ll play in the other).
Here are some screenshots of possible screens you would get by interacting with this project!
We really enjoyed working on this project and exploring how different sounds and visuals interact and affect one another! We had difficulty at the beginning decided on exactly what we wished to do, but once we got the ball rolling things started to fall into place!
Since this was a partner project, we divided up the work to make it manageable and easier to code (as two people working on one computer would be slow and painful on our friendship). So we split the work up into such parts:
Elena Deng created the objects and visuals.
Dani Delgado edited the sound effects and created the background graphic.
Together we worked on debugging the code and adding the intended effects.
We hope you click around and have fun!