xxxxxxxxxx
320
let hh, clap, bass; //instrument will serve as a container that holds the sound source
let hhPat, cPat, bPat; // instrument pattern: an array of number that can be manipulated to make beats (0/1)
let hhPhrase, cPhrase, bPhrase; //instrument phrase: define how instrument is interpreted( what 0 and 1 will correspond to)
let drums; //part. will attach the phrase to the part which will serve as our transport to drive the phrase
let beatLength; // The number of beats = 16 = 4/4
let bpmCTRL; // bpm slider element
let playHeadCount; // array from 1-16 to keep count of the playhead
function preload() {
drumparts = loadImage("drumparts.png");
// image for the key/legend of the 3 drum sounds
}
function setup() {
createCanvas(520, 220);
beatLength = 16;
// loading the sound in setup using callback function argument
hh = loadSound("samples/hh_sample.mp3", () => {});
clap = loadSound("samples/clap_sample.mp3", () => {});
bass = loadSound("samples/bass_sample.mp3", () => {});
//mixing sound levels of the drum sounds
hh.amp(0.6);
bass.amp(0.5);
clap.amp(0.4);
//pattern array of the beat
hhPat = [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1];
cPat = [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1];
bPat = [1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0];
// playhead count array hard-coded
playHeadCount = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
// phrase function which interprets the above pattern
phraseZ();
//initializing drum p5 Part function
drums = new p5.Part();
//attaching all the phrases to the drum parts
drums.addPhrase(hhPhrase);
drums.addPhrase(cPhrase);
drums.addPhrase(bPhrase);
// attaching playheadcount in the sequence function by adding this phrase
drums.addPhrase("seq", sequence, playHeadCount);
// creates the initial matrix
drawMatrix();
// first scene/mouseclicked to switch to 2nd scene
drawScene1();
mouseClicked();
}
// play/pause loop of the beat with spacebar
function keyPressed() {
if (key == ' ' ) {
if (hh.isLoaded() && clap.isLoaded() && bass.isLoaded()) {
if (!drums.isPlaying) {
drums.loop();
} else {
drums.stop();
}
} else {
console.log("let drums load");
}
}
}
// determines whether a beat/note is played when mouse is clicked on the grid
function mousePressed() {
// let rowClicked = floor(3*mouseY/height)
let rowClicked = floor((3 * (mouseY - 50)) / (height - 135));
// let indexClicked = floor (16*mouseX/width)
let indexClicked = floor((16 * (mouseX - 50)) / (width - 100));
if (rowClicked === 0) {
console.log("1st row" + indexClicked);
hhPat[indexClicked] = +!hhPat[indexClicked];
}
if (rowClicked === 1) {
console.log("2nd row");
cPat[indexClicked] = +!cPat[indexClicked];
}
if (rowClicked === 2) {
console.log("3rd row");
bPat[indexClicked] = +!bPat[indexClicked];
}
// updates the matrix with shapes added/removed
drawMatrix();
}
//creates grid
function drawMatrix() {
background(80);
image(drumparts, 445, 138, 27, 67.5);
push();
textFont("Helvetica");
noStroke();
fill("rgb(165,165,165)");
textSize(17);
text("BPM CONTROL", 52, 186);
// textSize(35);
// text("4", 20, 85);
// text("4", 20, 119);
// legend/key
translate(1, 1);
textSize(10);
text("HI HAT ", 408, 152.7);
text("CLAP ", 414, 172.9);
text("BASS ", 413, 194.7);
pop();
stroke("gray");
strokeWeight(2);
// Creating the grid and dividing it into 4 bars by using for loops
// vertical lines
for (let i = 0; i < beatLength + 1; i++) {
stroke("rgb(123,123,123)");
line(50 + (i * 420) / beatLength, 51, 50 + (i * 420) / beatLength, 129);
}
// horizontal lines
for (let i = 0; i < 4; i++) {
if (i == 0 || i == 3) {
stroke("rgb(53,53,53)");
} else {
stroke("rgb(123,123,123)");
}
line(50, 50 + (i * 80) / 3, 470, 50 + (i * 80) / 3);
}
// bar divider lines
for (let i = 0; i < beatLength + 1; i++) {
if (i == 0 || i == 4 || i == 8 || i == 12 || i == 16) {
stroke("rgb(53,53,53)");
line(50 + (i * 420) / beatLength, 50, 50 + (i * 420) / beatLength, 130);
}
}
// Initializing Shapes
stroke("gray");
strokeWeight(1);
// Hihat Shape
for (let i = 0; i < beatLength; i++) {
let xPnt = 50 + (i * 420) / beatLength + (0.5 * 420) / beatLength;
let yPnt = 50 + 80 / 6;
if (hhPat[i] === 1) {
triangle(xPnt, yPnt - 5, xPnt + 5.45, yPnt + 5, xPnt - 5.45, yPnt + 5);
}
// Clap Shape
if (cPat[i] === 1) {
rectMode(CENTER);
rect(xPnt, yPnt + 27.5, 9.3, 9.3);
}
// Bass Shape
if (bPat[i] === 1) {
ellipse(xPnt, 50 + (80 * 5) / 6, 10.4);
}
}
}
// Playhead Counter and drawing Playhead/Live Count
function sequence(time, beatIndex) {
drawMatrix();
push();
rectMode(CORNER);
let xPnt = 50 + (beatIndex - 1) * (420 / beatLength);
console.log(beatIndex);
// playHead drawn
strokeWeight(2);
stroke("#250356");
fill(41, 0, 100, 100);
triangle(12.5 + xPnt + 5.95, 30, 12.5 + xPnt, 42, 12.5 + xPnt - 5.95, 30);
stroke("#250356");
strokeWeight(2);
fill(41, 0, 100, 100);
rect(50 + (beatIndex - 1) * (420 / beatLength), 50, 420 / beatLength, 80);
pop();
}
// Creating Shuffle Button
function shuffleButton() {
button = createButton("SHUFFLE BEAT");
button.position(203, 153);
button.mousePressed(shuffleIt);
}
// Using shuffle function to shuffle the array to create a new beat
function shuffleIt() {
shuffle(hhPat, true);
shuffle(cPat, true);
shuffle(bPat, true);
print(hhPat);
drawMatrix();
}
// Initializing all the phrases
function phraseZ() {
hhPhrase = new p5.Phrase(
"hh",
(time) => {
hh.play(time);
},
hhPat
);
cPhrase = new p5.Phrase(
"clap",
(time) => {
clap.play(time);
},
cPat
);
bPhrase = new p5.Phrase(
"bass",
(time) => {
bass.play(time);
},
bPat
);
}
// Creating the first scene for the drum machine
var drawScene1 = function () {
currentScene = 1;
background(90);
push();
translate(-33, -57);
stroke(0);
strokeWeight(1);
textSize(70);
text("BOOGIE BOX", 40, 120);
strokeWeight(0.7);
textSize(20);
text("A DRUM PAD SIMULATION.", 45, 150);
pop();
stroke(0);
strokeWeight(0.6);
textSize(10);
text("CLICK ANYWHERE ON THE SCREEN TO BEGIN", 285, 210);
};
// Function to change the scene from the intro page to the drum pad
function mouseClicked() {
mouse = true;
if (currentScene === 1) {
currentScene = 2;
} else if (currentScene === 2) {
// for some reason DOM elements such as sliders and button only worked with changing scenes if they appeared after mouseclick, otherwise they show in the previous page as well
bpmCTRL = createSlider(30, 155, 90, 1);
bpmCTRL.position(50, 156);
bpmCTRL.input(() => {
drums.setBPM(bpmCTRL.value());
});
bpmCTRL.addClass("mySliders");
drums.setBPM("90");
shuffleButton();
push();
fill(37, 3, 86, 240);
rectMode(CENTER);
rect(width / 2, height / 3 + 18, 280, 110);
circle(400, 38, 18);
pop();
push();
stroke("gray");
strokeWeight(0.5);
fill("gray");
textSize(16);
text("SPACEBAR = Play/Pause", 130, 63);
text("Click on the grid to create your own ", 130, 98);
text("drum beat. ", 130, 123);
text("i", 398.2, 43.6);
pop();
currentScene = 3;
}
console.log("Scene #" + currentScene);
}