Adding show scale method to interact with lighted keyboards
This commit is contained in:
@ -39,7 +39,7 @@
|
||||
"tone": "^14.8.49",
|
||||
"unique-names-generator": "^4.7.1",
|
||||
"vite-plugin-markdown": "^2.1.0",
|
||||
"zifferjs": "^0.0.32",
|
||||
"zifferjs": "^0.0.33",
|
||||
"zzfx": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
58
src/API.ts
58
src/API.ts
@ -1,4 +1,4 @@
|
||||
import { seededRandom } from "zifferjs";
|
||||
import { getAllScaleNotes, seededRandom } from "zifferjs";
|
||||
import {
|
||||
MidiCCEvent,
|
||||
MidiConnection,
|
||||
@ -63,6 +63,7 @@ export class UserAPI {
|
||||
private errorTimeoutID: number = 0;
|
||||
private printTimeoutID: number = 0;
|
||||
public MidiConnection: MidiConnection;
|
||||
public scale_aid: string|number|undefined = undefined;
|
||||
load: samples;
|
||||
|
||||
constructor(public app: Editor) {
|
||||
@ -586,6 +587,61 @@ export class UserAPI {
|
||||
else return this.MidiConnection.ccInputBuffer.shift();
|
||||
};
|
||||
|
||||
public show_scale = (
|
||||
root: number|string,
|
||||
scale: number|string,
|
||||
channel: number = 0,
|
||||
port: number|string = (this.MidiConnection.currentOutputIndex || 0),
|
||||
soundOff: boolean = false): void => {
|
||||
/**
|
||||
* Sends given scale to midi output for visual aid
|
||||
*/
|
||||
if (!this.scale_aid || scale !== this.scale_aid) {
|
||||
this.hide_scale(root,scale,channel,port);
|
||||
const scaleNotes = getAllScaleNotes(scale, root);
|
||||
// Send each scale note to current midi out
|
||||
scaleNotes.forEach(note => {
|
||||
this.MidiConnection.sendMidiOn(note, channel, 1, port);
|
||||
if(soundOff) this.MidiConnection.sendAllSoundOff(channel, port);
|
||||
});
|
||||
|
||||
this.scale_aid = scale;
|
||||
}
|
||||
}
|
||||
|
||||
public hide_scale = (
|
||||
// @ts-ignore
|
||||
root: number|string=0,
|
||||
// @ts-ignore
|
||||
scale: number|string=0,
|
||||
channel: number = 0,
|
||||
port: number|string = (this.MidiConnection.currentOutputIndex || 0)): void => {
|
||||
/**
|
||||
* Hides all notes by sending all notes off to midi output
|
||||
*/
|
||||
const allNotes = Array.from(Array(128).keys());
|
||||
// Send each scale note to current midi out
|
||||
allNotes.forEach(note => {
|
||||
this.MidiConnection.sendMidiOff(note, channel, port);
|
||||
});
|
||||
this.scale_aid = undefined;
|
||||
|
||||
}
|
||||
|
||||
midi_notes_off = (channel: number = 0, port: number|string = (this.MidiConnection.currentOutputIndex || 0)): void => {
|
||||
/**
|
||||
* Sends all notes off to midi output
|
||||
*/
|
||||
this.MidiConnection.sendAllNotesOff(channel, port);
|
||||
}
|
||||
|
||||
midi_sound_off = (channel: number = 0, port: number|string = (this.MidiConnection.currentOutputIndex || 0)): void => {
|
||||
/**
|
||||
* Sends all sound off to midi output
|
||||
*/
|
||||
this.MidiConnection.sendAllSoundOff(channel, port);
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
// Ziffers related functions
|
||||
// =============================================================
|
||||
|
||||
@ -31,7 +31,7 @@ export class MidiConnection {
|
||||
private settings: AppSettings;
|
||||
private midiAccess: MIDIAccess | null = null;
|
||||
public midiOutputs: MIDIOutput[] = [];
|
||||
private currentOutputIndex: number = 0;
|
||||
public currentOutputIndex: number = 0;
|
||||
private scheduledNotes: { [noteNumber: number]: number } = {}; // { noteNumber: timeoutId }
|
||||
|
||||
/* Midi input */
|
||||
@ -625,6 +625,64 @@ export class MidiConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public sendMidiOn(note: number, channel: number, velocity: number, port: number | string = this.currentOutputIndex) {
|
||||
/**
|
||||
* Sending Midi Note on message
|
||||
*/
|
||||
if(typeof port === "string") port = this.getMidiOutputIndex(port);
|
||||
const output = this.midiOutputs[port];
|
||||
note = Math.min(Math.max(note, 0), 127);
|
||||
if (output) {
|
||||
const noteOnMessage = [0x90 + channel, note, velocity];
|
||||
output.send(noteOnMessage);
|
||||
} else {
|
||||
console.error("MIDI output not available.");
|
||||
}
|
||||
}
|
||||
|
||||
sendMidiOff(note: number, channel: number, port: number | string = this.currentOutputIndex) {
|
||||
/**
|
||||
* Sending Midi Note off message
|
||||
*/
|
||||
if(typeof port === "string") port = this.getMidiOutputIndex(port);
|
||||
const output = this.midiOutputs[port];
|
||||
note = Math.min(Math.max(note, 0), 127);
|
||||
if (output) {
|
||||
const noteOffMessage = [0x80 + channel, note, 0];
|
||||
output.send(noteOffMessage);
|
||||
} else {
|
||||
console.error("MIDI output not available.");
|
||||
}
|
||||
}
|
||||
|
||||
sendAllNotesOff(channel: number, port: number | string = this.currentOutputIndex) {
|
||||
/**
|
||||
* Sending Midi Note off message
|
||||
*/
|
||||
if(typeof port === "string") port = this.getMidiOutputIndex(port);
|
||||
const output = this.midiOutputs[port];
|
||||
if (output) {
|
||||
const noteOffMessage = [0xb0 + channel, 123, 0];
|
||||
output.send(noteOffMessage);
|
||||
} else {
|
||||
console.error("MIDI output not available.");
|
||||
}
|
||||
}
|
||||
|
||||
sendAllSoundOff(channel: number, port: number | string = this.currentOutputIndex) {
|
||||
/**
|
||||
* Sending all sound off
|
||||
*/
|
||||
if(typeof port === "string") port = this.getMidiOutputIndex(port);
|
||||
const output = this.midiOutputs[port];
|
||||
if (output) {
|
||||
const noteOffMessage = [0xb0 + channel, 120, 0];
|
||||
output.send(noteOffMessage);
|
||||
} else {
|
||||
console.error("MIDI output not available.");
|
||||
}
|
||||
}
|
||||
|
||||
public sendSysExMessage(message: number[]): void {
|
||||
/**
|
||||
* Sends a SysEx message to the currently selected MIDI output.
|
||||
|
||||
@ -149,5 +149,26 @@ beat(.25) :: sound('sine')
|
||||
`,
|
||||
true
|
||||
)}
|
||||
|
||||
## Scale output for lighted keys
|
||||
|
||||
Topos can output scales to external keyboards lighted keys using the following functions:
|
||||
|
||||
- <ic>show_scale(key: string, scale: string|int, channel?: number, port?: string|number, soundOff?: boolean): void</ic>: sends the scale as midi on messages to specified port and channel to light the keys of external keyboard. If soundOff is true, all sound off message will be sent after every note on message. This can be useful with some keyboards not supporting external channel for lightning or routing for the midi in to suppress the sound from incoming note on messages.
|
||||
|
||||
${makeExample(
|
||||
"Show scale on external keyboard",
|
||||
`show_scale("F","aeolian",0,4)`,
|
||||
true
|
||||
)}
|
||||
|
||||
${makeExample(
|
||||
"Hide scale",
|
||||
`hide_scale("F","aeolian",0,4)`,
|
||||
true
|
||||
)}
|
||||
|
||||
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
@ -1451,10 +1451,10 @@ yaml@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
|
||||
integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
|
||||
|
||||
zifferjs@^0.0.32:
|
||||
version "0.0.32"
|
||||
resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.32.tgz#825ab27f890f6fc9315e350e9d6b7ea40bcdaa3e"
|
||||
integrity sha512-jY7Jx1lFIa7+I606G0+SSYID5hUe8nYlzebtlLKmbuE1Fb1utReb6064auLcpUcRz+zoSBm2GDr6/JlZ4HpKJg==
|
||||
zifferjs@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.33.tgz#286e3c9ccaebe88d4acaad59f99db0cff5cc1884"
|
||||
integrity sha512-sYD4wOSKTip4GTkK3epMNAzlRWN3YpQlgR9sCGvyj6xdHzaaEHdU8F/PvkI092UbfYi4NNM/pVZKF1RLUlJPAw==
|
||||
|
||||
zzfx@^1.2.0:
|
||||
version "1.2.0"
|
||||
|
||||
Reference in New Issue
Block a user