diff --git a/index.html b/index.html
index 5c4e15d..97244f8 100644
--- a/index.html
+++ b/index.html
@@ -265,7 +265,7 @@
diff --git a/src/IO/MidiConnection.ts b/src/IO/MidiConnection.ts
index a7fec62..d07fecf 100644
--- a/src/IO/MidiConnection.ts
+++ b/src/IO/MidiConnection.ts
@@ -22,13 +22,13 @@ export class MidiConnection {
private scheduledNotes: { [noteNumber: number]: number } = {}; // { noteNumber: timeoutId }
/* MIDI clock stuff */
+ private midiClockInputIndex: number|undefined = undefined;
private midiClockInput?: MIDIInput|undefined = undefined;
private lastTimestamp: number = 0;
private midiClockDelta: number = 0;
private lastBPM: number;
private roundedBPM: number = 0;
private clockBuffer: number[] = [];
- private deltaBuffer: number[] = [];
private clockBufferLength = 24;
private clockTicks = 0;
private clockErrorCount = 0;
@@ -59,7 +59,7 @@ export class MidiConnection {
if (this.midiInputs.length === 0) {
console.warn("No MIDI inputs available.");
} else {
- this.updateMidiClockSelect();
+ this.updateInputSelects();
}
} catch (error) {
console.error("Failed to initialize MIDI:", error);
@@ -134,14 +134,15 @@ export class MidiConnection {
*/
const inputIndex = this.getMidiInputIndex(inputName);
if (inputIndex !== -1) {
+ this.midiClockInputIndex = inputIndex;
this.midiClockInput = this.midiInputs[inputIndex];
- this.registerMidiClockListener();
+ this.registerMidiInputListener(inputIndex);
} else {
this.midiClockInput = undefined;
}
}
- public updateMidiClockSelect() {
+ public updateInputSelects() {
/**
* Updates the MIDI clock input select element with the available MIDI inputs.
*/
@@ -152,12 +153,18 @@ export class MidiConnection {
midiClockSelect.innerHTML = "";
midiInputSelect.innerHTML = "";
- // Defaults to internal clock
+ // Set Midi clock as Internal by default
const defaultOption = document.createElement("option");
defaultOption.value = "-1";
defaultOption.text = "Internal";
midiClockSelect.appendChild(defaultOption);
+ // Set default input as None by default
+ const defaultInputOption = document.createElement("option");
+ defaultInputOption.value = "-1";
+ defaultInputOption.text = "None";
+ midiInputSelect.appendChild(defaultInputOption);
+
// Add MIDI inputs to clock select input and default midi input
this.midiInputs.forEach((input, index) => {
const option = document.createElement("option");
@@ -172,7 +179,7 @@ export class MidiConnection {
midiClockSelect.value = clockMidiInputIndex.toString();
if(clockMidiInputIndex > 0) {
this.midiClockInput = this.midiInputs[clockMidiInputIndex];
- this.registerMidiClockListener();
+ this.registerMidiInputListener(clockMidiInputIndex);
}
} else {
midiClockSelect.value = "-1";
@@ -183,24 +190,25 @@ export class MidiConnection {
midiInputSelect.value = defaultMidiInputIndex.toString();
if(defaultMidiInputIndex > 0) {
this.currentInputIndex = defaultMidiInputIndex;
- this.registerMidiInputListener();
+ this.registerMidiInputListener(defaultMidiInputIndex);
}
} else {
- midiInputSelect.value = "";
+ midiInputSelect.value = "-1";
}
// Add midi clock listener
midiClockSelect.addEventListener("change", (event) => {
const value = (event.target as HTMLSelectElement).value;
if(value === "-1") {
- if(this.midiClockInput) this.midiClockInput.onmidimessage = null;
+ if(this.midiClockInput && this.midiClockInputIndex!=this.currentInputIndex) this.midiClockInput.onmidimessage = null;
this.midiClockInput = undefined;
this.settings.midi_clock_input = undefined;
} else {
const clockInputIndex = parseInt(value);
- if(this.midiClockInput) this.midiClockInput.onmidimessage = null;
+ this.midiClockInputIndex = clockInputIndex;
+ if(this.midiClockInput && this.midiClockInputIndex!=this.currentInputIndex) this.midiClockInput.onmidimessage = null;
this.midiClockInput = this.midiInputs[clockInputIndex];
- this.registerMidiClockListener();
+ this.registerMidiInputListener(clockInputIndex);
this.settings.midi_clock_input = this.midiClockInput.name || undefined;
}
});
@@ -208,10 +216,14 @@ export class MidiConnection {
// Add mini input listener
midiInputSelect.addEventListener("change", (event) => {
const value = (event.target as HTMLSelectElement).value;
- if(value) {
- this.unregisterMidiInputListener();
+ if(value === "-1") {
+ if(this.currentInputIndex && this.currentInputIndex!=this.midiClockInputIndex) this.unregisterMidiInputListener(this.currentInputIndex);
+ this.currentInputIndex = undefined;
+ this.settings.default_midi_input = undefined;
+ } else {
+ if(this.currentInputIndex && this.currentInputIndex!=this.midiClockInputIndex) this.unregisterMidiInputListener(this.currentInputIndex);
this.currentInputIndex = parseInt(value);
- this.registerMidiInputListener();
+ this.registerMidiInputListener(this.currentInputIndex);
this.settings.default_midi_input = this.midiInputs[this.currentInputIndex].name || undefined;
}
});
@@ -219,71 +231,62 @@ export class MidiConnection {
}
}
- public registerMidiClockListener(): void {
- /**
- * Registers a listener for MIDI clock messages on the currently selected MIDI input.
- */
- if (this.midiClockInput) {
- this.midiClockInput.onmidimessage = (event: Event) => {
- const message = event as MIDIMessageEvent;
- if (message.data[0] === 0xf8) {
- if(this.skipOnError>0) {
- this.skipOnError -= 1;
- } else {
- this.onMidiClock(event.timeStamp);
- }
- } else if(message.data[0] === 0xfa) {
- console.log("MIDI start received");
- this.api.stop();
- this.api.play();
- } else if(message.data[0] === 0xfc) {
- console.log("MIDI stop received");
- this.api.pause();
- } else if(message.data[0] === 0xfb) {
- console.log("MIDI continue received");
- this.api.play();
- } else if(message.data[0] === 0xfe) {
- console.log("MIDI active sensing received");
- } else {
- // Ignore other MIDI messages
- // console.log("Ignored MIDI message: ", message.data[0], message.data[1]);
- }
- }
- }
- }
-
- public registerMidiInputListener(): void {
+ public registerMidiInputListener(inputIndex: number): void {
/**
* Register midi input listener and store last value as global parameter named channel_{number}
*/
- if(this.currentInputIndex !== undefined) {
- const input = this.midiInputs[this.currentInputIndex];
- if(input) {
+ if(inputIndex !== undefined) {
+ const input = this.midiInputs[inputIndex];
+ if(input && !input.onmidimessage) {
input.onmidimessage = (event: Event) => {
const message = event as MIDIMessageEvent;
-
- // List of all note_on messages from channels 1-16
- const all_note_ons = [0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,0x9E, 0x9F];
- // If message is one of note ons
- if(all_note_ons.indexOf(message.data[0]) !== -1) {
- const channel = all_note_ons.indexOf(message.data[0])+1;
- const note = message.data[1];
- const velocity = message.data[2];
- this.api.variable(`channel_${channel}_note`, note);
- this.api.variable(`channel_${channel}_velocity`, velocity);
- if(this.settings.midi_channels_scripts) this.api.script(channel);
+ /* MIDI CLOCK */
+ if(input.name === this.settings.midi_clock_input) {
+ if (message.data[0] === 0xf8) {
+ if(this.skipOnError>0) {
+ this.skipOnError -= 1;
+ } else {
+ this.onMidiClock(event.timeStamp);
+ }
+ } else if(message.data[0] === 0xfa) {
+ console.log("MIDI start received");
+ this.api.stop();
+ this.api.play();
+ } else if(message.data[0] === 0xfc) {
+ console.log("MIDI stop received");
+ this.api.pause();
+ } else if(message.data[0] === 0xfb) {
+ console.log("MIDI continue received");
+ this.api.play();
+ } else if(message.data[0] === 0xfe) {
+ console.log("MIDI active sensing received");
+ }
+ }
+ /* DEFAULT MIDI INPUT */
+ if(input.name === this.settings.default_midi_input) {
+ // List of all note_on messages from channels 1-16
+ const all_note_ons = [0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,0x9E, 0x9F];
+ // If message is one of note ons
+ if(all_note_ons.indexOf(message.data[0]) !== -1) {
+ const channel = all_note_ons.indexOf(message.data[0])+1;
+ const note = message.data[1];
+ const velocity = message.data[2];
+ this.api.variable(`channel_${channel}_note`, note);
+ this.api.variable(`channel_${channel}_velocity`, velocity);
+ if(this.settings.midi_channels_scripts) this.api.script(channel);
+ }
}
}
}
}
}
- public unregisterMidiInputListener(): void {
+ public unregisterMidiInputListener(inputIndex: number): void {
/**
* Unregister midi input listener
*/
- if(this.currentInputIndex !== undefined) {
- const input = this.midiInputs[this.currentInputIndex];
+ if(inputIndex !== undefined) {
+ const input = this.midiInputs[inputIndex];
if(input) {
input.onmidimessage = null;
}
@@ -311,7 +314,6 @@ export class MidiConnection {
console.log("Last delta: ", this.midiClockDelta);
console.log("Current delta: ", timestamp - this.lastTimestamp);
console.log("BPMs", this.clockBuffer);
- console.log("Deltas", this.deltaBuffer);
this.clockErrorCount = 0;
/* I dont know why this happens. But when it does, deltas for the following messages are off.
So skipping ~ quarted of clock resolution usually helps */