810bae60b8
When toggled, the color of each note will be affected by its velocity. Suitable when practicing this kind of stuff: https://wiwi.video/w/uuwkerA14WnDnysFCh6q4z?start=11m1s
148 lines
No EOL
4.6 KiB
JavaScript
148 lines
No EOL
4.6 KiB
JavaScript
let midiSelectSlider;
|
||
|
||
// for piano visualizer
|
||
let nowPedaling = false; // is it pedaling?(不要動)
|
||
let isKeyOn = []; // what notes are being pressed (1 or 0)(不要動)
|
||
let isPedaled = []; // what notes are pedaled (1 or 0)(不要動)
|
||
let keyOnColor // set it in setup()
|
||
let pedaledColor // set it in setup()
|
||
let isBlack = [0, 11, 0, 13, 0, 0, 11, 0, 12, 0, 13, 0]; // 是黑鍵嗎?是的話,相對左方的白鍵位移多少?(default: {0, 11, 0, 13, 0, 0, 11, 0, 12, 0, 13, 0})
|
||
let border = 3; // 左方留空幾個畫素?(default: 3)
|
||
let whiteKeyWidth = 20; // 白鍵多寬?(default: 20)
|
||
let whiteKeySpace = 1; // 白鍵間的縫隙多寬?(default: 1)
|
||
let blackKeyWidth = 17; // 黑鍵多寬?(default: 17)
|
||
let blackKeyHeight = 45; // 黑鍵多高?(default: 45)
|
||
let radius = 5; // 白鍵圓角(default: 5)
|
||
let bRadius = 4; // 黑鍵圓角(default: 4)
|
||
let keyAreaY = 3; // 白鍵從 Y 軸座標多少開始?(default: 3)
|
||
let keyAreaHeight = 70; // 白鍵多高?(default: 70)
|
||
let rainbowMode = false; // 彩虹模式 (default: false)
|
||
let velocityMode = false; // 力度模式 (default: false)
|
||
let cc64now = 0; // 現在的踏板狀態
|
||
let cc67now = 0;
|
||
|
||
let sessionStartTime = new Date();
|
||
let sessionTotalSeconds = 0;
|
||
|
||
let flatNames = false;
|
||
|
||
// note counter
|
||
let notesThisFrame = 0;
|
||
let totalNotesPlayed = 0;
|
||
let shortTermTotal = new Array(60).fill(0);
|
||
let legatoHistory = new Array(60).fill(0);
|
||
let notesSMax = 0;
|
||
let totalIntensityScore = 0;
|
||
|
||
// for key pressed counter
|
||
let notePressedCount = 0;
|
||
let notePressedCountHistory = [];
|
||
|
||
WebMidi.enable(function (err) { //check if WebMidi.js is enabled
|
||
if (err) {
|
||
console.log("WebMidi could not be enabled.", err);
|
||
} else {
|
||
console.log("WebMidi enabled!");
|
||
}
|
||
|
||
//name our visible MIDI input and output ports
|
||
console.log("---");
|
||
console.log("Inputs Ports: ");
|
||
for (i = 0; i < WebMidi.inputs.length; i++) {
|
||
console.log(i + ": " + WebMidi.inputs[i].name);
|
||
}
|
||
|
||
console.log("---");
|
||
console.log("Output Ports: ");
|
||
for (i = 0; i < WebMidi.outputs.length; i++) {
|
||
console.log(i + ": " + WebMidi.outputs[i].name);
|
||
}
|
||
midiSelectSlider = select("#slider");
|
||
midiSelectSlider.attribute("max", WebMidi.inputs.length - 1);
|
||
midiSelectSlider.input(inputChanged);
|
||
midiIn = WebMidi.inputs[midiSelectSlider.value()]
|
||
inputChanged();
|
||
});
|
||
|
||
function inputChanged() {
|
||
isKeyOn.fill(0);
|
||
controllerChange(64, 0);
|
||
controllerChange(67, 0);
|
||
|
||
midiIn.removeListener();
|
||
midiIn = WebMidi.inputs[midiSelectSlider.value()];
|
||
midiIn.addListener('noteon', "all", function (e) {
|
||
console.log("Received 'noteon' message (" + e.note.number + ", " + e.velocity + ").");
|
||
noteOn(e.note.number, e.velocity);
|
||
});
|
||
midiIn.addListener('noteoff', "all", function (e) {
|
||
console.log("Received 'noteoff' message (" + e.note.number + ", " + e.velocity + ").");
|
||
noteOff(e.note.number, e.velocity);
|
||
})
|
||
midiIn.addListener('controlchange', 'all', function(e) {
|
||
console.log("Received control change message:", e.controller.number, e.value);
|
||
controllerChange(e.controller.number, e.value)
|
||
});
|
||
console.log(midiIn.name);
|
||
select("#device").html(midiIn.name);
|
||
};
|
||
|
||
function noteOn(pitch, velocity) {
|
||
totalNotesPlayed++;
|
||
notesThisFrame++;
|
||
totalIntensityScore += velocity;
|
||
|
||
// piano visualizer
|
||
isKeyOn[pitch] = velocity;
|
||
if (nowPedaling) {
|
||
isPedaled[pitch] = velocity;
|
||
}
|
||
}
|
||
|
||
function noteOff(pitch, velocity) {
|
||
isKeyOn[pitch] = 0;
|
||
}
|
||
|
||
function controllerChange(number, value) {
|
||
// Receive a controllerChange
|
||
if (number == 64) {
|
||
cc64now = value;
|
||
|
||
if (value >= 64) {
|
||
nowPedaling = true;
|
||
for (let i = 0; i < 128; i++) {
|
||
// copy key on to pedal
|
||
isPedaled[i] = isKeyOn[i];
|
||
}
|
||
} else if (value < 64) {
|
||
nowPedaling = false;
|
||
for (let i = 0; i < 128; i++) {
|
||
// reset isPedaled
|
||
isPedaled[i] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (number == 67) {
|
||
cc67now = value;
|
||
|
||
}
|
||
}
|
||
|
||
function toggleRainbowMode(cb) {
|
||
rainbowMode = cb.checked;
|
||
if (rainbowMode)
|
||
select('#colorpicker').attribute('disabled', true)
|
||
else
|
||
select('#colorpicker').removeAttribute('disabled')
|
||
}
|
||
|
||
function toggleVelocityMode(cb) {
|
||
velocityMode = cb.checked;
|
||
}
|
||
|
||
function changeColor() {
|
||
keyOnColor = color(select('#colorpicker').value());
|
||
let darkenedColor = keyOnColor.levels.map(x => floor(x * .7));
|
||
pedaledColor = color(`rgb(${darkenedColor[0]}, ${darkenedColor[1]}, ${darkenedColor[2]})`);
|
||
} |