Connecting evaluation mechanism again
This commit is contained in:
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
this.app.settings.send_clock ?? this.app.api.MidiConnection.sendMidiClock();
|
||||
tryEvaluate(
|
||||
this.app,
|
||||
this.app.exampleIsPlaying
|
||||
? this.app.example_buffer
|
||||
: this.app.global_buffer
|
||||
);
|
||||
}
|
||||
|
||||
const endTime = performance.now();
|
||||
const executionTime = endTime - startTime;
|
||||
console.log(`Execution time: ${executionTime}ms`);
|
||||
};
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
@ -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],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user