diff --git a/globals.js b/globals.js
index 40748fb..7f4b990 100644
--- a/globals.js
+++ b/globals.js
@@ -1,11 +1,21 @@
+// @ts-check
+
let midiSelectSlider;
+let midiIn;
// for piano visualizer
+const state = State('pianometer/', {
+ color: '#2ee5b8',
+ rainbowMode: false, // 彩虹模式
+ velocityMode: false, // 力度模式
+});
+/** @type {Color} */
+let keyOnColor; // 「按下時」的顏色 [HSB Color Mode]
+/** @type {Color} */
+let pedaledColor; // 「踏板踩住」的顏色 [HSB Color Mode]
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)
@@ -16,8 +26,6 @@ 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;
@@ -38,27 +46,28 @@ let totalIntensityScore = 0;
let notePressedCount = 0;
let notePressedCountHistory = [];
-WebMidi.enable(function (err) { //check if WebMidi.js is enabled
+WebMidi.enable(function (err) { // check if WebMidi.js is enabled
if (err) {
- console.log("WebMidi could not be enabled.", err);
+ console.log('WebMidi could not be enabled.', err);
} else {
- console.log("WebMidi enabled!");
+ 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('Inputs Ports: ');
+ WebMidi.inputs.forEach(({name}, i) => {
+ console.log(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);
+ console.log('---');
+ console.log('Output Ports: ');
+ WebMidi.outputs.forEach(({name}, i) => {
+ console.log(i + ': ' + name);
+ });
+
+ midiSelectSlider = select('#slider');
+ midiSelectSlider.attribute('max', WebMidi.inputs.length - 1);
midiSelectSlider.input(inputChanged);
midiIn = WebMidi.inputs[midiSelectSlider.value()]
inputChanged();
@@ -71,22 +80,26 @@ function inputChanged() {
midiIn.removeListener();
midiIn = WebMidi.inputs[midiSelectSlider.value()];
- midiIn.addListener('noteon', "all", function (e) {
- console.log("Received 'noteon' message (" + e.note.number + ", " + e.velocity + ").");
+ 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 + ").");
+ 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);
+ 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);
+ select('#device').html(midiIn.name);
};
+/**
+ * @param {number} pitch
+ * @param {number} velocity
+ */
function noteOn(pitch, velocity) {
totalNotesPlayed++;
notesThisFrame++;
@@ -99,10 +112,18 @@ function noteOn(pitch, velocity) {
}
}
+/**
+ * @param {number} pitch
+ * @param {number} _velocity
+ */
function noteOff(pitch, _velocity) {
isKeyOn[pitch] = 0;
}
+/**
+ * @param {number} number
+ * @param {number} value
+ */
function controllerChange(number, value) {
// Receive a controllerChange
if (number == 64) {
@@ -128,20 +149,27 @@ function controllerChange(number, value) {
}
}
+/**
+ * @param {HTMLInputElement} cb
+ */
function toggleRainbowMode(cb) {
- rainbowMode = cb.checked;
- if (rainbowMode)
+ state.rainbowMode = cb.checked;
+ if (state.rainbowMode) {
select('#colorpicker').attribute('disabled', true)
- else
+ } else {
select('#colorpicker').removeAttribute('disabled')
+ }
}
+/**
+ * @param {HTMLInputElement} cb
+ */
function toggleVelocityMode(cb) {
- velocityMode = cb.checked;
+ state.velocityMode = cb.checked;
}
function changeColor() {
- keyOnColor = color(select('#colorpicker').value());
- let darkenedColor = keyOnColor.levels.map(x => floor(x * .7));
+ keyOnColor = color(state.color = select('#colorpicker').value());
+ const darkenedColor = keyOnColor.levels.map(x => Math.floor(x * .7));
pedaledColor = color(`rgb(${darkenedColor[0]}, ${darkenedColor[1]}, ${darkenedColor[2]})`);
}
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000..e987a63
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,49 @@
+const WebMidi: {
+ enable(callback: (err: Error|null)=>void): void
+ inputs: MidiIn[]
+ outputs: any[]
+};
+type MidiIn = {
+ name: string
+ addListener(type: 'noteon', channel: string, listener: (e: {
+ note: {number: number}
+ velocity: number
+ })=>void): void
+ addListener(type: 'noteoff', channel: string, listener: (e: {
+ note: {number: number}
+ velocity: number
+ })=>void): void
+ addListener(type: 'controlchange', channel: string, listener: (e: {
+ controller: {number: number}
+ value: number
+ })=>void): void
+};
+
+const Tonal: any;
+
+function select(selector: string): any;
+
+function color(color: string): Color;
+type Color = {
+ levels: number[],
+};
+
+const createCanvas: Function;
+const colorMode: Function;
+const smooth: Function;
+const frameRate: Function;
+const {HSB, BOLD, LEFT, TOP}: any;
+const background: Function;
+const fill: Function;
+const stroke: Function;
+const strokeWeight: Function;
+const rect: Function;
+const textFont: Function;
+const textStyle: Function;
+const textSize: Function;
+const textAlign: Function;
+const text: Function;
+const saveCanvas: Function;
+const {mouseX, mouseY}: number;
+
+function map(...argv: any[]): number;
diff --git a/index.html b/index.html
index 95e2197..27c074b 100644
--- a/index.html
+++ b/index.html
@@ -1,72 +1,67 @@
+
-
- 好和弦的鋼琴鍵盤顯示器
-
-
-
+
+ 好和弦的鋼琴鍵盤顯示器
+
+
+
-
-
-
+
+
+
+
-
-
-
-
鋼琴鍵盤顯示器 by NiceChord
-
-
-
選擇 MIDI 裝置
-
-
Select Input:
-
-
-
-
-
-
-
+
+
+
+
鋼琴鍵盤顯示器 by NiceChord
+
+
+
選擇 MIDI 裝置
+
+
Select Input:
-
-
-
-
-
-
-
- TIME:使用時間 | NOTE COUNT:總彈奏音符數 | NPS:最近一秒鐘彈奏音符數(括號為歷史最大值) | LEGATO:圓滑指數(最近一秒鐘平均來說有幾個鍵被同時按住)
- CALORIES:消耗熱量(估計值,好玩就好)| PEDALS:左右踏板深度顯示
- (密技:點鍵盤最左上角的角落,可以儲存截圖)
-
-
-
- 覺得好用嗎?到
NiceChord.com 逛逛支持我!原始碼在
GitHub。
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ TIME:使用時間 | NOTE COUNT:總彈奏音符數 | NPS:最近一秒鐘彈奏音符數(括號為歷史最大值) | LEGATO:圓滑指數(最近一秒鐘平均來說有幾個鍵被同時按住)
+ CALORIES:消耗熱量(估計值,好玩就好)| PEDALS:左右踏板深度顯示
+ (密技:點鍵盤最左上角的角落,可以儲存截圖)
+
+ 覺得好用嗎?到
NiceChord.com 逛逛支持我!原始碼在
GitHub。
+
-
\ No newline at end of file
+