xxxxxxxxxx
560
let pads = []; // Array to store all Pad objects
let TR505 = []; // Array to store TR-505 sound players
let TR808 = []; // Array to store TR-808 sound players
let Chop1 = []; // Array to store Chop1 sound players
let Garage = [];
let activeSounds = []; // Currently active sound players
let dropdown; // Dropdown menu
let screenfont;
let color1;
let color2;
let color3;
let color4;
let totalSounds = 0;
let soundsReady = false; // To track whether sounds are ready
let loadedCount = 0; // To track total sounds in each array
function preload() {
screenfont = loadFont("fonts/digital-7.ttf");
}
function setup() {
createCanvas(1470, 920); // Fixed canvas size
initializeUI();
initializePadsAndGrid(); // Initialize the pads and grid layout
// Initialize Tone.js players for TR-505 sounds
initializeTR505();
activeSounds = TR505; // Set the active sound players to TR-505 by default
Tone.context.latencyHint = 'interactive'; // Low-latency mode for real-time interactions
Tone.context.resume(); // Ensure the audio context is active
}
function draw() {
background(125);
// Draw borders
fill(0);
noStroke();
rect(0, 0, 335, height); // Left border
rect(width - 335, 0, 335, height); // Right border
if (!soundsReady) {
fill(255);
textAlign(CENTER, CENTER);
textFont(screenfont);
textSize(40);
text("Loading sounds, please wait...", width / 2, height / 2);
return; // Prevent drawing the pads until sounds are ready
}
// Draw all Pad objects
for (let pad of pads) {
pad.draw();
}
// Draw header
fill(15);
rect(355, 10, 760, 130);
// Draw selected drum kit name
let displayText = dropdown.selected();
fill(255);
textAlign(CENTER, CENTER);
textFont(screenfont);
textSize(160); // Adjust text size for better fit
text(displayText, width / 2, 70); // Centered in the header
}
function initializeUI() {
dropdown = createSelect();
dropdown.position(1020 , 110);
dropdown.size(75, 20);
dropdown.option("TR-505");
dropdown.option("TR-808");
dropdown.option("Chop 1");
dropdown.option("Garage");
dropdown.changed(() => {
const selected = dropdown.selected();
if (selected === "TR-505") {
loadDrumKit("TR-505", getLabels505());
} else if (selected === "TR-808") {
loadDrumKit("TR-808", getLabels808());
} else if (selected === "Chop 1") {
loadDrumKit("Chop 1", getLabelsChop1());
} else if (selected === "Garage") {
loadDrumKit("Garage", getLabelsGarage());
} else {
console.log("Other kits not implemented yet.");
}
});
initializeTR505(); // Initialize the default drum kit
activeSounds = TR505; // Set the default active sound kit
}
function initializePadsAndGrid(labels = getLabels505()) {
let border = 20; // Border around the pads
let spacing = 10; // Spacing between squares
let rows = 4; // Number of rows
let cols = 4; // Number of columns
// Fixed grid width of 800
let gridWidth = 800;
let squareSize = (gridWidth - (cols - 1) * spacing - 2 * border) / cols;
let gridHeight = rows * squareSize + (rows - 1) * spacing;
// Vertical centering
let verticalShift = (height - gridHeight) - 10;
// Horizontal centering with 335px borders
let horizontalShift = ((width - gridWidth) / 2) + 20;
initializePads(verticalShift, horizontalShift, squareSize, spacing, labels);
}
function initializePads(verticalShift, horizontalShift, squareSize, spacing, labels) {
pads = []; // Clear existing pads
let rows = 4; // Number of rows
let cols = 4; // Number of columns
let labelIndex = 0;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let x = horizontalShift + j * (squareSize + spacing); // Adjust horizontal position
let y = verticalShift + i * (squareSize + spacing); // Adjust vertical position
let color = 30; // Default color for the square
let label = labels[labelIndex++]; // Get corresponding drum label
pads.push(new Pad(x, y, squareSize, color, label)); // Create a new Pad object
}
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
initializePadsAndGrid();
}
// Initialize pads with the given labels
// Initialize pads with labels
function initializePads(verticalShift, horizontalShift, squareSize, spacing, labels) {
pads = []; // Clear existing pads
let rows = 4; // Number of rows
let cols = 4; // Number of columns
let labelIndex = 0;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let x = horizontalShift + j * (squareSize + spacing); // Centered horizontally with the grid
let y = verticalShift + i * (squareSize + spacing); // Centered vertically
let color = 30; // Default color for the square
let label = labels[labelIndex++]; // Get corresponding drum label
pads.push(new Pad(x, y, squareSize, color, label)); // Create a new Pad object
}
}
}
// Load the selected drum kit
function loadDrumKit(kitName, labels) {
if (kitName === "TR-505") {
activeSounds = TR505; // Set active sounds to TR-505
} else if (kitName === "TR-808") {
if (TR808.length === 0) initializeTR808(); // Load TR-808 sounds if not already loaded
activeSounds = TR808; // Set active sounds to TR-808
} else if (kitName === "Chop 1") {
if (Chop1.length === 0) initializeChop1();
activeSounds = Chop1;
} else if (kitName === "Garage") {
if (Garage.length === 0) initializeGarage();
activeSounds = Garage;
}
// initalize pads and grid with updated labels
initializePadsAndGrid(labels);
}
// Get labels for TR-505
function getLabels505() {
return [
"Hi Conga",
"Low Conga",
"Hi Cowbell",
"Low Cowbell",
"Hi Tom",
"Mid Tom",
"Low Tom",
"Clap",
"Crash",
"Open Hat",
"Closed Hat",
"Ride",
"Snare",
"Rim Shot",
"Timbale",
"Kick",
];
}
// Get labels for TR-808
function getLabels808() {
return [
"Conga High",
"Conga Mid",
"Conga Low",
"Cowbell",
"Tom High",
"Tom Mid",
"Tom Low",
"Maracas",
"Cymbal",
"Open Hat Short",
"Hihat",
"Claves",
"Snare Bright",
"Snare Mid",
"Rimshot",
"Kick Basic",
];
}
function getLabelsChop1() {
return [
"Kick",
"Hat 1",
"Snare 1",
"Crash 2",
"Chord 1",
"Hat 2",
"Ghost Snare 1",
"Snare 2",
"Kick 2",
"Hat 3",
"Snare 3",
"Chord 2",
"808",
"Ghost Snare 2",
"Snare 4",
"Chord 3",
];
}
function getLabelsGarage() {
return [
"Low Tom ",
"Mid Tom ",
"High Tom",
"Crash",
"Hat Open",
"SideStick",
"Hat Lid",
"Shaker",
"Bass",
"Snare Roll",
"Hat Closed",
"Wood Stick",
"Kick",
"Snare Hit 1",
"Snare Hit 2",
"Ride",
];
}
function initializeGarage() {
const sounds = [
"A13.WAV",
"A14.WAV",
"A15.WAV",
"A16.WAV",
"A9.WAV",
"A10.WAV",
"A11.WAV",
"A12.WAV",
"A5.WAV",
"A6.WAV",
"A7.WAV",
"A8.WAV",
"A1.WAV",
"A3.WAV",
"A2.WAV",
"A4.WAV",
];
totalSounds = sounds.length; // Set total sounds for this kit
soundsReady = false; // Reset flag
loadedCount = 0; // Reset loaded count
// Create Tone.Player objects for each sound
sounds.forEach((sound) => {
const player = new Tone.Player({
url: `drum_samples/Garage/${sound}`,
onload: () => {
console.log(`${sound} loaded`);
loadedCount++;
if (loadedCount === totalSounds) {
soundsReady = true;
console.log("All sounds loaded for Garage.");
}
},
onerror: (err) => {
console.error(`Error loading ${sound}:`, err);
},
}).toDestination();
Garage.push(player);
});
}
// Initialize Tone.js players for TR-505 sounds
function initializeTR505() {
const sounds = [
"hi_conga_bip.wav",
"Low_conga_bip.wav",
"hi_cowbell_bip.wav",
"low_cowbell_bip.wav",
"hi_tom_bip.wav",
"mid_tom_bip.wav",
"low_tom_bip.wav",
"clap_bip.wav",
"crash_bip.wav",
"open_hat_bip.wav",
"closed_hhat_bip.wav",
"Ride_bip.wav",
"snare_bip.wav",
"rim_shot_bip.wav",
"timbale_bip.wav",
"kick_bip.wav",
];
totalSounds = sounds.length; // Set total sounds for this kit
soundsReady = false; // Reset flag
loadedCount = 0; // Reset loaded count
// Create Tone.Player objects for each sound
sounds.forEach((sound) => {
const player = new Tone.Player({
url: `drum_samples/TR-505/${sound}`,
onload: () => {
console.log(`${sound} loaded`);
loadedCount++;
if (loadedCount === totalSounds) {
soundsReady = true;
console.log("All sounds loaded for TR-505.");
}
},
onerror: (err) => {
console.error(`Error loading ${sound}:`, err);
},
}).toDestination();
TR505.push(player);
});
}
// Initialize Tone.js players for TR-808 sounds
function initializeTR808() {
const sounds = [
"Conga_High.wav",
"Conga_Mid.wav",
"Conga_Low.wav",
"Cowbell.wav",
"Tom_High.wav",
"Tom_Mid.wav",
"Tom_Low.wav",
"Maracas.wav",
"Cymbal.wav",
"Open_Hat_Short.wav",
"Hihat.wav",
"Claves.wav",
"Snare_Bright.wav",
"Snare_Mid.wav",
"Rimshot.wav",
"Kick_Basic.wav",
];
totalSounds = sounds.length; // Set total sounds for this kit
soundsReady = false; // Reset flag
loadedCount = 0; // Reset loaded count
// Create Tone.Player objects for each sound
sounds.forEach((sound) => {
const player = new Tone.Player({
url: `drum_samples/TR-808/${sound}`,
onload: () => {
console.log(`${sound} loaded`);
loadedCount++;
if (loadedCount === totalSounds) {
soundsReady = true;
console.log("All sounds loaded for TR-808.");
}
},
onerror: (err) => {
console.error(`Error loading ${sound}:`, err);
},
}).toDestination();
TR808.push(player);
});
}
function initializeChop1() {
const sounds = [
"kick.wav",
"hat1.wav",
"snare1.wav",
"crash2.wav",
"chord1.wav",
"hat2.wav",
"ghostsnare.wav",
"snare2.wav",
"kick2.wav",
"hat3.wav",
"snare3.wav",
"chord2.wav",
"808.wav",
"ghostsnare2.wav",
"snare4.wav",
"chord3.wav",
];
totalSounds = sounds.length; // Set total sounds for this kit
soundsReady = false; // Reset flag
loadedCount = 0; // Reset loaded count
// Create Tone.Player objects for each sound
sounds.forEach((sound) => {
const player = new Tone.Player({
url: `drum_samples/Chop1/${sound}`,
onload: () => {
console.log(`${sound} loaded`);
loadedCount++;
if (loadedCount === totalSounds) {
soundsReady = true;
console.log("All sounds loaded for Chop 1.");
}
},
onerror: (err) => {
console.error(`Error loading ${sound}:`, err);
},
}).toDestination();
Chop1.push(player);
});
}
// Handle serial input
function readSerial(data) {
if (!serialActive) return;
let padIndex = parseInt(data.trim());
if (isNaN(padIndex) || padIndex < 0 || padIndex >= pads.length) {
console.log("Invalid pad index:", data);
return; // Ignore invalid input
}
if (!soundsReady) {
console.log("Sounds are still loading. Please wait.");
return; // Prevent interaction if sounds are not ready
}
if (!activeSounds || !activeSounds[padIndex]) {
console.log(`Sound not loaded for pad ${padIndex}.`);
return; // Prevent errors if sounds are not loaded
}
pads[padIndex].highlight(100); // Highlight the pad
activeSounds[padIndex].start(); // Play the corresponding sound
}
// Pad class remains unchanged
class Pad {
constructor(x, y, size, color, label) {
this.x = x; // X-coordinate
this.y = y; // Y-coordinate
this.size = size; // Size of the square
this.color = color; // Default color
this.label = label; // Drum label for the pad
this.isHighlighted = false;
this.highlightTime = 0;
}
draw() {
// Determine row based on y position
let row = floor((this.y - 20) / ((height - 40) / 4)); // Adjust based on the total height and padding
// Highlight color based on row
let highlightColor;
if (row === 0) {
highlightColor = color(0,255, 0); // green
} else if (row === 1) {
highlightColor = color(255); // white
} else if (row === 2) {
highlightColor = color(255,255, 0); //yellow
} else if (row === 3) {
highlightColor = color(255, 0, 0); // red
} else{
highlightColor = color(255,0,0)
}
// Draw the pad
if (this.isHighlighted && millis() - this.highlightTime < 100) {
fill(highlightColor); // Highlight color
} else {
this.isHighlighted = false; // Reset highlight
fill(this.color);
}
rect(this.x, this.y, this.size, this.size);
// Draw the label
fill(255);
textAlign(CENTER, CENTER);
textSize(30);
text(this.label, this.x + this.size / 2, this.y + this.size / 2);
}
highlight(duration) {
this.isHighlighted = true;
this.highlightTime = millis();
}
}
function keyPressed() {
const keyMapping = {
// Map keys to pad indices
'1': 0, '2': 1, '3': 2, '4': 3,
'Q': 4, 'W': 5, 'E': 6, 'R': 7,
'7': 8, '8': 9, '9': 10, '0': 11,
'U': 12, 'I': 13, 'O': 14, 'P': 15
};
const padIndex = keyMapping[key.toUpperCase()]; // Get pad index for the pressed key
if (padIndex !== undefined && padIndex >= 0 && padIndex < pads.length) {
if (!soundsReady) {
console.log("Sounds are still loading. Please wait.");
return; // Prevent interaction if sounds are not ready
}
if (!activeSounds || !activeSounds[padIndex]) {
console.log(`Sound not loaded for pad ${padIndex}.`);
return; // Prevent errors if sounds are not loaded
}
pads[padIndex].highlight(100); // Highlight the pad
activeSounds[padIndex].start(); // Play the corresponding sound
} if (key === " ") {
// Try to set up the serial connection
setUpSerial()
.then(() => console.log("Serial connection established."))
.catch((err) => {
console.error("Failed to establish serial connection:", err);
alert("Serial not established, please try again.");
});
}
else if (key === 'F' || key === 'f') {
let fs = fullscreen();
fullscreen(!fs); // Toggle fullscreen mode
} else if (key === 'Y' || key === 'y') {
console.log(width, height); // Log canvas dimensions
}
}