Dani Delgado and Elena Deng – Final Project

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!

shape 1: ripples
shape 2: squares
shape 3: diamonds
shape 4: centroid

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!

Leave a Reply