xxxxxxxxxx
/*
1 - DrumPad messages received from the MIDI keyboard using WebMIDI.
2 - Function written to check whether the Pads are open or closed based on DrumPad messages.
3 - Pad visuals drawn on the canvas.
4 - Visual representation of whether the pads are open or closed.
5 - Other messages from the keyboard (Wheels, Knobs, Faders) received.
6 - Inputs from Wheels, Knobs, and Faders saved to variables.
7 - Variables from Wheels, Knobs, and Faders visually displayed on the canvas.
8 - Individual fft waveform analysis completed.
9 - Individual waveform's from sounds that connected to pads displayed on canvas.
10 - Volume level of sound outputs displayed on canvas with circle.(Removed)
11 - Each knob controls the volume of a sound individually.
12 - Fader 1 controls the color scheme of canvas.
13 - Fader 2 controls the visibility of the waveforms.
14 - Fader 3 controls the visibility of animated rectengle.
15 - Fader 4 controls the trail effect.
16 - Mod Wheel controls the master volume.
17 - Step 10 is removed.
*/
//Channel 10
let midiStatus = 0, midiKey = 0, midiPressure = 0;
let pad = new Array(8).fill(0);
//Channel 1
let messageType = 0, controlNumber = 0, controlValue = 0;
let pitchWheel = 64, modWheel = 64;
let knob = new Array(8).fill(0);
let fader = new Array(4).fill(0);
//Sounds
let loop1;
let loop2
let kick;
let snare;
let claps;
let hihat;
let bass;
let synth;
//Fonts
let font;
//Draw
let bSize;
let bOff;
let bStroke;
// Visual
let fftPad1, fftPad2, fftPad3, fftPad4, fftPad5, fftPad6, fftPad7, fftPad8;
//Colors
let backgroundCol, backgroundAlp, sqCol, padOpenCol, padCloseCol,
waveCol, waveAlp, screenCol, screenStrokeCol, textCol,
knob_r, knob_a;
//Square
let sqWeight;
let sqSize = 0;
let sqAlp;
//Amplitude
let levelMain;
//==================================================================================================
function preload(){
loop1 = loadSound("lowBass.mp3");
loop2 = loadSound("lowChords.mp3");
kick = loadSound("lowDrumLoops.mp3");
snare = loadSound("lowKick.mp3");
claps = loadSound("lowTopShaker.mp3");
hihat = loadSound("lowVocal.mp3");
bass = loadSound("lowBass.mp3");
synth = loadSound("lowBass.mp3");
font = loadFont("Digital.ttf");
}
//==================================================================================================
function setup() {
createCanvas(windowWidth, windowHeight);
// Enable WEBMIDI.js and trigger the onEnabled() function when ready
WebMidi.enable().then(onEnabled).catch(err => console.error("WebMidi could not be enabled:", err));
//Pads
bSize = windowWidth / 12;
bOff = (width - (bSize*8)) / 9;
bStroke = bSize / 12;
//FFT Analyze of Sounds Individually
ampMain = new p5.Amplitude();
fftPad1 = new p5.FFT();
fftPad2 = new p5.FFT();
fftPad3 = new p5.FFT();
fftPad4 = new p5.FFT();
fftPad5 = new p5.FFT();
fftPad6 = new p5.FFT();
fftPad7 = new p5.FFT();
fftPad8 = new p5.FFT();
//Setting input sounds to the pads
fftPad1.setInput(loop1);
fftPad2.setInput(loop2);
fftPad3.setInput(kick);
fftPad4.setInput(snare);
fftPad5.setInput(claps);
fftPad6.setInput(hihat);
fftPad7.setInput(bass);
fftPad8.setInput(synth);
//Colors
backgroundCol = "#000000";
sqCol = "#FFFFFF";
padOpenCol = "#FFFFFF";
padCloseCol = "#555555";
waveCol = "#FFFFFF";
screenCol = "#000000"
screenStrokeCol = "#555555";
textCol = "#FFFFFF"
knob_a = 100;
}
//==================================================================================================
function draw() {
sceneColor();
background(backgroundCol, backgroundAlp);
padVisuals(bSize, bOff, bStroke, pad, knob);
padVolume();
}
//==================================================================================================
function padVisuals(bSize, bOff, bStroke, padArray, knobArray){
//Illusion Rect
push();
rectMode(CENTER);
fill(0, 0);
stroke(sqCol, sqAlp);
strokeWeight(sqSize*0.1);
rect(width / 2, height / 2, sqSize, sqSize);
sqSize += 50; // Increase the size by 1 in each frame
// Reset the size if it becomes larger than the width of the canvas
if (sqSize > width) {
sqSize = 0;
}
pop();
//Waveform
let wavePad1 = fftPad1.waveform();
let wavePad2 = fftPad2.waveform();
let wavePad3 = fftPad3.waveform();
let wavePad4 = fftPad4.waveform();
let wavePad5 = fftPad5.waveform();
let wavePad6 = fftPad6.waveform();
let wavePad7 = fftPad7.waveform();
let wavePad8 = fftPad8.waveform();
let waveForms = [wavePad1,wavePad2,wavePad3,wavePad4,wavePad5,wavePad6,wavePad7,wavePad8];
//Pads
for(let i=0; i<8; i++){
knob_r = map(knob[i], 0, 127, 0, 60);
fill(knob_r, knob_r, knob_r, knob_a);
//Visual representation of pad's state
if(pad[i] === 0){
stroke(padCloseCol);
}else{
stroke(padOpenCol);
}
//Define pads coordinates
let sqrX = bOff+(bSize*i)+bOff*i
let sqrY = height-bSize-(bStroke*1.5)
strokeWeight(bStroke);
square(sqrX, sqrY, bSize, 10);
//WaveForm
push();
noFill();
stroke(waveCol, waveAlp);
//Visual representation of waves state - visible or not
if(pad[i] === 1){
strokeWeight(2);
}
else{
strokeWeight(0);
}
beginShape();
for(let j=0; j<height-(bSize+(bStroke*1.5)); j++){
let index = floor(map(j, 0, height-(bSize+(bStroke*1.5)), 0, waveForms[i].length));
let waveY = j;
let waveX = waveForms[i][index] * 150 + sqrX + bSize/2;
vertex(waveX, waveY);
}
endShape();
pop();
}
//Screen
push();
rectMode(CENTER);
fill(screenCol);
stroke(screenStrokeCol);
strokeWeight(bStroke*0.25);
rect(width/2, height-bSize-(bStroke*1.5)-(height/12), bSize, bSize/3, 10);
pop();
push();
strokeWeight(0);
fill(textCol);
textAlign(CENTER, CENTER);
textSize(bSize*0.2);
textFont(font);
text(floor(map(controlValue, 0, 127, 0, 100)), width/2, height-bSize-(bStroke*1.5)-(height/12))
pop();
}
//==================================================================================================
//Function to define state of pad (open-closed)
function padCheck(midiStatus, midiKey){
if(midiStatus == 153){
pad[midiKey-44] = 1 - pad[midiKey-44];
//console.log("Pad toggled to:" + pad[midiKey-44]);
//print(pad);
padSound(pad, loop1, loop2, kick, snare, claps, hihat, bass, synth);
}
}
//==================================================================================================
//Function to play or stop sounds
function padSound(pad, sounds) {
for(let i = 0; i < pad.length; i++) {
if(pad[i] === 1 && sounds[i]) {
if(!sounds[i].isPlaying()) {
sounds[i].loop();
}
}else {
if (sounds[i] && sounds[i].isPlaying()) {
sounds[i].stop();
}
}
}
}
//==================================================================================================
//Function to set colume of sounds and master sound
function padVolume(){
let masterVolume = map(modWheel, 0, 127, 0, 1);
loop1.setVolume(map(knob[0], 0, 127, 0, 1));
loop2.setVolume(map(knob[1], 0, 127, 0, 1));
kick.setVolume(map(knob[2], 0, 127, 0, 1));
snare.setVolume(map(knob[3], 0, 127, 0, 1));
claps.setVolume(map(knob[4], 0, 127, 0, 1));
hihat.setVolume(map(knob[5], 0, 127, 0, 1));
bass.setVolume(map(knob[6], 0, 127, 0, 1));
synth.setVolume(map(knob[7], 0, 127, 0, 1));
//Master Volume
p5.soundOut.output.gain.value = masterVolume;
}
//==================================================================================================
//Function to change scene's color scheme while conditions met
function sceneColor(){
levelMain = ampMain.getLevel();
if(fader[0] > 125 && levelMain > 0.35) {
backgroundCol = 255;
sqCol = 0;
padOpenCol = "#000000";
padCloseCol = "#000000";
waveCol = 0;
screenCol = "#FFFFFF"
screenStrokeCol = "#000000";
textCol = "#000000"
knob_a = 0;
}else {
backgroundCol = 0;
sqCol = 255;
padOpenCol = "#FFFFFF";
padCloseCol = "#555555";
waveCol = 255;
screenCol = "#000000"
screenStrokeCol = "#555555";
textCol = "#FFFFFF"
knob_a = 100;
}
waveAlp = map(fader[1], 0, 127, 0, 255);
sqAlp = map(fader[2], 0, 127, 0, 255);
backgroundAlp = map(fader[3], 0, 127, 20, 100);
}
//==================================================================================================