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

View File

@ -1,54 +1,43 @@
import { TransportNode } from "./ClockNode";
import { ClockNode } from "./ClockNode";
import TransportProcessor from "./ClockProcessor?worker&url";
import { Editor } from "../main";
export interface TimePosition {
/**
* A position in time.
*
* @param bar - The bar number
* @param beat - The beat number
* @param pulse - The pulse number
*/
bar: number;
beat: number;
bpm: number;
ppqn: number;
time: number;
tick: number;
beat: number;
bar: number;
num: number;
den: number;
}
export class Clock {
ctx: AudioContext;
logicalTime: number;
transportNode: TransportNode | null;
private _bpm: number;
time_signature: number[];
transportNode: ClockNode | null;
time_position: TimePosition;
private _ppqn: number;
tick: number;
running: boolean;
lastPauseTime: number;
lastPlayPressTime: number;
totalPauseTime: number;
constructor(
public app: Editor,
ctx: AudioContext,
) {
this.time_position = { bar: 0, beat: 0, tick: 0 };
this.time_signature = [4, 4];
this.logicalTime = 0;
this.tick = 0;
this._bpm = 120;
this._ppqn = 48 * 2;
this.time_position = {
bpm: 0,
time: 0,
ppqn: 0,
tick: 0,
beat: 0,
bar: 0,
num: 0,
den: 0,
};
this.transportNode = null;
this.ctx = ctx;
this.running = true;
this.lastPauseTime = 0;
this.lastPlayPressTime = 0;
this.totalPauseTime = 0;
ctx.audioWorklet
.addModule(TransportProcessor)
.then((e) => {
this.transportNode = new TransportNode(ctx, {}, this.app);
this.transportNode = new ClockNode(ctx, {}, this.app);
this.transportNode.connect(ctx.destination);
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 {
/**
* 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
*/
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;
return beatsMissingFromBar * this.ppqn + ticskMissingFromBeat;
return beatsMissingFromBar * this.ppqn + ticksMissingFromBeat;
}
get next_beat_in_ticks(): number {
@ -94,7 +72,7 @@ export class Clock {
/**
* Returns the number of beats per bar.
*/
return this.time_signature[0] || 4;
return this.time_position.num;
}
get beats_since_origin(): number {
@ -103,7 +81,7 @@ export class Clock {
*
* @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 {
@ -112,69 +90,43 @@ export class Clock {
*
* @returns number of pulses since origin
*/
return this.tick;
return this.time_position.tick;
}
get pulse_duration(): number {
/**
* 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 {
/**
* 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 {
return this._bpm;
}
set nudge(nudge: number) {
this.transportNode?.setNudge(nudge);
return this.time_position.bpm;
}
set bpm(bpm: number) {
if (bpm > 0 && this._bpm !== bpm) {
if (bpm > 0 && this.time_position.bpm !== bpm) {
this.transportNode?.setBPM(bpm);
this._bpm = bpm;
this.logicalTime = this.realTime;
}
}
get ppqn(): number {
return this._ppqn;
}
get realTime(): number {
return this.app.audioContext.currentTime - this.totalPauseTime;
}
get deviation(): number {
return Math.abs(this.logicalTime - this.realTime);
return this.time_position.ppqn;
}
set ppqn(ppqn: number) {
if (ppqn > 0 && this._ppqn !== ppqn) {
this._ppqn = ppqn;
if (ppqn > 0 && this.ppqn !== 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 {
/**
* 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
*/
this.app.audioContext.resume();
this.running = true;
this.app.api.MidiConnection.sendStartMessage();
this.lastPlayPressTime = this.app.audioContext.currentTime;
this.totalPauseTime += this.lastPlayPressTime - this.lastPauseTime;
this.transportNode?.start();
}
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.lastPauseTime = this.app.audioContext.currentTime;
this.logicalTime = this.realTime;
this.transportNode?.pause()
}
public signature(num: number, den: number): void {
this.transportNode?.setSignature(num, den);
}
public stop(): void {
/**
* 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();
this.transportNode?.stop()
}
}

View File

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

View File

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