From 0b09f166248609b804554a06a8904805234988ee Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Sat, 20 Apr 2024 02:26:53 +0200 Subject: [PATCH] Connecting evaluation mechanism again --- src/classes/SoundEvent.ts | 4 +- src/clock/Clock.ts | 142 ++++++++++-------------------------- src/clock/ClockNode.js | 49 +++++-------- src/clock/ClockProcessor.js | 14 +++- 4 files changed, 73 insertions(+), 136 deletions(-) diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 321220f..6eb3c40 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -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); } }; diff --git a/src/clock/Clock.ts b/src/clock/Clock.ts index c45f1e1..cd42c7f 100644 --- a/src/clock/Clock.ts +++ b/src/clock/Clock.ts @@ -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() } + } diff --git a/src/clock/ClockNode.js b/src/clock/ClockNode.js index 373b4e6..3d0b8aa 100644 --- a/src/clock/ClockNode.js +++ b/src/clock/ClockNode.js @@ -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} */ 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 }); } diff --git a/src/clock/ClockProcessor.js b/src/clock/ClockProcessor.js index 252e00e..5f20cbe 100644 --- a/src/clock/ClockProcessor.js +++ b/src/clock/ClockProcessor.js @@ -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], }); } }