Click the boxes to activate the notes and push play to start the song. Tutorial: https://youtu.be/67O3sK5Uq7o
xxxxxxxxxx
//instruments is an array that stores the actual rectangles that get drawn and clicked on
var instruments = [];
//maestro is the horizontal scrolling bar that trigger the sounds
var maestro;
//pos is a vector variable that stores mouseX & Y coordinates to determine when
//an instrument has been clicked on
var pos;
//k stores a loop that correlates to the 24 instrument Y coordinates
var k;
//sounds is an array that stores the reference names of each sound file used
var sounds = ["C1", "B1", "A1", "G1", "F1", "E1", "D1", "CO1", "C2", "B2", "A2", "G2", "F2", "E2", "D2", "C02", "DR1", "DR2", "DR3", "DR4", "DR5", "DR6", "DR7", "DR8"];
//files is an array that stores the actual file names of the sound files used
var files = ["PianoHiC.wav", "PianoHiB.wav", "PianoHiA.wav", "PianoHiG.wav", "PianoHiF.wav", "PianoHiE.wav", "PianoHiD.wav", "PianoHiOctaveC.wav", "PianoMiddleC.wav", "PianoMiddleB.wav", "PianoMiddleA.wav", "PianoMiddleG.wav", "PianoMiddleF.wav", "PianoMiddleE.wav", "PianoMiddleD.wav", "PianoMiddleOctaveC.wav", "Kick.wav", "ClosedHiHat.wav", "Snare.wav", "Crash.wav", "FloorTom.wav", "AltTom.wav", "HiTom.wav", "OpenHiHat.wav"];
var saved = [];
var loaded;
var soundsY;
var drums = [];
function preload() {
//this loop attaches a reference name to an actual file name for each sound file
//for example: C1 = loadSound("files/PianoHiC.wav") and so forth for every sound file
for (var s = 0; s < 24; s++) {
sounds[s] = loadSound(files[s]);
}
loadStrings("saved.txt", gotData);
myFont = loadFont('arial.ttf');
}
function setup() {
//a good usuable size for a canvas, but could be altered
createCanvas(950, 700);
//resetSketch is a function that creates the basics of the sketch
resetSketch();
//creates a reset button, to reset the sketch
var button = createButton("Reset");
button.size(width / 11, width / 11);
button.position(instruments[0].x - (instruments[0].r * 4), instruments[0].y - (instruments[0].r / 2));
button.mousePressed(resetSketch);
//creates a button that will start or stop the maestro and therefor start or stop
//playing the sound files
var play = createButton("Play/Stop");
play.size(width / 11, width / 11);
play.position(instruments[0].x - (instruments[0].r * 4), instruments[131].y);
play.mousePressed(Play);
//view your saved composition in the AgentSonosP5 folder
var saver = createButton("Save");
saver.size(width / 11, width / 11);
saver.position(instruments[0].x - (instruments[0].r * 4), instruments[223].y + (instruments[0].r / 2));
saver.mousePressed(saves);
var loader = createButton("Load");
loader.size(width / 11, width / 11);
loader.position(instruments[0].x - (instruments[0].r * 4), instruments[315].y + instruments[0].r);
loader.mousePressed(load);
}
function resetSketch() {
//the function associated with the reset button
//below are two loops; one that addresses horizontal arrays of instruments and
//one that addresses verticles arrays of instruments
//t stores the instrument index number
var t = 0;
for (var j = 0; j < 25; j++) {
for (var i = 0; i < 33; i++) {
instruments[t++] = new Instrument(i * 25 + 100, j * 25 + 37.5);
}
}
//create the maestro upon setup
maestro = new Maestro(instruments[1].x - (instruments[0].r / 2), 0);
for (var p = 0; p < 8; p++) {
drums[p] = new Drum();
}
}
function Play() {
//the function associated with the play/stop button
if (maestro.play === false) {
maestro.play = true;
} else if (maestro.play === true) {
maestro.play = false;
}
}
function saves() {
for (var i = 0; i < instruments.length; i++) {
if (instruments[i].active === true) {
append(saved, i);
}
}
saveStrings(saved, 'saved.txt');
console.log(saved);
loadStrings("saved.txt", gotData);
}
function gotData(data) {
loaded = data;
}
function load() {
resetSketch();
var soundsY = [instruments[33].y, instruments[66].y, instruments[99].y, instruments[132].y, instruments[165].y, instruments[198].y, instruments[231].y, instruments[264].y, instruments[297].y, instruments[330].y, instruments[363].y, instruments[396].y, instruments[429].y, instruments[462].y, instruments[495].y, instruments[528].y, instruments[561].y, instruments[594].y, instruments[627].y, instruments[660].y, instruments[693].y, instruments[726].y, instruments[759].y, instruments[792].y];
//a loop that associates with the instruments y coordinates via soundsY[]
for (var t = 0; t < 24; t++) {
//k stores a loop that correlates to the 24 instrument Y coordinates
k = t;
for (var i = 0; i < loaded.length; i++) {
if (instruments[loaded[i]].active === false && instruments[loaded[i]].y == soundsY[k]) {
instruments[loaded[i]].clicked();
}
}
}
}
function draw() {
background(51);
//a loop to draw all the instruments as rectangles
for (var i = 0; i < instruments.length; i++) {
//show, draws the instruments
instruments[i].show();
if (i < 33 || i % 33 === 0) {
//sets the colour of the top row and the left column of instruments
instruments[i].barcount();
}
}
for (var p = 0; p < drums.length; p++) {
drums[p].show();}
//a maestro function that wraps the maestro around the sketch
maestro.border();
//a maestro function that moves the maestro
maestro.move();
//a function that plays soundfiles based on y coordinates & the instrument being active
sound();
//a function that create labels for the notes and the beat
labels();
//a maestro funtion that draws the maestro
maestro.display();
}
function sound() {
//two loops that link a different sound file to each different group of y coordinates
//soundsY is an array that stores the Y coordinate of each row of instruments
var soundsY = [instruments[33].y, instruments[66].y, instruments[99].y, instruments[132].y, instruments[165].y, instruments[198].y, instruments[231].y, instruments[264].y, instruments[297].y, instruments[330].y, instruments[363].y, instruments[396].y, instruments[429].y, instruments[462].y, instruments[495].y, instruments[528].y, instruments[561].y, instruments[594].y, instruments[627].y, instruments[660].y, instruments[693].y, instruments[726].y, instruments[759].y, instruments[792].y];
for (var i = 0; i < instruments.length; i++) {
for (var t = 0; t < 24; t++) {
//k stores a loop that correlates to the 24 instrument Y coordinates
k = t;
//if the instrument is active (has been clicked) play the cooresponding sound file
if (maestro.x == instruments[i].x + 0.5 && instruments[i].y == soundsY[t] && instruments[i].active === true || maestro.x == instruments[i].x + 1.5 && instruments[i].y == soundsY[t] && instruments[i].active === true) {
sounds[t].play();
}
}
}
}
function Drum() {
this.show = function(){
stroke(0);
fill(255);
textFont(myFont, [15]);
//textSize(12);
textAlign(LEFT);
var soundname = ["Kick", "ClosedHiHat", "Snare", "Crash", "FloorTom", "AltTom", "HiTom", "OpenHiHat"];
var soundsY = [instruments[561].y, instruments[594].y, instruments[627].y, instruments[660].y, instruments[693].y, instruments[726].y, instruments[759].y, instruments[792].y];
for (i = 0; i < soundname.length; i++){
text(soundname[i], 0, soundsY[i] + 5);
}
}
}
function labels() {
//beats is an array that stores the beat labels
var beats = ["0", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4", "1", "2", "3", "4"];
//notes is an array that stores the note labels
var notes = ["C", "B", "A", "G", "F", "E", "D", "C", "C", "B", "A", "G", "F", "E", "D", "C", "C", "B", "A", "G", "F", "E", "D", "C"];
//notesY is an array that stores the Y coordinate of each row of instruments
var notesY = [instruments[33].y, instruments[66].y, instruments[99].y, instruments[132].y, instruments[165].y, instruments[198].y, instruments[231].y, instruments[264].y, instruments[297].y, instruments[330].y, instruments[363].y, instruments[396].y, instruments[429].y, instruments[462].y, instruments[495].y, instruments[528].y, instruments[561].y, instruments[594].y, instruments[627].y, instruments[660].y, instruments[693].y, instruments[726].y, instruments[759].y, instruments[792].y];
//a loop to draw the vertical note labels
for (var n = 0; n < 24; n++) {
stroke(0);
fill(255);
textAlign(CENTER);
text(notes[n], instruments[0].x, notesY[n] + (instruments[0].r / 4));
}
//a loop to draw the horiztonal beat labels
for (var b = 1; b < 33; b++) {
stroke(0);
fill(255);
textAlign(CENTER);
text(beats[b], instruments[b].x, instruments[0].y + (instruments[0].r / 4));
}
}
function mouseClicked() {
//a loop through every instrument to determine when the mouse intersects an instrument
for (var i = 0; i < instruments.length; i++) {
//if mouseX&Y intersects an instrument
if (instruments[i].intersects(pos)) {
// console.log("x = " + instruments[i].x);
// console.log("y = " + instruments[i].y);
// console.log(i);
}
//soundsY is an array that stores the Y coordinate of each row of instruments
var soundsY = [instruments[33].y, instruments[66].y, instruments[99].y, instruments[132].y, instruments[165].y, instruments[198].y, instruments[231].y, instruments[264].y, instruments[297].y, instruments[330].y, instruments[363].y, instruments[396].y, instruments[429].y, instruments[462].y, instruments[495].y, instruments[528].y, instruments[561].y, instruments[594].y, instruments[627].y, instruments[660].y, instruments[693].y, instruments[726].y, instruments[759].y, instruments[792].y];
//a loop that associates with the instruments y coordinates via soundsY[]
for (var t = 0; t < 24; t++) {
//k stores a loop that correlates to the 24 instrument Y coordinates
k = t;
//if the instrument is black and is clicked then change colour
if (instruments[i].intersects(pos) && instruments[i].active === false && instruments[i].y == soundsY[t]) {
instruments[i].clicked();
//if the instrument is coloured and is clicked then change to black
} else if (instruments[i].intersects(pos) && instruments[i].active === true && instruments[i].y == soundsY[t]) {
instruments[i].reclicked();
}
}
}
}
//the functions of the maestro
function Maestro(x, y) {
//maestro variables
this.x = x;
this.y = y;
this.play = false;
this.move = function() {
//if maestro is moving and the play/stop button is clicked then stop moving
//and move maestro back to the start
if (this.play === false) {
this.x = instruments[1].x - (instruments[0].r / 2);
}
//if maestro is not playing and the play/stop button is clicked then start moving
else if (this.play === true) {
this.x += 2;
}
}
this.border = function() {
//if the maestro goes offscreen then return to the start
if (this.x > instruments[32].x + (instruments[0].r / 2)) {
this.x = instruments[1].x - (instruments[0].r / 2);
}
}
this.intersects = function() {
//a loop to run through all the instruments
for (var i = 0; i < instruments.length; i++) {
//var d is the distance between instruments and the maestro
var d = dist(this.x, this.y - height / 2, instruments[i].x, instruments[i].y);
//if the distances is less than the diameter of an instrument then it intersects
if (d < instruments[i].r) {
return true;
} else {
return false;
}
}
}
this.display = function() {
//draws the maestro
strokeWeight(3);
stroke(255);
fill(255);
line(this.x, this.y, this.x, this.y + (26 * 25));
}
}
//the functions of the instruments
function Instrument(x, y) {
//instrument variables
this.x = x;
this.y = y;
this.r = 25;
this.col = color(0, 0, 0);
this.active = false;
this.show = function() {
//draws the instruments
strokeWeight(1);
rectMode(CENTER);
fill(this.col);
rect(this.x, this.y, this.r, this.r);
stroke(255);
}
this.intersects = function() {
//pos is a vector variable that stores mouseX & Y coordinates to determine when
//an instrument has been clicked on
pos = createVector(mouseX, mouseY);
// var d is the distance between instruments and the mouse cursor
var d = dist(this.x, this.y, mouseX, mouseY);
//if the distances is less than the radius of an instrument then it intersects
if (d < this.r - (this.r / 2)) {
return true;
} else {
return false;
}
}
this.clicked = function() {
//this function sets the colour of an instrument once it has been clicked on
//var colours = [color(250, 104, 0), color(240, 163, 10), color(227, 200, 0), color(130, 90, 44), color(244, 114, 208), color(216, 0, 115), color(162, 0, 37), color(229, 20, 0), color(250, 104, 0), color(240, 163, 10), color(227, 200, 0), color(130, 90, 44), color(244, 114, 208), color(216, 0, 115), color(162, 0, 37), color(229, 20, 0), color(250, 104, 0), color(240, 163, 10), color(227, 200, 0), color(130, 90, 44), color(244, 114, 208), color(216, 0, 115), color(162, 0, 37), color(229, 20, 0)];
//colours is an array that stores 8 predetermine colours to establish patterns
var colours = [color(255, 0, 77), color(255, 163, 0), color(255, 236, 39), color(0, 228, 54), color(41, 173, 255), color(131, 118, 156), color(255, 119, 168), color(255, 204, 170), color(255, 0, 77), color(255, 163, 0), color(255, 236, 39), color(0, 228, 54), color(41, 173, 255), color(131, 118, 156), color(255, 119, 168), color(255, 204, 170), color(255, 0, 77), color(255, 163, 0), color(255, 236, 39), color(0, 228, 54), color(41, 173, 255), color(131, 118, 156), color(255, 119, 168), color(255, 204, 170)];
// red, orange, yellow, green, blue, indigo, pink, peach
//k stores the instruments Y coordinates, giving a different colour to each row
this.col = colours[k];
//if clicked the instrument becomes coloured and is considered active
this.active = true;
}
this.reclicked = function() {
//this function sets the colour of an instrument once it has been clicked off
//below isthe colour black
this.col = color(0, 0, 0);
//if clicked the instrument turns black and is considered inactive
this.active = false;
}
this.barcount = function() {
//sets the colour of the instruments used strictly as labels
this.col = color(101);
}
}