Connecting evaluation mechanism again

This commit is contained in:
2024-04-20 02:26:53 +02:00
parent 2304015975
commit 0b09f16624
4 changed files with 73 additions and 136 deletions

View File

@ -451,7 +451,7 @@ export class SoundEvent extends AudibleEvent {
} }
superdough( superdough(
filteredEvent, filteredEvent,
this.nudge - this.app.clock.deviation, 0.2,
filteredEvent['dur'] filteredEvent['dur']
); );
} }
@ -477,7 +477,7 @@ export class SoundEvent extends AudibleEvent {
address: oscAddress, address: oscAddress,
port: oscPort, port: oscPort,
args: event, args: event,
timetag: Math.round(Date.now() + (this.nudge - this.app.clock.deviation)), timetag: Math.round(Date.now()),
} as OSCMessage); } as OSCMessage);
} }
}; };

View File

@ -1,54 +1,43 @@
import { TransportNode } from "./ClockNode"; import { ClockNode } from "./ClockNode";
import TransportProcessor from "./ClockProcessor?worker&url"; import TransportProcessor from "./ClockProcessor?worker&url";
import { Editor } from "../main"; import { Editor } from "../main";
export interface TimePosition { export interface TimePosition {
/** bpm: number;
* A position in time. ppqn: number;
* time: number;
* @param bar - The bar number
* @param beat - The beat number
* @param pulse - The pulse number
*/
bar: number;
beat: number;
tick: number; tick: number;
beat: number;
bar: number;
num: number;
den: number;
} }
export class Clock { export class Clock {
ctx: AudioContext; ctx: AudioContext;
logicalTime: number; transportNode: ClockNode | null;
transportNode: TransportNode | null;
private _bpm: number;
time_signature: number[];
time_position: TimePosition; time_position: TimePosition;
private _ppqn: number;
tick: number;
running: boolean;
lastPauseTime: number;
lastPlayPressTime: number;
totalPauseTime: number;
constructor( constructor(
public app: Editor, public app: Editor,
ctx: AudioContext, ctx: AudioContext,
) { ) {
this.time_position = { bar: 0, beat: 0, tick: 0 }; this.time_position = {
this.time_signature = [4, 4]; bpm: 0,
this.logicalTime = 0; time: 0,
this.tick = 0; ppqn: 0,
this._bpm = 120; tick: 0,
this._ppqn = 48 * 2; beat: 0,
bar: 0,
num: 0,
den: 0,
};
this.transportNode = null; this.transportNode = null;
this.ctx = ctx; this.ctx = ctx;
this.running = true;
this.lastPauseTime = 0;
this.lastPlayPressTime = 0;
this.totalPauseTime = 0;
ctx.audioWorklet ctx.audioWorklet
.addModule(TransportProcessor) .addModule(TransportProcessor)
.then((e) => { .then((e) => {
this.transportNode = new TransportNode(ctx, {}, this.app); this.transportNode = new ClockNode(ctx, {}, this.app);
this.transportNode.connect(ctx.destination); this.transportNode.connect(ctx.destination);
return e; return e;
}) })
@ -57,17 +46,6 @@ export class Clock {
}); });
} }
convertTicksToTimeposition(ticks: number): TimePosition {
const beatsPerBar = this.app.clock.time_signature[0]!;
const tickPosition = ticks % this.app.clock.ppqn;
const beatNumber = Math.floor(ticks / this.app.clock.ppqn);
const barNumber = Math.floor(beatNumber / beatsPerBar);
const beatWithinBar = Math.floor(beatNumber % beatsPerBar);
return { bar: barNumber, beat: beatWithinBar, tick: tickPosition };
}
get ticks_before_new_bar(): number { get ticks_before_new_bar(): number {
/** /**
* This function returns the number of ticks separating the current moment * This function returns the number of ticks separating the current moment
@ -75,9 +53,9 @@ export class Clock {
* *
* @returns number of ticks until next bar * @returns number of ticks until next bar
*/ */
const ticskMissingFromBeat = this.ppqn - this.time_position.tick; const ticksMissingFromBeat = this.ppqn - this.time_position.tick;
const beatsMissingFromBar = this.beats_per_bar - this.time_position.beat; const beatsMissingFromBar = this.beats_per_bar - this.time_position.beat;
return beatsMissingFromBar * this.ppqn + ticskMissingFromBeat; return beatsMissingFromBar * this.ppqn + ticksMissingFromBeat;
} }
get next_beat_in_ticks(): number { get next_beat_in_ticks(): number {
@ -94,7 +72,7 @@ export class Clock {
/** /**
* Returns the number of beats per bar. * Returns the number of beats per bar.
*/ */
return this.time_signature[0] || 4; return this.time_position.num;
} }
get beats_since_origin(): number { get beats_since_origin(): number {
@ -103,7 +81,7 @@ export class Clock {
* *
* @returns number of beats since origin * @returns number of beats since origin
*/ */
return Math.floor(this.tick / this.ppqn); return Math.floor(this.time_position.tick / this.ppqn)
} }
get pulses_since_origin(): number { get pulses_since_origin(): number {
@ -112,69 +90,43 @@ export class Clock {
* *
* @returns number of pulses since origin * @returns number of pulses since origin
*/ */
return this.tick; return this.time_position.tick;
} }
get pulse_duration(): number { get pulse_duration(): number {
/** /**
* Returns the duration of a pulse in seconds. * Returns the duration of a pulse in seconds.
*/ */
return 60 / this.bpm / this.ppqn; return 60 / this.time_position.bpm / this.time_position.ppqn;
} }
public pulse_duration_at_bpm(bpm: number = this.bpm): number { public pulse_duration_at_bpm(bpm: number = this.bpm): number {
/** /**
* Returns the duration of a pulse in seconds at a specific bpm. * Returns the duration of a pulse in seconds at a specific bpm.
*/ */
return 60 / bpm / this.ppqn; return 60 / bpm / this.time_position.ppqn;
} }
get bpm(): number { get bpm(): number {
return this._bpm; return this.time_position.bpm;
}
set nudge(nudge: number) {
this.transportNode?.setNudge(nudge);
} }
set bpm(bpm: number) { set bpm(bpm: number) {
if (bpm > 0 && this._bpm !== bpm) { if (bpm > 0 && this.time_position.bpm !== bpm) {
this.transportNode?.setBPM(bpm); this.transportNode?.setBPM(bpm);
this._bpm = bpm;
this.logicalTime = this.realTime;
} }
} }
get ppqn(): number { get ppqn(): number {
return this._ppqn; return this.time_position.ppqn;
}
get realTime(): number {
return this.app.audioContext.currentTime - this.totalPauseTime;
}
get deviation(): number {
return Math.abs(this.logicalTime - this.realTime);
} }
set ppqn(ppqn: number) { set ppqn(ppqn: number) {
if (ppqn > 0 && this._ppqn !== ppqn) { if (ppqn > 0 && this.ppqn !== ppqn) {
this._ppqn = ppqn;
this.transportNode?.setPPQN(ppqn); this.transportNode?.setPPQN(ppqn);
this.logicalTime = this.tick * this.pulse_duration_at_bpm(this.bpm);
} }
} }
public incrementTick(bpm: number) {
/**
* Increment the clock tick by 1.
* @param bpm - The current beats per minute value
* @returns void
*/
this.tick++;
this.logicalTime += this.pulse_duration_at_bpm(bpm);
}
public nextTickFrom(time: number, nudge: number): number { public nextTickFrom(time: number, nudge: number): number {
/** /**
* Compute the time remaining before the next clock tick. * Compute the time remaining before the next clock tick.
@ -203,39 +155,21 @@ export class Clock {
* *
* @remark also sends a MIDI message if a port is declared * @remark also sends a MIDI message if a port is declared
*/ */
this.app.audioContext.resume();
this.running = true;
this.app.api.MidiConnection.sendStartMessage(); this.app.api.MidiConnection.sendStartMessage();
this.lastPlayPressTime = this.app.audioContext.currentTime;
this.totalPauseTime += this.lastPlayPressTime - this.lastPauseTime;
this.transportNode?.start(); this.transportNode?.start();
} }
public pause(): void { public pause(): void {
/**
* Pauses the TransportNode (pauses the clock).
*
* @remark also sends a MIDI message if a port is declared
*/
this.running = false;
this.transportNode?.pause();
this.app.api.MidiConnection.sendStopMessage(); this.app.api.MidiConnection.sendStopMessage();
this.lastPauseTime = this.app.audioContext.currentTime; this.transportNode?.pause()
this.logicalTime = this.realTime; }
public signature(num: number, den: number): void {
this.transportNode?.setSignature(num, den);
} }
public stop(): void { public stop(): void {
/** this.transportNode?.stop()
* Stops the TransportNode (stops the clock).
*
* @remark also sends a MIDI message if a port is declared
*/
this.running = false;
this.tick = 0;
this.lastPauseTime = this.app.audioContext.currentTime;
this.logicalTime = this.realTime;
this.time_position = { bar: 0, beat: 0, tick: 0 };
this.app.api.MidiConnection.sendStopMessage();
this.transportNode?.stop();
} }
} }

View File

@ -1,6 +1,6 @@
import { tryEvaluate } from "../Evaluator"; import { tryEvaluate } from "../Evaluator";
export class TransportNode extends AudioWorkletNode { export class ClockNode extends AudioWorkletNode {
constructor(context, options, application) { constructor(context, options, application) {
super(context, "transport", options); super(context, "transport", options);
@ -13,39 +13,25 @@ export class TransportNode extends AudioWorkletNode {
/** @type {(this: MessagePort, ev: MessageEvent<any>) => any} */ /** @type {(this: MessagePort, ev: MessageEvent<any>) => any} */
handleMessage = (message) => { handleMessage = (message) => {
let clock = this.app.clock; let clock = this.app.clock;
const startTime = performance.now();
if (message.data.type === "time") { if (message.data.type === "time") {
console.log(message.data)
clock.time_position = { clock.time_position = {
bpm: message.data.bpm,
ppqn: message.data.ppqn,
time: message.data.time,
tick: message.data.tick, tick: message.data.tick,
beat: message.data.beat, beat: message.data.beat,
bar: message.data.bar, bar: message.data.bar,
time: message.data.time, num: message.data.num,
den: message.data.den,
} }
}
if (message.data.type === "bang") {
if (this.app.clock.running) {
clock.time_position = clock.convertTicksToTimeposition(clock.tick);
this.app.settings.send_clock ?? this.app.api.MidiConnection.sendMidiClock(); this.app.settings.send_clock ?? this.app.api.MidiConnection.sendMidiClock();
tryEvaluate( tryEvaluate(
this.app, this.app,
this.app.exampleIsPlaying this.app.exampleIsPlaying
? this.app.example_buffer ? this.app.example_buffer
: this.app.global_buffer : this.app.global_buffer
); );
clock.incrementTick(message.data.bpm);
} }
}
const endTime = performance.now();
const executionTime = endTime - startTime;
console.log(`Execution time: ${executionTime}ms`);
}; };
start() { start() {
@ -61,6 +47,7 @@ export class TransportNode extends AudioWorkletNode {
} }
setBPM(bpm) { setBPM(bpm) {
console.log("Changement du bpm")
this.port.postMessage({ type: "bpm", value: bpm }); this.port.postMessage({ type: "bpm", value: bpm });
} }
@ -68,6 +55,10 @@ export class TransportNode extends AudioWorkletNode {
this.port.postMessage({ type: "ppqn", value: ppqn }); this.port.postMessage({ type: "ppqn", value: ppqn });
} }
setSignature(num, den) {
this.port.postMessage({ type: "timeSignature", num: num, den: den });
}
setNudge(nudge) { setNudge(nudge) {
this.port.postMessage({ type: "nudge", value: nudge }); this.port.postMessage({ type: "nudge", value: nudge });
} }

View File

@ -1,3 +1,5 @@
import { blinkScript } from "../DOM/Visuals/Blinkers";
class TransportProcessor extends AudioWorkletProcessor { class TransportProcessor extends AudioWorkletProcessor {
constructor(options) { constructor(options) {
super(options); super(options);
@ -38,6 +40,11 @@ class TransportProcessor extends AudioWorkletProcessor {
this.bpm = message.data.value; this.bpm = message.data.value;
} else if (message.data.type === "ppqn") { } else if (message.data.type === "ppqn") {
this.ppqn = message.data.value; this.ppqn = message.data.value;
} else if (message.data.type === "timeSignature") {
this.timeSignature = [
message.data.num,
message.data.den
]
} else if (message.data.type === "nudge") { } else if (message.data.type === "nudge") {
this.nudge = message.data.value; this.nudge = message.data.value;
} else if (message.data.type === "timeSignature") { } else if (message.data.type === "timeSignature") {
@ -64,11 +71,16 @@ class TransportProcessor extends AudioWorkletProcessor {
const currentBar = Math.floor(this.currentPulsePosition / ticksPerBar); const currentBar = Math.floor(this.currentPulsePosition / ticksPerBar);
this.port.postMessage({ this.port.postMessage({
bpm: this.bpm,
ppqn: this.ppqn,
type: 'time', type: 'time',
time: currentTime, time: currentTime,
tick: currentTick, tick: currentTick,
beat: currentBeat, beat: currentBeat,
bar: currentBar bar: currentBar,
bpm: this.bpm,
num: this.timeSignature[0],
den: this.timeSignature[1],
}); });
} }
} }