Skip to content

Commit

Permalink
Piano-style note display. #18
Browse files Browse the repository at this point in the history
  • Loading branch information
PoneyClairDeLune committed Sep 20, 2023
1 parent 893864c commit 937f904
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 17 deletions.
43 changes: 27 additions & 16 deletions src/cambiare/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ let Cambiare = class extends RootDisplay {
#sectPart = [];
#sectMeta = {};
#noteEvents = [];
style = "block";
#style = "block";
#drawNote(context, note, velo, state = 0, pitch = 0) {
// Param calculation
let upThis = this;
Expand All @@ -165,7 +165,7 @@ let Cambiare = class extends RootDisplay {
let range = upThis.#renderRange;
let isHeld = state > 3,
isBlackKey = blackKeys.indexOf(note % 12) > -1;
switch (upThis.style) {
switch (upThis.#style) {
case "block":
case "comb": {
sx = Math.round(note * width / 128);
Expand All @@ -175,10 +175,9 @@ let Cambiare = class extends RootDisplay {
break;
};
case "piano": {
sx = Math.round((Math.floor(note / 12) * 7 + keyXs[note % 12]) * width / 75);
ex = Math.round((Math.floor(note / 12) * 7 + keyXs[note % 12] + 1) * width / 75);
sx = Math.round((Math.floor(note / 12) * 7 + keyXs[note % 12]) * width / 75 * 1.0044642857142856);
ex = Math.round((Math.floor(note / 12) * 7 + keyXs[note % 12] + 1) * width / 75 * 1.0044642857142856) - 1;
dx = ex - sx;
console.debug(dx, sx, ex);
border = range == 1 ? 3 : 1;
break;
};
Expand All @@ -190,7 +189,7 @@ let Cambiare = class extends RootDisplay {
context.fillStyle = `#${isBlackKey ? (upThis.#accent) : "ffffff"}${((velo << 1) | (velo >> 6)).toString(16).padStart(2, "0")}`;
context.strokeStyle = context.fillStyle;
// Draw calls
switch (upThis.style) {
switch (upThis.#style) {
case "block": {
let h = context.canvas.height - 1;
context.fillRect(sx, 1, dx, h);
Expand All @@ -208,7 +207,7 @@ let Cambiare = class extends RootDisplay {
break;
};
case "piano": {
let sh = (context.canvas.height >> 1) * isHeld + 1,
let sh = (isBlackKey ? 0 : context.canvas.height >> 1) + 1,
dh = (context.canvas.height >> 1) - 1;
context.fillRect(sx, sh, dx, dh);
if (isHeld) {
Expand All @@ -221,6 +220,18 @@ let Cambiare = class extends RootDisplay {
};
};
};
#redrawNotesInternal(sum, overrideActiveCh) {
let upThis = this;
(sum?.chInUse || overrideActiveCh).forEach((e, part) => {
if (e) {
let context = upThis.#sectPart[part >> 4][part & 15].cxt;
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
sum.chKeyPr[part].forEach(({v, s}, note) => {
upThis.#drawNote(context, note, v, s, upThis.device.getPitchShift(part));
});
};
});
};
#scrollMeta(resetTime) {
let upThis = this;
if (Date.now() - upThis.#metaLastWheel > 4000) {
Expand Down Expand Up @@ -348,15 +359,7 @@ let Cambiare = class extends RootDisplay {
};
};
// Draw every note that has channels updated
channels.forEach((e, part) => {
if (e) {
let context = upThis.#sectPart[part >> 4][part & 15].cxt;
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
sum.chKeyPr[part].forEach(({v, s}, note) => {
upThis.#drawNote(context, note, v, s, upThis.device.getPitchShift(part));
});
};
});
upThis.#redrawNotesInternal(sum, channels);
// Draw every note inside extraStates
offNotes.forEach((key) => {
let {part, note, velo, state} = extraStates[key];
Expand All @@ -366,6 +369,14 @@ let Cambiare = class extends RootDisplay {
};
#renderer;
#renderThread;
get style() {
return this.#style;
};
set style(value) {
let upThis = this;
upThis.#style = value;
upThis.#redrawNotesInternal(upThis.render(upThis.#clockSource?.currentTime || 0));
};
setClockSource(clockSource) {
this.#clockSource = clockSource;
};
Expand Down
3 changes: 3 additions & 0 deletions src/cambiare_demo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ self.gDemo = async function ({file, id, artist, title}) {
Alpine.store("play", "demo");
Alpine.store("sound", "demo");
};
self.gStyle = async function (type) {
visualizer.style = type;
};

const propsMid = JSON.parse('{"extensions":[".mid",".MID",".kar",".KAR",".syx",".SYX",".s7e",".S7E",".mdat",".MDAT"],"startIn":"music","id":"midiOpener","description":"Open a MIDI file"}'),
propsAud = JSON.parse('{"mimeTypes":["audio/*"],"startIn":"music","id":"audioOpener","description":"Open an audio file"}');
Expand Down
2 changes: 1 addition & 1 deletion test/cambiare.htm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<div class="column column-option"><b>Open from</b></div>
<div class="column column-option column-button" @click="gOpenSmf()" :active="$store.play=='smf'?'true':'false'" title="Open MIDI files, SysEx blobs or bank files.">MIDI</div>
<div class="column column-option column-button" @click="gOpenSnd()" :active="$store.sound=='file'?'true':'false'" title="Open synchronized audio tracks.">audio</div>
<div class="column column-option column-button" @click="gOpenSnd()" :active="$store.sound=='mic'?'true':'false'" title="Open audio capture.">capture</div>
<div class="column column-option column-button" @click="gOpenCap()" :active="$store.sound=='mic'?'true':'false'" title="Open audio capture.">capture</div>
<div class="column column-option column-button" @click="gOpenLni()" :active="$store.play=='lni'?'true':'false'" title="Reset and receive raw MIDI inputs from middleware.">line in</div>
<div class="column column-option column-button" @click="gOpenLno()" :active="$store.play=='lno'?'true':'false'" title="Reset and receive MIDI events emitted from middleware.">line out</div>
<div class="column"></div>
Expand Down

0 comments on commit 937f904

Please sign in to comment.