From fd54c0fd82bd247a694363343846e6c90f7a1b81 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 09:48:24 +0200 Subject: [PATCH 01/22] adding elapsed time, missing pause/resume mechanism --- src/Clock.ts | 3 +++ src/TransportNode.js | 8 +++++--- src/TransportProcessor.js | 3 +++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index a2ed80b..053db67 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -23,6 +23,7 @@ export class Clock { * * @param app - The main application instance * @param ctx - The current AudioContext used by app + * @param elapsed - Time elapsed since play been pressed * @param transportNode - The TransportNode helper * @param bpm - The current beats per minute value * @param time_signature - The time signature @@ -32,6 +33,7 @@ export class Clock { */ ctx: AudioContext; + elapsed: number transportNode: TransportNode | null; private _bpm: number; time_signature: number[]; @@ -42,6 +44,7 @@ export class Clock { constructor(public app: Editor, ctx: AudioContext) { this.time_position = { bar: -1, beat: -1, pulse: -1 }; this.time_signature = [4, 4]; + this.elapsed = 0; this.tick = -1; this._bpm = 120; this._ppqn = 48; diff --git a/src/TransportNode.js b/src/TransportNode.js index 32e6939..e206a0d 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -12,6 +12,9 @@ export class TransportNode extends AudioWorkletNode { /** @type {(this: MessagePort, ev: MessageEvent) => any} */ handleMessage = (message) => { + if (message.data && message.data.type === "elapsed") { + this.app.clock.elapsed = message.data.value + } if (message.data && message.data.type === "bang") { if (this.app.settings.send_clock) this.app.api.MidiConnection.sendMidiClock(); @@ -20,9 +23,8 @@ export class TransportNode extends AudioWorkletNode { 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.clock.bpm}`; + this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${futureTimeStamp.beat + 1 + }:${zeroPad(futureTimeStamp.pulse, 2)} / ${this.app.clock.bpm}`; if (this.app.exampleIsPlaying) { tryEvaluate(this.app, this.app.example_buffer); } else { diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 6e593d8..a0b7720 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -16,6 +16,7 @@ class TransportProcessor extends AudioWorkletProcessor { this.port.postMessage(message.data); } else if (message.data === "start") { this.started = true; + this.lastPlayPressTime = currentTime; } else if (message.data === "pause") { this.started = false; } else if (message.data === "stop") { @@ -36,6 +37,8 @@ class TransportProcessor extends AudioWorkletProcessor { const adjustedCurrentTime = currentTime + (this.nudge / 100); const beatNumber = adjustedCurrentTime / (60 / this.bpm); const currentPulsePosition = Math.ceil(beatNumber * this.ppqn); + const elapsedTime = currentTime - this.lastPlayPressTime; + this.port.postMessage({ type: "elapsed", value: elapsedTime }) if (currentPulsePosition > this.currentPulsePosition) { this.currentPulsePosition = currentPulsePosition; this.port.postMessage({ type: "bang" }); From da70a6007a5ba0b6925410cc42acf710516a0afc Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 09:50:16 +0200 Subject: [PATCH 02/22] adding resume to Transport --- src/TransportNode.js | 4 ++++ src/TransportProcessor.js | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/TransportNode.js b/src/TransportNode.js index e206a0d..db09830 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -41,6 +41,10 @@ export class TransportNode extends AudioWorkletNode { this.port.postMessage("pause"); } + resume() { + this.port.postMessage("resume"); + } + setBPM(bpm) { this.port.postMessage({ type: "bpm", value: bpm }); } diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index a0b7720..8e58188 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -17,6 +17,8 @@ class TransportProcessor extends AudioWorkletProcessor { } else if (message.data === "start") { this.started = true; this.lastPlayPressTime = currentTime; + } else if (message.data === "resume") { + this.started = true; } else if (message.data === "pause") { this.started = false; } else if (message.data === "stop") { From dcd438805372e10196ae9de22a2760a903bb93f8 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 09:52:29 +0200 Subject: [PATCH 03/22] connecting resume to the interface --- src/Clock.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Clock.ts b/src/Clock.ts index 053db67..9a6081f 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -184,7 +184,11 @@ export class Clock { */ this.app.audioContext.resume(); this.app.api.MidiConnection.sendStartMessage(); - this.transportNode?.start(); + if (this.tick > 0) { + this.transportNode?.resume(); + } else { + this.transportNode?.start(); + } } public pause(): void { From 0e205b6b6c6d211c77c7755d264462e31db2ca9b Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 09:56:28 +0200 Subject: [PATCH 04/22] adding logicalTime and realTime getters --- src/Clock.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Clock.ts b/src/Clock.ts index 9a6081f..fab3172 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -144,6 +144,14 @@ export class Clock { return this._ppqn; } + get logicalTime(): number { + return this.tick * this.pulse_duration; + } + + get realTime(): number { + return this.elapsed; + } + set ppqn(ppqn: number) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; From 0c5437e1c58655950c811e268d7897afd6e16b91 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 10:00:21 +0200 Subject: [PATCH 05/22] Account for deviation --- src/Clock.ts | 8 ++++++-- src/classes/SoundEvent.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index fab3172..43d173a 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -152,6 +152,10 @@ export class Clock { return this.elapsed; } + get deviation(): number { + return Math.abs(this.logicalTime - this.realTime) + } + set ppqn(ppqn: number) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; @@ -215,8 +219,8 @@ export class Clock { * * @remark also sends a MIDI message if a port is declared */ - this.app.clock.tick = -1; - this.time_position = { bar: -1, beat: -1, pulse: -1 }; + this.app.clock.tick = 0; + this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); this.transportNode?.stop(); } diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 80ac9f8..799ee51 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -463,10 +463,10 @@ export class SoundEvent extends AudibleEvent { this.values.chord.forEach((obj: { [key: string]: number }) => { const copy = { ...this.values }; copy.freq = obj.freq; - superdough(copy, this.nudge, this.values.dur); + superdough(copy, this.nudge - this.app.clock.deviation, this.values.dur); }); } else { - superdough(this.values, this.nudge, this.values.dur); + superdough(this.values, this.nudge - this.app.clock.deviation, this.values.dur); } }; } From ecd3783adf51dfd0d28fe35cacf9d0248b76eeda Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 10:24:52 +0200 Subject: [PATCH 06/22] This is better but the deviation keeps growing --- src/TransportProcessor.js | 12 +++++++++++- src/classes/SoundEvent.ts | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 8e58188..046d17f 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -9,6 +9,9 @@ class TransportProcessor extends AudioWorkletProcessor { this.bpm = 120; this.ppqn = 48; this.currentPulsePosition = 0; + this.totalPausedTime = 0; + this.lastPauseTime = null; + } handleMessage = (message) => { @@ -17,10 +20,17 @@ class TransportProcessor extends AudioWorkletProcessor { } else if (message.data === "start") { this.started = true; this.lastPlayPressTime = currentTime; + this.totalPausedTime = 0; + } else if (message.data === "resume") { this.started = true; + if (this.lastPauseTime !== null) { + this.totalPausedTime += currentTime - this.lastPauseTime; + this.lastPauseTime = null; + } } else if (message.data === "pause") { this.started = false; + this.lastPauseTime = currentTime; } else if (message.data === "stop") { this.started = false; } else if (message.data.type === 'bpm') { @@ -39,7 +49,7 @@ class TransportProcessor extends AudioWorkletProcessor { const adjustedCurrentTime = currentTime + (this.nudge / 100); const beatNumber = adjustedCurrentTime / (60 / this.bpm); const currentPulsePosition = Math.ceil(beatNumber * this.ppqn); - const elapsedTime = currentTime - this.lastPlayPressTime; + const elapsedTime = (currentTime - this.lastPlayPressTime) - this.totalPausedTime; this.port.postMessage({ type: "elapsed", value: elapsedTime }) if (currentPulsePosition > this.currentPulsePosition) { this.currentPulsePosition = currentPulsePosition; diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 799ee51..725458d 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -459,6 +459,7 @@ export class SoundEvent extends AudibleEvent { }; out = (): void => { + console.log(this.app.clock.deviation) if (this.values.chord) { this.values.chord.forEach((obj: { [key: string]: number }) => { const copy = { ...this.values }; From 662f8ef82fab54c56a0ee0128622e2afbfa2feee Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 13:52:18 +0200 Subject: [PATCH 07/22] uniformise startup --- src/Clock.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 43d173a..cb2d3d0 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -42,10 +42,10 @@ export class Clock { tick: number; constructor(public app: Editor, ctx: AudioContext) { - this.time_position = { bar: -1, beat: -1, pulse: -1 }; + this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.time_signature = [4, 4]; this.elapsed = 0; - this.tick = -1; + this.tick = 0; this._bpm = 120; this._ppqn = 48; this.transportNode = null; From 34b4c1c11453e436d51f0be9e1b01ed6879cd21d Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 13:53:57 +0200 Subject: [PATCH 08/22] remove +1 in ziffers object --- src/classes/ZPlayer.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/classes/ZPlayer.ts b/src/classes/ZPlayer.ts index 85fb3ba..fca35f5 100644 --- a/src/classes/ZPlayer.ts +++ b/src/classes/ZPlayer.ts @@ -82,7 +82,7 @@ export class Player extends Event { }; origin = (): number => { - return this.app.clock.pulses_since_origin + 1; + return this.app.clock.pulses_since_origin; }; pulse = (): number => { @@ -109,18 +109,18 @@ export class Player extends Event { } const patternIsStarting = (this.notStarted() && - (this.pulse() === 0 || this.origin() >= this.nextBeatInTicks()) && - this.origin() >= this.waitTime); + (this.pulse() === 0 || this.origin() >= this.nextBeatInTicks()) && + this.origin() >= this.waitTime); const timeToPlayNext = (this.current && this.pulseToSecond(this.origin()) >= this.pulseToSecond(this.lastCallTime) + - this.pulseToSecond(this.current.duration*4*this.app.clock.ppqn) && + this.pulseToSecond(this.current.duration * 4 * this.app.clock.ppqn) && this.origin() >= this.waitTime); // If pattern is starting or it's time to play next event const areWeThereYet = patternIsStarting || timeToPlayNext; - + // Increment index of how many times call is skipped this.skipIndex = areWeThereYet ? 0 : this.skipIndex + 1; @@ -139,10 +139,10 @@ export class Player extends Event { }; sound(name?: string) { - + if (this.areWeThereYet()) { const event = this.next() as Pitch | Chord | ZRest; - const noteLengthInSeconds = this.app.clock.convertPulseToSecond(event.duration*4*this.app.clock.ppqn); + const noteLengthInSeconds = this.app.clock.convertPulseToSecond(event.duration * 4 * this.app.clock.ppqn); if (event instanceof Pitch) { const obj = event.getExisting( "freq", @@ -152,8 +152,8 @@ export class Player extends Event { "octave", "parsedScale" ); - if(event.sound) name = event.sound as string; - if(event.soundIndex) obj.n = event.soundIndex; + if (event.sound) name = event.sound as string; + if (event.soundIndex) obj.n = event.soundIndex; obj.dur = noteLengthInSeconds; return new SoundEvent(obj, this.app).sound(name || "sine"); } else if (event instanceof Chord) { @@ -167,8 +167,8 @@ export class Player extends Event { "parsedScale" ); }); - const sound: SoundParams = {dur: noteLengthInSeconds}; - if(name) sound.s = name; + const sound: SoundParams = { dur: noteLengthInSeconds }; + if (name) sound.s = name; return new SoundEvent(sound, this.app).chord(pitches); } else if (event instanceof ZRest) { return RestEvent.createRestProxy(event.duration, this.app); @@ -191,7 +191,7 @@ export class Player extends Event { "parsedScale", ); if (event instanceof Pitch) { - if(event.soundIndex) obj.channel = event.soundIndex; + if (event.soundIndex) obj.channel = event.soundIndex; const note = new MidiEvent(obj, this.app); return value ? note.note(value) : note; } else if (event instanceof ZRest) { From 53deb747001006c9083d2ed1930fa7b81b26bc83 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Fri, 27 Oct 2023 15:00:39 +0300 Subject: [PATCH 09/22] Handle messages separately --- src/TransportNode.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/TransportNode.js b/src/TransportNode.js index db09830..83ee5ae 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -12,23 +12,24 @@ export class TransportNode extends AudioWorkletNode { /** @type {(this: MessagePort, ev: MessageEvent) => any} */ handleMessage = (message) => { - if (message.data && message.data.type === "elapsed") { - this.app.clock.elapsed = message.data.value - } - if (message.data && message.data.type === "bang") { - if (this.app.settings.send_clock) - this.app.api.MidiConnection.sendMidiClock(); - this.app.clock.tick++; - const futureTimeStamp = this.app.clock.convertTicksToTimeposition( - 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.clock.bpm}`; - if (this.app.exampleIsPlaying) { - tryEvaluate(this.app, this.app.example_buffer); - } else { - tryEvaluate(this.app, this.app.global_buffer); + if(message.data) { + if (message.data.type === "elapsed") { + this.app.clock.elapsed = message.data.value + } else if (message.data.type === "bang") { + if (this.app.settings.send_clock) + this.app.api.MidiConnection.sendMidiClock(); + this.app.clock.tick++; + const futureTimeStamp = this.app.clock.convertTicksToTimeposition( + 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.clock.bpm}`; + if (this.app.exampleIsPlaying) { + tryEvaluate(this.app, this.app.example_buffer); + } else { + tryEvaluate(this.app, this.app.global_buffer); + } } } }; From 06addec7cb905a2f26b90bd7f34db71bf277f301 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Fri, 27 Oct 2023 15:29:55 +0300 Subject: [PATCH 10/22] Refactor logicalTime as incremental --- src/Clock.ts | 13 ++++++++----- src/TransportNode.js | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index cb2d3d0..b1f197b 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -33,7 +33,8 @@ export class Clock { */ ctx: AudioContext; - elapsed: number + elapsed: number; + logicalTime: number; transportNode: TransportNode | null; private _bpm: number; time_signature: number[]; @@ -45,6 +46,7 @@ export class Clock { this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.time_signature = [4, 4]; this.elapsed = 0; + this.logicalTime = 0; this.tick = 0; this._bpm = 120; this._ppqn = 48; @@ -144,10 +146,6 @@ export class Clock { return this._ppqn; } - get logicalTime(): number { - return this.tick * this.pulse_duration; - } - get realTime(): number { return this.elapsed; } @@ -163,6 +161,11 @@ export class Clock { } } + public incrementTick() { + this.tick++; + this.logicalTime += this.pulse_duration; + } + public nextTickFrom(time: number, nudge: number): number { /** * Compute the time remaining before the next clock tick. diff --git a/src/TransportNode.js b/src/TransportNode.js index 83ee5ae..0644d90 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -18,7 +18,7 @@ export class TransportNode extends AudioWorkletNode { } else if (message.data.type === "bang") { if (this.app.settings.send_clock) this.app.api.MidiConnection.sendMidiClock(); - this.app.clock.tick++; + this.app.clock.incrementTick(); const futureTimeStamp = this.app.clock.convertTicksToTimeposition( this.app.clock.tick ); From 7ac784bc0e1ee3a613ec85d276550c785cf51cf5 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 14:33:44 +0200 Subject: [PATCH 11/22] Push amiika suggestion --- src/Clock.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Clock.ts b/src/Clock.ts index b1f197b..e0f814d 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -223,6 +223,7 @@ export class Clock { * @remark also sends a MIDI message if a port is declared */ this.app.clock.tick = 0; + this.logicalTime = 0 this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); this.transportNode?.stop(); From 6f40e8afd23da19566b5bcd9b5e05b74ca7a9beb Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Fri, 27 Oct 2023 15:48:02 +0300 Subject: [PATCH 12/22] Route bpm change from TransportProcessor --- src/Clock.ts | 4 ++-- src/TransportNode.js | 2 ++ src/TransportProcessor.js | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index e0f814d..8dff62c 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -137,7 +137,6 @@ export class Clock { set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { - this._bpm = bpm; this.transportNode?.setBPM(bpm); } } @@ -223,7 +222,8 @@ export class Clock { * @remark also sends a MIDI message if a port is declared */ this.app.clock.tick = 0; - this.logicalTime = 0 + this.logicalTime = 0; + this.elapsed = 0; this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); this.transportNode?.stop(); diff --git a/src/TransportNode.js b/src/TransportNode.js index 0644d90..7c6c681 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -30,6 +30,8 @@ export class TransportNode extends AudioWorkletNode { } else { tryEvaluate(this.app, this.app.global_buffer); } + } else if (message.data.type === "bpm") { + this.app.clock.bpm = message.data.value; } } }; diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 046d17f..06bd225 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -36,6 +36,7 @@ class TransportProcessor extends AudioWorkletProcessor { } else if (message.data.type === 'bpm') { this.bpm = message.data.value; this.currentPulsePosition = 0; + this.port.postMessage({ type: "bpm", value: this.bpm }); } else if (message.data.type === 'ppqn') { this.ppqn = message.data.value; this.currentPulsePosition = 0; From e6022711434080e20cbc8fd55ea3d4c3c7914172 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 27 Oct 2023 15:12:13 +0200 Subject: [PATCH 13/22] Just plain weird fix for bpm change --- src/Clock.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Clock.ts b/src/Clock.ts index 8dff62c..1f8e330 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -138,6 +138,7 @@ export class Clock { set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { this.transportNode?.setBPM(bpm); + this._bpm = bpm } } From 43efdf66de4028960e55d62ca78fd78e0863beb6 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Fri, 27 Oct 2023 16:13:34 +0300 Subject: [PATCH 14/22] Remove attempt to fix bpm --- src/TransportNode.js | 2 -- src/TransportProcessor.js | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/TransportNode.js b/src/TransportNode.js index 7c6c681..0644d90 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -30,8 +30,6 @@ export class TransportNode extends AudioWorkletNode { } else { tryEvaluate(this.app, this.app.global_buffer); } - } else if (message.data.type === "bpm") { - this.app.clock.bpm = message.data.value; } } }; diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 06bd225..8d5d5d8 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -35,11 +35,8 @@ class TransportProcessor extends AudioWorkletProcessor { this.started = false; } else if (message.data.type === 'bpm') { this.bpm = message.data.value; - this.currentPulsePosition = 0; - this.port.postMessage({ type: "bpm", value: this.bpm }); } else if (message.data.type === 'ppqn') { this.ppqn = message.data.value; - this.currentPulsePosition = 0; } else if (message.data.type === 'nudge') { this.nudge = message.data.value } From 0dbb26feb8c41b01176f5598869ecfa5dca77a27 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Sat, 28 Oct 2023 11:48:16 +0300 Subject: [PATCH 15/22] Logging for testing message delay --- src/Clock.ts | 7 ++++++- src/TransportNode.js | 29 +++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 1f8e330..bcf679a 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -41,6 +41,7 @@ export class Clock { time_position: TimePosition; private _ppqn: number; tick: number; + running: boolean; constructor(public app: Editor, ctx: AudioContext) { this.time_position = { bar: 0, beat: 0, pulse: 0 }; @@ -52,6 +53,7 @@ export class Clock { this._ppqn = 48; this.transportNode = null; this.ctx = ctx; + this.running = true; ctx.audioWorklet .addModule(TransportProcessor) .then((e) => { @@ -138,7 +140,7 @@ export class Clock { set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { this.transportNode?.setBPM(bpm); - this._bpm = bpm + this._bpm = bpm; } } @@ -198,6 +200,7 @@ 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(); if (this.tick > 0) { this.transportNode?.resume(); @@ -212,6 +215,7 @@ export class Clock { * * @remark also sends a MIDI message if a port is declared */ + this.running = false; this.transportNode?.pause(); this.app.api.MidiConnection.sendStopMessage(); } @@ -222,6 +226,7 @@ export class Clock { * * @remark also sends a MIDI message if a port is declared */ + this.running = false; this.app.clock.tick = 0; this.logicalTime = 0; this.elapsed = 0; diff --git a/src/TransportNode.js b/src/TransportNode.js index 0644d90..3b59af9 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -16,19 +16,24 @@ export class TransportNode extends AudioWorkletNode { if (message.data.type === "elapsed") { this.app.clock.elapsed = message.data.value } else if (message.data.type === "bang") { - if (this.app.settings.send_clock) - this.app.api.MidiConnection.sendMidiClock(); - this.app.clock.incrementTick(); - const futureTimeStamp = this.app.clock.convertTicksToTimeposition( - 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.clock.bpm}`; - if (this.app.exampleIsPlaying) { - tryEvaluate(this.app, this.app.example_buffer); + if(this.app.clock.running) { + if (this.app.settings.send_clock) { + this.app.api.MidiConnection.sendMidiClock(); + } + const futureTimeStamp = this.app.clock.convertTicksToTimeposition( + 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.clock.bpm}`; + if (this.app.exampleIsPlaying) { + tryEvaluate(this.app, this.app.example_buffer); + } else { + tryEvaluate(this.app, this.app.global_buffer); + } + this.app.clock.incrementTick(); } else { - tryEvaluate(this.app, this.app.global_buffer); + console.log("STILLLLLLLLLLLLLLLL BANGING!"); } } } From 6beb5f2c84c74361b418acee484cb724cd6f113c Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Sat, 28 Oct 2023 12:57:37 +0300 Subject: [PATCH 16/22] Some more logging on message delay --- src/Clock.ts | 20 ++++++++++++++------ src/TransportNode.js | 28 ++++++++++++++-------------- src/TransportProcessor.js | 10 ++++++---- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index bcf679a..23d26fd 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -42,6 +42,7 @@ export class Clock { private _ppqn: number; tick: number; running: boolean; + messageSent: number; constructor(public app: Editor, ctx: AudioContext) { this.time_position = { bar: 0, beat: 0, pulse: 0 }; @@ -54,6 +55,7 @@ export class Clock { this.transportNode = null; this.ctx = ctx; this.running = true; + this.messageSent = 0; ctx.audioWorklet .addModule(TransportProcessor) .then((e) => { @@ -139,7 +141,8 @@ export class Clock { set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { - this.transportNode?.setBPM(bpm); + this.messageSent = this.app.audioContext.currentTime; + this.transportNode?.setBPM(bpm, this.messageSent); this._bpm = bpm; } } @@ -159,7 +162,8 @@ export class Clock { set ppqn(ppqn: number) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; - this.transportNode?.setPPQN(ppqn); + this.messageSent = this.app.audioContext.currentTime; + this.transportNode?.setPPQN(ppqn, this.messageSent); } } @@ -201,12 +205,14 @@ export class Clock { */ this.app.audioContext.resume(); this.running = true; + this.messageSent = this.app.audioContext.currentTime; this.app.api.MidiConnection.sendStartMessage(); if (this.tick > 0) { - this.transportNode?.resume(); + this.transportNode?.resume(this.messageSent); } else { - this.transportNode?.start(); + this.transportNode?.start(this.messageSent); } + } public pause(): void { @@ -216,7 +222,8 @@ export class Clock { * @remark also sends a MIDI message if a port is declared */ this.running = false; - this.transportNode?.pause(); + this.messageSent = this.app.audioContext.currentTime; + this.transportNode?.pause(this.messageSent); this.app.api.MidiConnection.sendStopMessage(); } @@ -232,6 +239,7 @@ export class Clock { this.elapsed = 0; this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); - this.transportNode?.stop(); + this.messageSent = this.app.audioContext.currentTime; + this.transportNode?.stop(this.messageSent); } } diff --git a/src/TransportNode.js b/src/TransportNode.js index 3b59af9..f4d679f 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -39,31 +39,31 @@ export class TransportNode extends AudioWorkletNode { } }; - start() { - this.port.postMessage("start"); + start(sentAt) { + this.port.postMessage({ type: "start", sentAt: sentAt}); } - pause() { - this.port.postMessage("pause"); + pause(sentAt) { + this.port.postMessage({ type: "pause", sentAt: sentAt}); } - resume() { - this.port.postMessage("resume"); + resume(sentAt) { + this.port.postMessage({ type: "resume", sentAt: sentAt }); } - setBPM(bpm) { - this.port.postMessage({ type: "bpm", value: bpm }); + setBPM(bpm, sentAt) { + this.port.postMessage({ type: "bpm", value: bpm, sentAt: sentAt }); } - setPPQN(ppqn) { - this.port.postMessage({ type: "ppqn", value: ppqn }); + setPPQN(ppqn, sentAt) { + this.port.postMessage({ type: "ppqn", value: ppqn, sentAt: sentAt }); } - setNudge(nudge) { - this.port.postMessage({ type: "nudge", value: nudge }); + setNudge(nudge, sentAt) { + this.port.postMessage({ type: "nudge", value: nudge, sentAt: sentAt }); } - stop() { - this.port.postMessage("stop"); + stop(sentAt) { + this.port.postMessage({type: "stop", sentAt: sentAt}); } } diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 8d5d5d8..7cc698a 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -17,21 +17,21 @@ class TransportProcessor extends AudioWorkletProcessor { handleMessage = (message) => { if (message.data && message.data.type === "ping") { this.port.postMessage(message.data); - } else if (message.data === "start") { + } else if (message.data.type === "start") { this.started = true; this.lastPlayPressTime = currentTime; this.totalPausedTime = 0; - } else if (message.data === "resume") { + } else if (message.data.type === "resume") { this.started = true; if (this.lastPauseTime !== null) { this.totalPausedTime += currentTime - this.lastPauseTime; this.lastPauseTime = null; } - } else if (message.data === "pause") { + } else if (message.data.type === "pause") { this.started = false; this.lastPauseTime = currentTime; - } else if (message.data === "stop") { + } else if (message.data.type === "stop") { this.started = false; } else if (message.data.type === 'bpm') { this.bpm = message.data.value; @@ -40,6 +40,8 @@ class TransportProcessor extends AudioWorkletProcessor { } else if (message.data.type === 'nudge') { this.nudge = message.data.value } + // Log difference between currentTime and message.data.sentAt + console.log("Message delay: ", currentTime - message.data.sentAt); } process(inputs, outputs, parameters) { From 2a44840ee749c250ea7ebb0771367b1c5d205949 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Sat, 28 Oct 2023 21:25:24 +0300 Subject: [PATCH 17/22] Fix for bpm change issue --- src/Clock.ts | 11 +++++++++-- src/TransportNode.js | 2 +- src/TransportProcessor.js | 13 +++++++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 23d26fd..343360f 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -131,6 +131,13 @@ export class Clock { return 60 / this.bpm / this.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; + } + get bpm(): number { return this._bpm; } @@ -167,9 +174,9 @@ export class Clock { } } - public incrementTick() { + public incrementTick(bpm: number) { this.tick++; - this.logicalTime += this.pulse_duration; + this.logicalTime += this.pulse_duration_at_bpm(bpm); } public nextTickFrom(time: number, nudge: number): number { diff --git a/src/TransportNode.js b/src/TransportNode.js index f4d679f..ceb51b3 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -31,7 +31,7 @@ export class TransportNode extends AudioWorkletNode { } else { tryEvaluate(this.app, this.app.global_buffer); } - this.app.clock.incrementTick(); + this.app.clock.incrementTick(message.data.bpm); } else { console.log("STILLLLLLLLLLLLLLLL BANGING!"); } diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 7cc698a..7c8abff 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -11,7 +11,6 @@ class TransportProcessor extends AudioWorkletProcessor { this.currentPulsePosition = 0; this.totalPausedTime = 0; this.lastPauseTime = null; - } handleMessage = (message) => { @@ -35,13 +34,13 @@ class TransportProcessor extends AudioWorkletProcessor { this.started = false; } else if (message.data.type === 'bpm') { this.bpm = message.data.value; + this.currentPulsePosition = currentTime; } else if (message.data.type === 'ppqn') { this.ppqn = message.data.value; } else if (message.data.type === 'nudge') { - this.nudge = message.data.value + this.nudge = message.data.value; } - // Log difference between currentTime and message.data.sentAt - console.log("Message delay: ", currentTime - message.data.sentAt); + console.log("Message delay: ", currentTime - message.data.sentAt); } process(inputs, outputs, parameters) { @@ -50,10 +49,12 @@ class TransportProcessor extends AudioWorkletProcessor { const beatNumber = adjustedCurrentTime / (60 / this.bpm); const currentPulsePosition = Math.ceil(beatNumber * this.ppqn); const elapsedTime = (currentTime - this.lastPlayPressTime) - this.totalPausedTime; - this.port.postMessage({ type: "elapsed", value: elapsedTime }) + this.port.postMessage({ type: "elapsed", value: elapsedTime }); if (currentPulsePosition > this.currentPulsePosition) { this.currentPulsePosition = currentPulsePosition; - this.port.postMessage({ type: "bang" }); + this.port.postMessage({ type: "bang", bpm: this.bpm }); + } else { + console.log("No bang", currentPulsePosition, this.currentPulsePosition); } } return true; From 4aa7448fa71b73f5ea173088f2d15f13aa849dc2 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Sat, 28 Oct 2023 23:25:11 +0300 Subject: [PATCH 18/22] Fix delay issue by moving things from TransportProcessor --- src/API.ts | 6 +++--- src/Clock.ts | 40 +++++++++++++++++++-------------------- src/TransportNode.js | 34 +++++++++++++++------------------ src/TransportProcessor.js | 17 ----------------- 4 files changed, 38 insertions(+), 59 deletions(-) diff --git a/src/API.ts b/src/API.ts index c6c4008..b62388a 100644 --- a/src/API.ts +++ b/src/API.ts @@ -115,6 +115,7 @@ export class UserAPI { ? code : (this.app.selectedExample as string); } + this.stop(); this.play(); }; @@ -125,7 +126,7 @@ export class UserAPI { current_universe.example.candidate! = ""; current_universe.example.committed! = ""; } - this.pause(); + this.stop(); }; _playDocExampleOnce = (code?: string) => { @@ -134,6 +135,7 @@ export class UserAPI { current_universe.example.candidate! = ""; current_universe.example.committed! = ""; } + this.stop(); this.play(); this.app.exampleIsPlaying = true; evaluateOnce(this.app, code as string); @@ -206,13 +208,11 @@ export class UserAPI { public pause = (): void => { this.app.setButtonHighlighting("pause", true); - this.MidiConnection.sendStopMessage(); this.app.clock.pause(); }; public stop = (): void => { this.app.setButtonHighlighting("stop", true); - this.MidiConnection.sendStopMessage(); this.app.clock.stop(); }; silence = this.stop; diff --git a/src/Clock.ts b/src/Clock.ts index 343360f..fb0fe4a 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -23,17 +23,19 @@ export class Clock { * * @param app - The main application instance * @param ctx - The current AudioContext used by app - * @param elapsed - Time elapsed since play been pressed * @param transportNode - The TransportNode helper * @param bpm - The current beats per minute value * @param time_signature - The time signature * @param time_position - The current time position * @param ppqn - The pulses per quarter note * @param tick - The current tick since origin + * @param running - Is the clock running? + * @param lastPauseTime - The last time the clock was paused + * @param lastPlayPressTime - The last time the clock was started + * @param totalPauseTime - The total time the clock has been paused / stopped */ ctx: AudioContext; - elapsed: number; logicalTime: number; transportNode: TransportNode | null; private _bpm: number; @@ -42,12 +44,13 @@ export class Clock { private _ppqn: number; tick: number; running: boolean; - messageSent: number; + lastPauseTime: number; + lastPlayPressTime: number; + totalPauseTime: number; constructor(public app: Editor, ctx: AudioContext) { this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.time_signature = [4, 4]; - this.elapsed = 0; this.logicalTime = 0; this.tick = 0; this._bpm = 120; @@ -55,7 +58,9 @@ export class Clock { this.transportNode = null; this.ctx = ctx; this.running = true; - this.messageSent = 0; + this.lastPauseTime = 0; + this.lastPlayPressTime = 0; + this.totalPauseTime = 0; ctx.audioWorklet .addModule(TransportProcessor) .then((e) => { @@ -148,8 +153,7 @@ export class Clock { set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { - this.messageSent = this.app.audioContext.currentTime; - this.transportNode?.setBPM(bpm, this.messageSent); + this.transportNode?.setBPM(bpm); this._bpm = bpm; } } @@ -159,7 +163,7 @@ export class Clock { } get realTime(): number { - return this.elapsed; + return this.app.audioContext.currentTime - this.lastPlayPressTime - this.totalPauseTime; } get deviation(): number { @@ -169,8 +173,7 @@ export class Clock { set ppqn(ppqn: number) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; - this.messageSent = this.app.audioContext.currentTime; - this.transportNode?.setPPQN(ppqn, this.messageSent); + this.transportNode?.setPPQN(ppqn); } } @@ -212,14 +215,12 @@ export class Clock { */ this.app.audioContext.resume(); this.running = true; - this.messageSent = this.app.audioContext.currentTime; this.app.api.MidiConnection.sendStartMessage(); + this.lastPlayPressTime = this.app.audioContext.currentTime; if (this.tick > 0) { - this.transportNode?.resume(this.messageSent); - } else { - this.transportNode?.start(this.messageSent); + this.totalPauseTime += this.app.audioContext.currentTime - this.lastPauseTime; } - + this.transportNode?.start(); } public pause(): void { @@ -229,9 +230,9 @@ export class Clock { * @remark also sends a MIDI message if a port is declared */ this.running = false; - this.messageSent = this.app.audioContext.currentTime; - this.transportNode?.pause(this.messageSent); + this.transportNode?.pause(); this.app.api.MidiConnection.sendStopMessage(); + this.lastPauseTime = this.app.audioContext.currentTime; } public stop(): void { @@ -243,10 +244,9 @@ export class Clock { this.running = false; this.app.clock.tick = 0; this.logicalTime = 0; - this.elapsed = 0; + this.totalPauseTime = 0; this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); - this.messageSent = this.app.audioContext.currentTime; - this.transportNode?.stop(this.messageSent); + this.transportNode?.stop(); } } diff --git a/src/TransportNode.js b/src/TransportNode.js index ceb51b3..220072f 100644 --- a/src/TransportNode.js +++ b/src/TransportNode.js @@ -13,9 +13,7 @@ export class TransportNode extends AudioWorkletNode { /** @type {(this: MessagePort, ev: MessageEvent) => any} */ handleMessage = (message) => { if(message.data) { - if (message.data.type === "elapsed") { - this.app.clock.elapsed = message.data.value - } else if (message.data.type === "bang") { + if (message.data.type === "bang") { if(this.app.clock.running) { if (this.app.settings.send_clock) { this.app.api.MidiConnection.sendMidiClock(); @@ -32,38 +30,36 @@ export class TransportNode extends AudioWorkletNode { tryEvaluate(this.app, this.app.global_buffer); } this.app.clock.incrementTick(message.data.bpm); - } else { - console.log("STILLLLLLLLLLLLLLLL BANGING!"); } } } }; - start(sentAt) { - this.port.postMessage({ type: "start", sentAt: sentAt}); + start() { + this.port.postMessage({ type: "start" }); } - pause(sentAt) { - this.port.postMessage({ type: "pause", sentAt: sentAt}); + pause() { + this.port.postMessage({ type: "pause" }); } - resume(sentAt) { - this.port.postMessage({ type: "resume", sentAt: sentAt }); + resume() { + this.port.postMessage({ type: "resume" }); } - setBPM(bpm, sentAt) { - this.port.postMessage({ type: "bpm", value: bpm, sentAt: sentAt }); + setBPM(bpm) { + this.port.postMessage({ type: "bpm", value: bpm }); } - setPPQN(ppqn, sentAt) { - this.port.postMessage({ type: "ppqn", value: ppqn, sentAt: sentAt }); + setPPQN(ppqn) { + this.port.postMessage({ type: "ppqn", value: ppqn }); } - setNudge(nudge, sentAt) { - this.port.postMessage({ type: "nudge", value: nudge, sentAt: sentAt }); + setNudge(nudge) { + this.port.postMessage({ type: "nudge", value: nudge }); } - stop(sentAt) { - this.port.postMessage({type: "stop", sentAt: sentAt}); + stop() { + this.port.postMessage({type: "stop" }); } } diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js index 7c8abff..17507f2 100644 --- a/src/TransportProcessor.js +++ b/src/TransportProcessor.js @@ -9,8 +9,6 @@ class TransportProcessor extends AudioWorkletProcessor { this.bpm = 120; this.ppqn = 48; this.currentPulsePosition = 0; - this.totalPausedTime = 0; - this.lastPauseTime = null; } handleMessage = (message) => { @@ -18,18 +16,8 @@ class TransportProcessor extends AudioWorkletProcessor { this.port.postMessage(message.data); } else if (message.data.type === "start") { this.started = true; - this.lastPlayPressTime = currentTime; - this.totalPausedTime = 0; - - } else if (message.data.type === "resume") { - this.started = true; - if (this.lastPauseTime !== null) { - this.totalPausedTime += currentTime - this.lastPauseTime; - this.lastPauseTime = null; - } } else if (message.data.type === "pause") { this.started = false; - this.lastPauseTime = currentTime; } else if (message.data.type === "stop") { this.started = false; } else if (message.data.type === 'bpm') { @@ -40,7 +28,6 @@ class TransportProcessor extends AudioWorkletProcessor { } else if (message.data.type === 'nudge') { this.nudge = message.data.value; } - console.log("Message delay: ", currentTime - message.data.sentAt); } process(inputs, outputs, parameters) { @@ -48,13 +35,9 @@ class TransportProcessor extends AudioWorkletProcessor { const adjustedCurrentTime = currentTime + (this.nudge / 100); const beatNumber = adjustedCurrentTime / (60 / this.bpm); const currentPulsePosition = Math.ceil(beatNumber * this.ppqn); - const elapsedTime = (currentTime - this.lastPlayPressTime) - this.totalPausedTime; - this.port.postMessage({ type: "elapsed", value: elapsedTime }); if (currentPulsePosition > this.currentPulsePosition) { this.currentPulsePosition = currentPulsePosition; this.port.postMessage({ type: "bang", bpm: this.bpm }); - } else { - console.log("No bang", currentPulsePosition, this.currentPulsePosition); } } return true; From 707435ee5ce157e65db8319deec3f03a72449ba8 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Mon, 30 Oct 2023 16:14:34 +0200 Subject: [PATCH 19/22] Fix pause/stop issue --- src/Clock.ts | 15 +++++++-------- src/classes/ZPlayer.ts | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index fb0fe4a..d54ac9a 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -163,11 +163,11 @@ export class Clock { } get realTime(): number { - return this.app.audioContext.currentTime - this.lastPlayPressTime - this.totalPauseTime; + return this.app.audioContext.currentTime - this.totalPauseTime; } get deviation(): number { - return Math.abs(this.logicalTime - this.realTime) + return Math.abs(this.logicalTime - this.realTime); } set ppqn(ppqn: number) { @@ -217,9 +217,7 @@ export class Clock { this.running = true; this.app.api.MidiConnection.sendStartMessage(); this.lastPlayPressTime = this.app.audioContext.currentTime; - if (this.tick > 0) { - this.totalPauseTime += this.app.audioContext.currentTime - this.lastPauseTime; - } + this.totalPauseTime += (this.lastPlayPressTime - this.lastPauseTime); this.transportNode?.start(); } @@ -233,6 +231,7 @@ export class Clock { this.transportNode?.pause(); this.app.api.MidiConnection.sendStopMessage(); this.lastPauseTime = this.app.audioContext.currentTime; + this.logicalTime = this.realTime; } public stop(): void { @@ -242,9 +241,9 @@ export class Clock { * @remark also sends a MIDI message if a port is declared */ this.running = false; - this.app.clock.tick = 0; - this.logicalTime = 0; - this.totalPauseTime = 0; + this.tick = 0; + this.lastPauseTime = this.app.audioContext.currentTime; + this.logicalTime = this.realTime; this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); this.transportNode?.stop(); diff --git a/src/classes/ZPlayer.ts b/src/classes/ZPlayer.ts index fca35f5..4a66e4f 100644 --- a/src/classes/ZPlayer.ts +++ b/src/classes/ZPlayer.ts @@ -82,7 +82,7 @@ export class Player extends Event { }; origin = (): number => { - return this.app.clock.pulses_since_origin; + return this.app.clock.pulses_since_origin + 1; }; pulse = (): number => { From 9ca325c92722b2c5f9c237652be0298867e3575f Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Tue, 31 Oct 2023 01:27:44 +0200 Subject: [PATCH 20/22] Fixing the fix for bpm --- src/Clock.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Clock.ts b/src/Clock.ts index d54ac9a..428dae8 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -155,6 +155,7 @@ export class Clock { if (bpm > 0 && this._bpm !== bpm) { this.transportNode?.setBPM(bpm); this._bpm = bpm; + this.logicalTime = this.realTime; } } From 466a562acf0e6ca2462e66dee4919839b97b9b1e Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 3 Nov 2023 19:16:01 +0100 Subject: [PATCH 21/22] merging branches --- src/classes/SoundEvent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 4156634..098515b 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -430,7 +430,7 @@ export class SoundEvent extends AudibleEvent { "parsedScale", ]); for (const event of events) { - superdough(event, this.nudge, event.dur); + superdough(event, this.nudge + this.app.clock.deviation, event.dur); } }; } From 4824e81dd4fe7fb09cad68854c78d4a8afa10cc6 Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Sat, 4 Nov 2023 15:43:07 +0200 Subject: [PATCH 22/22] Insane array mangling for scale arrays --- src/Utils/Generic.ts | 20 +++++++++++--------- src/classes/SoundEvent.ts | 1 - 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Utils/Generic.ts b/src/Utils/Generic.ts index d6e91e6..69e5da1 100644 --- a/src/Utils/Generic.ts +++ b/src/Utils/Generic.ts @@ -6,9 +6,15 @@ * @returns {Record[]} Array of objects * */ -export function objectWithArraysToArrayOfObjects(input: Record, ignoredKeys: string[]): Record[] { - ignoredKeys = ignoredKeys.map((k) => Array.isArray(input[k]) ? undefined : k).filter((k) => k !== undefined) as string[]; - const keys = Object.keys(input).filter((k) => !ignoredKeys.includes(k)); +export function objectWithArraysToArrayOfObjects(input: Record, arraysToArrays: string[]): Record[] { + arraysToArrays.forEach((k) => { + // Transform single array to array of arrays and keep array of arrays as is + if (Array.isArray(input[k]) && !Array.isArray(input[k][0])) { + input[k] = [input[k]]; + } + }); + const keys = Object.keys(input); + const maxLength = Math.max( ...keys.map((k) => Array.isArray(input[k]) ? (input[k] as any[]).length : 1 @@ -20,14 +26,10 @@ export function objectWithArraysToArrayOfObjects(input: Record, ign for (let i = 0; i < maxLength; i++) { const event: Record = {}; for (const k of keys) { - if (ignoredKeys.includes(k)) { - event[k] = input[k]; - } else { - if (Array.isArray(input[k])) { + if (Array.isArray(input[k])) { event[k] = (input[k] as any[])[i % (input[k] as any[]).length]; - } else { + } else { event[k] = input[k]; - } } } output.push(event); diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 098515b..2d34c12 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -375,7 +375,6 @@ export class SoundEvent extends AudibleEvent { const events = objectWithArraysToArrayOfObjects(filteredValues, [ "parsedScale", ]); - events.forEach((event) => { const [note, _] = noteFromPc( (event.key as number) || "C4",