improving midi clock ever so slightly
This commit is contained in:
13
src/Clock.ts
13
src/Clock.ts
@ -127,7 +127,7 @@ export class Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set bpm(bpm: number) {
|
set bpm(bpm: number) {
|
||||||
if(bpm>0 && this._bpm !== bpm) {
|
if (bpm > 0 && this._bpm !== bpm) {
|
||||||
this._bpm = bpm;
|
this._bpm = bpm;
|
||||||
this.transportNode?.setBPM(bpm);
|
this.transportNode?.setBPM(bpm);
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ export class Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set ppqn(ppqn: number) {
|
set ppqn(ppqn: number) {
|
||||||
if(ppqn>0 && this._ppqn !== ppqn) {
|
if (ppqn > 0 && this._ppqn !== ppqn) {
|
||||||
this._ppqn = ppqn;
|
this._ppqn = ppqn;
|
||||||
this.transportNode?.setPPQN(ppqn);
|
this.transportNode?.setPPQN(ppqn);
|
||||||
}
|
}
|
||||||
@ -154,23 +154,32 @@ export class Clock {
|
|||||||
public start(): void {
|
public start(): void {
|
||||||
/**
|
/**
|
||||||
* Starts the TransportNode (starts the clock).
|
* Starts the TransportNode (starts the clock).
|
||||||
|
*
|
||||||
|
* @remark also sends a MIDI message if a port is declared
|
||||||
*/
|
*/
|
||||||
this.app.audioContext.resume();
|
this.app.audioContext.resume();
|
||||||
|
this.app.api.MidiConnection.sendStartMessage();
|
||||||
this.transportNode?.start();
|
this.transportNode?.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public pause(): void {
|
public pause(): void {
|
||||||
/**
|
/**
|
||||||
* Pauses the TransportNode (pauses the clock).
|
* Pauses the TransportNode (pauses the clock).
|
||||||
|
*
|
||||||
|
* @remark also sends a MIDI message if a port is declared
|
||||||
*/
|
*/
|
||||||
this.transportNode?.pause();
|
this.transportNode?.pause();
|
||||||
|
this.app.api.MidiConnection.sendStopMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public stop(): void {
|
public stop(): void {
|
||||||
/**
|
/**
|
||||||
* Stops the TransportNode (stops the clock).
|
* Stops the TransportNode (stops the clock).
|
||||||
|
*
|
||||||
|
* @remark also sends a MIDI message if a port is declared
|
||||||
*/
|
*/
|
||||||
this.app.clock.tick = -1;
|
this.app.clock.tick = -1;
|
||||||
|
this.app.api.MidiConnection.sendStopMessage();
|
||||||
this.transportNode?.stop();
|
this.transportNode?.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,26 @@ export class MidiConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sendStartMessage(): void {
|
||||||
|
/**
|
||||||
|
* Sends a MIDI Start message to the currently selected MIDI output.
|
||||||
|
*/
|
||||||
|
const output = this.midiOutputs[this.currentOutputIndex];
|
||||||
|
if (output) {
|
||||||
|
output.send([0xfa]); // Send MIDI Start message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sendStopMessage(): void {
|
||||||
|
/**
|
||||||
|
* Sends a MIDI Stop message to the currently selected MIDI output.
|
||||||
|
*/
|
||||||
|
const output = this.midiOutputs[this.currentOutputIndex];
|
||||||
|
if (output) {
|
||||||
|
output.send([0xfc]); // Send MIDI Stop message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public getCurrentMidiPortIndex(): number {
|
public getCurrentMidiPortIndex(): number {
|
||||||
/**
|
/**
|
||||||
* Returns the index of the currently selected MIDI output.
|
* Returns the index of the currently selected MIDI output.
|
||||||
@ -79,8 +99,6 @@ export class MidiConnection {
|
|||||||
const output = this.midiOutputs[this.currentOutputIndex];
|
const output = this.midiOutputs[this.currentOutputIndex];
|
||||||
if (output) {
|
if (output) {
|
||||||
output.send([0xf8]); // Send a single MIDI clock message
|
output.send([0xf8]); // Send a single MIDI clock message
|
||||||
} else {
|
|
||||||
console.error("MIDI output not available.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,53 +1,52 @@
|
|||||||
import { tryEvaluate } from "./Evaluator";
|
import { tryEvaluate } from "./Evaluator";
|
||||||
const zeroPad = (num, places) => String(num).padStart(places, '0')
|
const zeroPad = (num, places) => String(num).padStart(places, "0");
|
||||||
|
|
||||||
export class TransportNode extends AudioWorkletNode {
|
export class TransportNode extends AudioWorkletNode {
|
||||||
|
constructor(context, options, application) {
|
||||||
|
super(context, "transport", options);
|
||||||
|
this.app = application;
|
||||||
|
this.port.addEventListener("message", this.handleMessage);
|
||||||
|
this.port.start();
|
||||||
|
this.timeviewer = document.getElementById("timeviewer");
|
||||||
|
}
|
||||||
|
|
||||||
constructor(context, options, application) {
|
/** @type {(this: MessagePort, ev: MessageEvent<any>) => any} */
|
||||||
super(context, "transport", options);
|
handleMessage = (message) => {
|
||||||
this.app = application
|
if (message.data && message.data.type === "bang") {
|
||||||
this.port.addEventListener("message", this.handleMessage);
|
this.app.clock.tick++;
|
||||||
this.port.start();
|
const futureTimeStamp = this.app.clock.convertTicksToTimeposition(
|
||||||
this.timeviewer = document.getElementById("timeviewer");
|
this.app.clock.tick
|
||||||
|
);
|
||||||
|
this.app.clock.time_position = futureTimeStamp;
|
||||||
|
this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${
|
||||||
|
futureTimeStamp.beat + 1
|
||||||
|
}:${zeroPad(futureTimeStamp.pulse, 2)}`;
|
||||||
|
this.app.api.MidiConnection.sendMidiClock();
|
||||||
|
if (this.app.exampleIsPlaying) {
|
||||||
|
tryEvaluate(this.app, this.app.example_buffer);
|
||||||
|
} else {
|
||||||
|
tryEvaluate(this.app, this.app.global_buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** @type {(this: MessagePort, ev: MessageEvent<any>) => any} */
|
start() {
|
||||||
handleMessage = (message) => {
|
this.port.postMessage("start");
|
||||||
if (message.data && message.data.type === "bang") {
|
}
|
||||||
|
|
||||||
this.app.clock.tick++
|
pause() {
|
||||||
const futureTimeStamp = this.app.clock.convertTicksToTimeposition(this.app.clock.tick);
|
this.port.postMessage("pause");
|
||||||
this.app.clock.time_position = futureTimeStamp;
|
}
|
||||||
this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${futureTimeStamp.beat+1}:${zeroPad(futureTimeStamp.pulse, 2)}`;
|
|
||||||
|
|
||||||
if (this.app.exampleIsPlaying) {
|
|
||||||
tryEvaluate(this.app, this.app.example_buffer);
|
|
||||||
} else {
|
|
||||||
tryEvaluate(this.app, this.app.global_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
setBPM(bpm) {
|
||||||
|
this.port.postMessage({ type: "bpm", value: bpm });
|
||||||
|
}
|
||||||
|
|
||||||
start() {
|
setPPQN(ppqn) {
|
||||||
this.port.postMessage("start");
|
this.port.postMessage({ type: "ppqn", value: ppqn });
|
||||||
}
|
}
|
||||||
|
|
||||||
pause() {
|
|
||||||
this.port.postMessage("pause");
|
|
||||||
}
|
|
||||||
|
|
||||||
setBPM(bpm) {
|
|
||||||
this.port.postMessage({ type: "bpm", value: bpm });
|
|
||||||
}
|
|
||||||
|
|
||||||
setPPQN(ppqn) {
|
|
||||||
this.port.postMessage({ type: "ppqn", value: ppqn });
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
this.port.postMessage("stop");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
this.port.postMessage("stop");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/main.ts
12
src/main.ts
@ -66,8 +66,6 @@ const bindings = Object.keys(classMap).map((key) => ({
|
|||||||
replace: (match, p1) => `<${key} class="${classMap[key]}" ${p1}>`,
|
replace: (match, p1) => `<${key} class="${classMap[key]}" ${p1}>`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class Editor {
|
export class Editor {
|
||||||
universes: Universes = template_universes;
|
universes: Universes = template_universes;
|
||||||
selected_universe: string;
|
selected_universe: string;
|
||||||
@ -487,10 +485,12 @@ export class Editor {
|
|||||||
this.setButtonHighlighting("pause", true);
|
this.setButtonHighlighting("pause", true);
|
||||||
this.isPlaying = !this.isPlaying;
|
this.isPlaying = !this.isPlaying;
|
||||||
this.clock.pause();
|
this.clock.pause();
|
||||||
|
this.api.MidiConnection.sendStopMessage();
|
||||||
} else {
|
} else {
|
||||||
this.setButtonHighlighting("play", true);
|
this.setButtonHighlighting("play", true);
|
||||||
this.isPlaying = !this.isPlaying;
|
this.isPlaying = !this.isPlaying;
|
||||||
this.clock.start();
|
this.clock.start();
|
||||||
|
this.api.MidiConnection.sendStartMessage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -562,12 +562,16 @@ export class Editor {
|
|||||||
|
|
||||||
if (this.settings.vimMode) {
|
if (this.settings.vimMode) {
|
||||||
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
||||||
let normal = document.getElementById("normal-mode-radio") as HTMLInputElement;
|
let normal = document.getElementById(
|
||||||
|
"normal-mode-radio"
|
||||||
|
) as HTMLInputElement;
|
||||||
vim.checked = true;
|
vim.checked = true;
|
||||||
normal.checked = false;
|
normal.checked = false;
|
||||||
} else {
|
} else {
|
||||||
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
|
||||||
let normal = document.getElementById("normal-mode-radio") as HTMLInputElement;
|
let normal = document.getElementById(
|
||||||
|
"normal-mode-radio"
|
||||||
|
) as HTMLInputElement;
|
||||||
normal.checked = true;
|
normal.checked = true;
|
||||||
vim.checked = false;
|
vim.checked = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user