diff --git a/globals.js b/globals.js
index f9bf036..df9475b 100644
--- a/globals.js
+++ b/globals.js
@@ -17,6 +17,7 @@ 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;
@@ -92,9 +93,9 @@ function noteOn(pitch, velocity) {
totalIntensityScore += velocity;
// piano visualizer
- isKeyOn[pitch] = 1;
+ isKeyOn[pitch] = velocity;
if (nowPedaling) {
- isPedaled[pitch] = 1;
+ isPedaled[pitch] = velocity;
}
}
@@ -136,9 +137,12 @@ function toggleRainbowMode(cb) {
select('#colorpicker').removeAttribute('disabled')
}
+function toggleVelocityMode(cb) {
+ velocityMode = cb.checked;
+}
+
function changeColor() {
- keyOnColor = pedaledColor = color(select('#colorpicker').value());
- darkenedColor = keyOnColor.levels.map(x => floor(x * .7));
- pedaledColor = color(`rgb(${darkenedColor[0]}, ${darkenedColor[1]}, ${darkenedColor[2]})`)
- console.log(pedaledColor.levels);
+ keyOnColor = color(select('#colorpicker').value());
+ let darkenedColor = keyOnColor.levels.map(x => floor(x * .7));
+ pedaledColor = color(`rgb(${darkenedColor[0]}, ${darkenedColor[1]}, ${darkenedColor[2]})`);
}
\ No newline at end of file
diff --git a/index.html b/index.html
index 06517f1..95e2197 100644
--- a/index.html
+++ b/index.html
@@ -31,7 +31,14 @@
彩虹模式
-
+
+ 力度模式
+
+
diff --git a/piano-visualizer.js b/piano-visualizer.js
index ca9b8ee..0a9a6b8 100644
--- a/piano-visualizer.js
+++ b/piano-visualizer.js
@@ -49,16 +49,28 @@ function drawWhiteKeys() {
for (let i = 21; i < 109; i++) {
if (isBlack[i % 12] == 0) {
// it's a white key
- if (isKeyOn[i] == 1 && !rainbowMode) {
- fill(keyOnColor); // keypressed
- } else if (isKeyOn[i] == 1 && rainbowMode) {
- fill(map(i, 21, 108, 0, 1080) % 360, 100, 100, 100); // rainbowMode
- } else if (isPedaled[i] == 1 && !rainbowMode) {
- fill(pedaledColor); // pedaled
- } else if (isPedaled[i] == 1 && rainbowMode) {
- fill(map(i, 21, 108, 0, 1080) % 360, 100, 70, 100); // pedaled rainbowMode
+ if (velocityMode) {
+ let m = max(isKeyOn[i], isPedaled[i]) * .9 + .1;
+ if ((isKeyOn[i] || isPedaled[i]) && !rainbowMode) {
+ let whitenedColor = keyOnColor.levels.map(x => floor(x * m + 255 * (1 - m)));
+ fill(`rgb(${whitenedColor[0]}, ${whitenedColor[1]}, ${whitenedColor[2]})`); // keypressed
+ } else if ((isKeyOn[i] || isPedaled[i]) && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100 * m, 100, 100); // rainbowMode
+ } else {
+ fill(0, 0, 100); // white key
+ }
} else {
- fill(0, 0, 100); // white key
+ if (isKeyOn[i] && !rainbowMode) {
+ fill(keyOnColor); // keypressed
+ } else if (isKeyOn[i] && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100, 100, 100); // rainbowMode
+ } else if (isPedaled[i] && !rainbowMode) {
+ fill(pedaledColor); // pedaled
+ } else if (isPedaled[i] && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100, 70, 100); // pedaled rainbowMode
+ } else {
+ fill(0, 0, 100); // white key
+ }
}
let thisX = border + wIndex * (whiteKeyWidth + whiteKeySpace);
rect(thisX, keyAreaY, whiteKeyWidth, keyAreaHeight, radius);
@@ -80,16 +92,28 @@ function drawBlackKeys() {
if (isBlack[i % 12] > 0) {
// it's a black key
- if (isKeyOn[i] == 1 && !rainbowMode) {
- fill(keyOnColor); // keypressed
- } else if (isKeyOn[i] == 1 && rainbowMode) {
- fill(map(i, 21, 108, 0, 1080) % 360, 100, 100, 100); // rainbowMode
- } else if (isPedaled[i] == 1 && !rainbowMode) {
- fill(pedaledColor); // pedaled
- } else if (isPedaled[i] == 1 && rainbowMode) {
- fill(map(i, 21, 108, 0, 1080) % 360, 100, 70, 100); // pedaled rainbowMode
+ if (velocityMode) {
+ let m = max(isKeyOn[i], isPedaled[i]) * .9 + .1;
+ if ((isKeyOn[i] || isPedaled[i]) && !rainbowMode) {
+ let darkenedColor = keyOnColor.levels.map(x => floor(x * m));
+ fill(`rgb(${darkenedColor[0]}, ${darkenedColor[1]}, ${darkenedColor[2]})`); // keypressed
+ } else if ((isKeyOn[i] || isPedaled[i]) && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100, 100 * m, 100); // rainbowMode
+ } else {
+ fill(0, 0, 0); // black key
+ }
} else {
- fill(0, 0, 0); // white key
+ if (isKeyOn[i] && !rainbowMode) {
+ fill(keyOnColor); // keypressed
+ } else if (isKeyOn[i] && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100, 100, 100); // rainbowMode
+ } else if (isPedaled[i] && !rainbowMode) {
+ fill(pedaledColor); // pedaled
+ } else if (isPedaled[i] && rainbowMode) {
+ fill(map(i, 21, 108, 0, 1080) % 360, 100, 70, 100); // pedaled rainbowMode
+ } else {
+ fill(0, 0, 0); // black key
+ }
}
let thisX = border + (wIndex - 1) * (whiteKeyWidth + whiteKeySpace) + isBlack[i % 12];
@@ -147,7 +171,7 @@ function pushHistories() {
shortTermTotal.push(notesThisFrame);
shortTermTotal.shift();
notesThisFrame = 0;
- legatoHistory.push(isKeyOn.reduce((accumulator, currentValue) => accumulator + currentValue, 0));
+ legatoHistory.push(isKeyOn.reduce((accumulator, currentValue) => accumulator + !!currentValue, 0));
legatoHistory.shift();
@@ -183,8 +207,7 @@ function getPressedKeys(returnString = true) {
let pressedOrPedaled = [];
for (let i = 0; i < isKeyOn.length; i++) {
- pressedOrPedaled[i] = isKeyOn[i] === 1 || isPedaled[i] === 1 ? 1 : 0;
-
+ pressedOrPedaled[i] = isKeyOn[i] || isPedaled[i];
}
let noteNames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']; // default if sharp
@@ -196,7 +219,7 @@ function getPressedKeys(returnString = true) {
const pressedKeys = [];
for (let i = 0; i < pressedOrPedaled.length; i++) {
- if (pressedOrPedaled[i] === 1) {
+ if (pressedOrPedaled[i]) {
const noteName = noteNames[i % 12];
const octave = Math.floor(i / 12) - 1;
pressedKeys.push(`${noteName}${octave}`);
diff --git a/style.css b/style.css
index d6a410b..b000fc6 100644
--- a/style.css
+++ b/style.css
@@ -552,7 +552,7 @@ input[type=checkbox] {
visibility: hidden;
}
-label[for=rainbow-mode-checkbox] {
+label.custom-checkbox {
cursor: pointer;
width: 50px;
height: 25px;
@@ -563,7 +563,7 @@ label[for=rainbow-mode-checkbox] {
transition: .3s;
}
-label[for=rainbow-mode-checkbox]:after {
+label.custom-checkbox:after {
content: '';
position: absolute;
top: 1.25px;
@@ -575,15 +575,15 @@ label[for=rainbow-mode-checkbox]:after {
transition: .3s;
}
-input:checked + label[for=rainbow-mode-checkbox] {
+input:checked + label.custom-checkbox {
background: #6f42c1;
}
-label[for=rainbow-mode-checkbox]:active:after {
+label.custom-checkbox:active:after {
width: 32.5px;
}
-input:checked + label[for=rainbow-mode-checkbox]:after {
+input:checked + label.custom-checkbox:after {
left: calc(100% - 1.25px);
transform: translateX(-100%);
}
\ No newline at end of file