xxxxxxxxxx
233
// p5.js drum machine
// incorporating elements of tone.js library
var beat = 0;
let value = 0;
var cells = [];
var playButton;
let slider;
// amount of steps or beats in one musical line
var nSteps = 8;
var currentStep = 0;
// amount of samples or tracks
var nSamples = 4;
// drawing visuals
var a = 40;
var b = 25;
var gridWidth, gridHeight, cellWidth, cellHeight;
var gray;
var colors = ["orange", "orange", "orange", "orange"];
// sample kits/sounds
var rock;
var trap;
var percussion;
var chooseKit;
var drumNames = ["kick", "snare", "hat", "open"];
// associate different sounds with each kit
//Tone.Player is a way to load and play back an audio file
rock = new Tone.Players({
kick: "kick1.wav",
snare: "snare1.wav",
hat: "hat1.wav",
open: "open1.wav",
});
// to be replaced with different kit sounds //
trap = new Tone.Players({
kick: "kick2.wav",
snare: "snare2.wav",
hat: "hat2.wav",
open: "open2.wav",
});
percussion = new Tone.Players({
kick: "bongo1.wav",
snare: "Cowbell1.wav",
hat: "ride3.wav",
open: "bells3.wav",
});
// toMaster function connects the output to the context's destination node
rock.toMaster();
trap.toMaster();
percussion.toMaster();
// transport is a timekeeper function in tone.js
//8n means 8th notes
Tone.Transport.scheduleRepeat(onBeat, "8n");
function preload() {
logo = loadImage("roland.png");
real = loadImage("real.png");
based = loadImage("based.png");
instructions = loadImage("instructions.png");
label = loadImage("label.png");
p5drum = loadImage("p5drum.png");
speed = loadImage("speed.png");
}
// slider for bpm
function setup() {
slider = createSlider(0, 200, 100);
slider.position(600, 400);
slider.style("width", "200px");
// drop down menu to select kit
sel = createSelect();
sel.position(24, 10);
sel.selected("rock");
sel.option("rock");
sel.option("trap");
sel.option("percussion");
sel.changed(mySelectEvent);
chooseKit = sel.value();
// initialize cell
// OFF = 0, ON = 1
for (var sample = 0; sample < nSamples; sample++) {
cells[sample] = [];
for (var step = 0; step < nSteps; step++) {
cells[sample][step] = 0;
}
}
// play button
playButton = createButton("PLAY");
playButton.position(120, 9);
playButton.mouseClicked(togglePlay);
// grid
createCanvas(1000, 1000);
gridWidth = width - 2 * b;
gridHeight = height / 2 - 2 * a;
cellWidth = gridWidth / nSteps;
cellHeight = gridHeight / nSamples;
gray = color(178, 178, 188);
}
function onBeat(time) {
var velocity = 0.5;
currentStep = beat % nSteps;
for (var sample = 0; sample < nSamples; sample++) {
if (cells[sample][currentStep]) {
var k, k2, k3;
if (chooseKit == "rock") {
k = rock.get(drumNames[sample]);
k.start(time);
} else if (chooseKit == "trap") {
k2 = trap.get(drumNames[sample]);
k2.start(time);
} else if (chooseKit == "percussion") {
k3 = percussion.get(drumNames[sample]);
k3.start(time);
}
}
}
beat++;
}
function draw() {
background(0, 0, 0);
image(logo, 225, 4, 180, 35);
image(real, 235, 520, 380, 205);
image(based, 235, 740, 380, 40);
image(instructions, 235, 360, 360, 175);
image(label, 1, 50, 70, 315);
image(p5drum, 385, 7, 320, 35);
image(speed, 600, 377, 200, 22);
let bpmMax = slider.value();
Tone.Transport.bpm.value = bpmMax;
fill(value);
// fill the cells in grid
for (var step = 0; step < nSteps; step++) {
for (var sample = 0; sample < nSamples; sample++) {
if (cells[sample][step] == 1) {
fill(colors[sample]);
rect(
b + step * cellWidth,
a + sample * cellHeight,
cellWidth,
cellHeight
);
}
}
}
// horizontal lines
for (var i = 0; i <= nSamples; i++) {
var y = a + i * cellHeight;
right = width - b;
line(b, y, right, y);
}
// vertical lines
for (var i = 0; i <= nSteps; i++) {
right = width - b;
stroke(gray);
line(b + i * cellWidth, a, b + i * cellWidth, a + gridHeight);
// highlight the cell that is playing
var step = (beat - 1) % nSteps;
if (i == step && Tone.Transport.state == "started") {
fill(255, 255, 255, 80);
noStroke();
rect(b + i * cellWidth, a, cellWidth, gridHeight);
}
}
}
function mousePressed() {
// make sure the mouse is in the grid
if (
b < mouseX &&
mouseX < b + gridWidth &&
a < mouseY &&
mouseY < a + gridHeight
) {
// margins
var x = mouseX - b;
var y = mouseY - a;
// which cell is clicked
var i = floor(x / cellWidth);
var j = floor(y / cellHeight);
// cell on/off switch
cells[j][i] = !cells[j][i];
}
}
// play, then stop button
function togglePlay() {
if (Tone.Transport.state == "started") {
Tone.Transport.stop();
playButton.html("PLAY");
} else {
if (rock.loaded && trap.loaded) {
Tone.Transport.start();
playButton.html("STOP");
}
}
}
// select the kits mySelectEvent is a function in p5.js
function mySelectEvent() {
if (sel.value() == "rock") {
chooseKit = "rock";
} else if (sel.value() == "trap") {
chooseKit = "trap";
} else if (sel.value() == "percussion") {
chooseKit = "percussion";
}
// say which kit is selected and playing in console
console.log("playing kit: " + chooseKit);
}