From 2309bcd95c354c590f80b9766fb668e940dba307 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 09:16:35 +0100 Subject: [PATCH 01/10] remove nodeprocessor and import zyklus --- package.json | 1 + src/Clock.ts | 25 +++------------------ src/TransportProcessor.js | 47 --------------------------------------- yarn.lock | 5 +++++ 4 files changed, 9 insertions(+), 69 deletions(-) delete mode 100644 src/TransportProcessor.js diff --git a/package.json b/package.json index b09c494..55cb430 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "unique-names-generator": "^4.7.1", "vite-plugin-markdown": "^2.1.0", "zifferjs": "^0.0.44", + "zyklus": "^0.1.4", "zzfx": "^1.2.0" } } diff --git a/src/Clock.ts b/src/Clock.ts index 2d78671..0b61162 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -1,7 +1,6 @@ -// @ts-ignore -import { TransportNode } from "./TransportNode"; -import TransportProcessor from "./TransportProcessor?worker&url"; import { Editor } from "./main"; +// @ts-ignore +import * as zyklus from "zyklus"; export interface TimePosition { /** @@ -37,7 +36,6 @@ export class Clock { ctx: AudioContext; logicalTime: number; - transportNode: TransportNode | null; private _bpm: number; time_signature: number[]; time_position: TimePosition; @@ -58,23 +56,12 @@ export class Clock { this.tick = 0; this._bpm = 120; this._ppqn = 48; - 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.connect(ctx.destination); - return e; - }) - .catch((e) => { - console.log("Error loading TransportProcessor.js:", e); - }); - } + } convertTicksToTimeposition(ticks: number): TimePosition { /** @@ -157,12 +144,10 @@ export class Clock { } set nudge(nudge: number) { - this.transportNode?.setNudge(nudge); } set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { - this.transportNode?.setBPM(bpm); this._bpm = bpm; this.logicalTime = this.realTime; } @@ -183,7 +168,6 @@ export class Clock { set ppqn(ppqn: number) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; - this.transportNode?.setPPQN(ppqn); this.logicalTime = this.realTime; } } @@ -226,7 +210,6 @@ export class Clock { this.app.api.MidiConnection.sendStartMessage(); this.lastPlayPressTime = this.app.audioContext.currentTime; this.totalPauseTime += this.lastPlayPressTime - this.lastPauseTime; - this.transportNode?.start(); } public pause(): void { @@ -236,7 +219,6 @@ 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(); this.lastPauseTime = this.app.audioContext.currentTime; this.logicalTime = this.realTime; @@ -254,6 +236,5 @@ export class Clock { 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/TransportProcessor.js b/src/TransportProcessor.js deleted file mode 100644 index 20e96ce..0000000 --- a/src/TransportProcessor.js +++ /dev/null @@ -1,47 +0,0 @@ -class TransportProcessor extends AudioWorkletProcessor { - constructor(options) { - super(options); - this.port.addEventListener("message", this.handleMessage); - this.port.start(); - this.nudge = 0; - this.started = false; - this.bpm = 120; - this.ppqn = 48; - this.currentPulsePosition = 0; - } - - handleMessage = (message) => { - if (message.data && message.data.type === "ping") { - this.port.postMessage(message.data); - } else if (message.data.type === "start") { - this.started = true; - } else if (message.data.type === "pause") { - this.started = false; - } else if (message.data.type === "stop") { - 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; - this.currentPulsePosition = currentTime; - } else if (message.data.type === "nudge") { - this.nudge = message.data.value; - } - }; - - process(inputs, outputs, parameters) { - if (this.started) { - const adjustedCurrentTime = currentTime + this.nudge / 100; - const beatNumber = adjustedCurrentTime / (60 / this.bpm); - const currentPulsePosition = Math.ceil(beatNumber * this.ppqn); - if (currentPulsePosition > this.currentPulsePosition) { - this.currentPulsePosition = currentPulsePosition; - this.port.postMessage({ type: "bang", bpm: this.bpm }); - } - } - return true; - } -} - -registerProcessor("transport", TransportProcessor); diff --git a/yarn.lock b/yarn.lock index 83e8be2..add9134 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3887,6 +3887,11 @@ zifferjs@^0.0.44: resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.44.tgz#c6b425166488ec05e349867e3de2460b74204449" integrity sha512-Q+0affxeUZwl+oJpsa1nb4hqHV6V4VX+pkejCQq/e9+/0H6ooTpcDQ9IDopvrWBnhA8E11k0tbwUee5TJtE8UQ== +zyklus@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/zyklus/-/zyklus-0.1.4.tgz#229b2966fd1126ef72c6004697269118762bdcd5" + integrity sha512-hbv2cyy4nOI7P8nL8b3ki1jswoLzkUzewPgCLDdDfABryDkV5iO8DAbU25OgO5ShRZHLjXJIylwv5PJQPl3Mpw== + zzfx@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/zzfx/-/zzfx-1.2.0.tgz#021e5df8e1605f507e2dde15608eba22798b424b" From 5b9a59effe7e019afdbe59e7d5ce119d2239aeb3 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 09:26:03 +0100 Subject: [PATCH 02/10] WIP: Zyklus callback --- src/Clock.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 0b61162..05be33c 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -1,6 +1,8 @@ import { Editor } from "./main"; // @ts-ignore -import * as zyklus from "zyklus"; +import { getAudioContext } from "superdough"; +// @ts-ignore +import "zyklus"; export interface TimePosition { /** @@ -21,8 +23,8 @@ export class Clock { * It is also responsible for starting and stopping the Clock TransportNode. * * @param app - The main application instance + * @param clock - The zyklus clock * @param ctx - The current AudioContext used by app - * @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 @@ -34,6 +36,7 @@ export class Clock { * @param totalPauseTime - The total time the clock has been paused / stopped */ + clock: any; ctx: AudioContext; logicalTime: number; private _bpm: number; @@ -61,8 +64,17 @@ export class Clock { this.lastPauseTime = 0; this.lastPlayPressTime = 0; this.totalPauseTime = 0; + this.clock = getAudioContext().createClock(this.clockCallback, this.pulse_duration) } + clockCallback = (time: number, duration: number, tick: number) => { + let deadline = time - getAudioContext().currentTime; + this.tick = tick; + + // Implement TransportNode clock callback and update clock info with it + + }; + convertTicksToTimeposition(ticks: number): TimePosition { /** * Converts ticks to a TimePosition object. From bb5dd6b348d826b0766882569204d0f256e537a1 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 10:45:35 +0100 Subject: [PATCH 03/10] first boom boom --- src/Clock.ts | 24 ++++++++++++++++++++++++ src/classes/SoundEvent.ts | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Clock.ts b/src/Clock.ts index 05be33c..10bf0c5 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -1,8 +1,10 @@ import { Editor } from "./main"; +import { tryEvaluate } from "./Evaluator"; // @ts-ignore import { getAudioContext } from "superdough"; // @ts-ignore import "zyklus"; +const zeroPad = (num: number, places: number) => String(num).padStart(places, "0"); export interface TimePosition { /** @@ -48,6 +50,7 @@ export class Clock { lastPauseTime: number; lastPlayPressTime: number; totalPauseTime: number; + timeviewer: HTMLElement; constructor( public app: Editor, @@ -64,12 +67,32 @@ export class Clock { this.lastPauseTime = 0; this.lastPlayPressTime = 0; this.totalPauseTime = 0; + this.timeviewer = document.getElementById("timeviewer")!; this.clock = getAudioContext().createClock(this.clockCallback, this.pulse_duration) } clockCallback = (time: number, duration: number, tick: number) => { let deadline = time - getAudioContext().currentTime; this.tick = tick; + 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; + if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) { + this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${ + futureTimeStamp.beat + 1 + } / ${this.app.clock.bpm}`; + } + if (this.app.exampleIsPlaying) { + tryEvaluate(this.app, this.app.example_buffer); + } else { + tryEvaluate(this.app, this.app.global_buffer); + } + } // Implement TransportNode clock callback and update clock info with it @@ -222,6 +245,7 @@ export class Clock { this.app.api.MidiConnection.sendStartMessage(); this.lastPlayPressTime = this.app.audioContext.currentTime; this.totalPauseTime += this.lastPlayPressTime - this.lastPauseTime; + this.clock.start() } public pause(): void { diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 6f5e216..b0af7ec 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -474,7 +474,7 @@ export class SoundEvent extends AudibleEvent { } superdough( filteredEvent, - this.nudge - this.app.clock.deviation, + this.nudge, filteredEvent.dur, ); } From a905d9b2df202877a1f36da5abbee0517e1904f2 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 10:49:29 +0100 Subject: [PATCH 04/10] connect deadline to output --- src/Clock.ts | 3 +++ src/classes/SoundEvent.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Clock.ts b/src/Clock.ts index 10bf0c5..1d93f92 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -51,6 +51,7 @@ export class Clock { lastPlayPressTime: number; totalPauseTime: number; timeviewer: HTMLElement; + deadline: number; constructor( public app: Editor, @@ -65,6 +66,7 @@ export class Clock { this.ctx = ctx; this.running = true; this.lastPauseTime = 0; + this.deadline = 0; this.lastPlayPressTime = 0; this.totalPauseTime = 0; this.timeviewer = document.getElementById("timeviewer")!; @@ -73,6 +75,7 @@ export class Clock { clockCallback = (time: number, duration: number, tick: number) => { let deadline = time - getAudioContext().currentTime; + this.deadline = deadline; this.tick = tick; if (this.app.clock.running) { if (this.app.settings.send_clock) { diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index b0af7ec..74a9e27 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -474,7 +474,7 @@ export class SoundEvent extends AudibleEvent { } superdough( filteredEvent, - this.nudge, + this.app.clock.deadline, filteredEvent.dur, ); } From dada6c1614c81225abbb8e732bb9d10284823b31 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 10:52:42 +0100 Subject: [PATCH 05/10] connecting more stuff before fixing --- src/Clock.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Clock.ts b/src/Clock.ts index 1d93f92..3ab8595 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -184,10 +184,15 @@ export class Clock { set nudge(nudge: number) { } + get tickDuration() { + return 1 / this.ppqn; + } + set bpm(bpm: number) { if (bpm > 0 && this._bpm !== bpm) { this._bpm = bpm; this.logicalTime = this.realTime; + this.clock.setDuration(() => (this.tickDuration * 60) / this.bpm); } } @@ -261,6 +266,7 @@ export class Clock { this.app.api.MidiConnection.sendStopMessage(); this.lastPauseTime = this.app.audioContext.currentTime; this.logicalTime = this.realTime; + this.clock.pause() } public stop(): void { @@ -275,5 +281,6 @@ export class Clock { this.logicalTime = this.realTime; this.time_position = { bar: 0, beat: 0, pulse: 0 }; this.app.api.MidiConnection.sendStopMessage(); + this.clock.stop(); } } From 31adc17a36652d8246848362ddba4dc65932dca7 Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 10:59:50 +0100 Subject: [PATCH 06/10] cleaning clock file a bit --- src/Clock.ts | 97 +++++----------------------------------------------- 1 file changed, 9 insertions(+), 88 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 3ab8595..6568cb6 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -33,9 +33,6 @@ export class Clock { * @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 */ clock: any; @@ -47,9 +44,6 @@ export class Clock { private _ppqn: number; tick: number; running: boolean; - lastPauseTime: number; - lastPlayPressTime: number; - totalPauseTime: number; timeviewer: HTMLElement; deadline: number; @@ -65,10 +59,7 @@ export class Clock { this._ppqn = 48; this.ctx = ctx; this.running = true; - this.lastPauseTime = 0; this.deadline = 0; - this.lastPlayPressTime = 0; - this.totalPauseTime = 0; this.timeviewer = document.getElementById("timeviewer")!; this.clock = getAudioContext().createClock(this.clockCallback, this.pulse_duration) } @@ -102,12 +93,6 @@ export class Clock { }; convertTicksToTimeposition(ticks: number): TimePosition { - /** - * Converts ticks to a TimePosition object. - * @param ticks The number of ticks to convert. - * @returns The TimePosition object representing the converted ticks. - */ - const beatsPerBar = this.app.clock.time_signature[0]; const ppqnPosition = ticks % this.app.clock.ppqn; const beatNumber = Math.floor(ticks / this.app.clock.ppqn); @@ -117,73 +102,39 @@ export class Clock { } get ticks_before_new_bar(): number { - /** - * This function returns the number of ticks separating the current moment - * from the beginning of the next bar. - * - * @returns number of ticks until next bar - */ const ticskMissingFromBeat = this.ppqn - this.time_position.pulse; const beatsMissingFromBar = this.beats_per_bar - this.time_position.beat; return beatsMissingFromBar * this.ppqn + ticskMissingFromBeat; } get next_beat_in_ticks(): number { - /** - * This function returns the number of ticks separating the current moment - * from the beginning of the next beat. - * - * @returns number of ticks until next beat - */ - return this.app.clock.pulses_since_origin + this.time_position.pulse; + return this.app.clock.pulses_since_origin + this.time_position.pulse; } get beats_per_bar(): number { - /** - * Returns the number of beats per bar. - */ - return this.time_signature[0]; + return this.time_signature[0]; } get beats_since_origin(): number { - /** - * Returns the number of beats since the origin. - * - * @returns number of beats since origin - */ - return Math.floor(this.tick / this.ppqn); + return Math.floor(this.tick / this.ppqn); } get pulses_since_origin(): number { - /** - * Returns the number of pulses since the origin. - * - * @returns number of pulses since origin - */ - return this.tick; + return this.tick; } get pulse_duration(): number { - /** - * Returns the duration of a pulse in seconds. - */ - return 60 / this.bpm / this.ppqn; + 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; + return 60 / bpm / this.ppqn; } get bpm(): number { return this._bpm; } - set nudge(nudge: number) { - } - get tickDuration() { return 1 / this.ppqn; } @@ -200,34 +151,18 @@ export class Clock { return this._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) { if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; - this.logicalTime = this.realTime; } } - public incrementTick(bpm: number) { + public incrementTick() { 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. - * @param time - audio context currentTime - * @param nudge - nudge in the future (in seconds) - * @returns remainingTime - */ - const pulseDuration = this.pulse_duration; + const pulseDuration = this.pulse_duration; const nudgedTime = time + nudge; const nextTickTime = Math.ceil(nudgedTime / pulseDuration) * pulseDuration; const remainingTime = nextTickTime - nudgedTime; @@ -236,9 +171,6 @@ export class Clock { } public convertPulseToSecond(n: number): number { - /** - * Converts a pulse to a second. - */ return n * this.pulse_duration; } @@ -251,21 +183,12 @@ export class Clock { 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.clock.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.app.api.MidiConnection.sendStopMessage(); - this.lastPauseTime = this.app.audioContext.currentTime; - this.logicalTime = this.realTime; this.clock.pause() } @@ -277,10 +200,8 @@ export class Clock { */ this.running = false; 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.clock.stop(); } -} +} \ No newline at end of file From a34f1a33eb3a2d68e52e5e3806b00ea0d3ff6aaa Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 11:16:16 +0100 Subject: [PATCH 07/10] lint --- src/API.ts | 16 ++++- src/Clock.ts | 69 +++++++++++---------- src/TransportNode.js | 68 --------------------- src/classes/AbstractEvents.ts | 22 ++++--- src/classes/SoundEvent.ts | 83 ++++++++++++-------------- src/documentation/more/oscilloscope.ts | 25 ++++---- src/extensions/NumberExtensions.ts | 6 +- 7 files changed, 117 insertions(+), 172 deletions(-) delete mode 100644 src/TransportNode.js diff --git a/src/API.ts b/src/API.ts index a4962d8..63699e5 100644 --- a/src/API.ts +++ b/src/API.ts @@ -1581,7 +1581,9 @@ export class UserAPI { // Low Frequency Oscillators // ============================================================= - line = (start: number, end: number, step: number = 1): number[] => { + public range = (v: number, a: number, b: number): number => v * (b - a) + a; + + public line = (start: number, end: number, step: number = 1): number[] => { /** * Returns an array of values between start and end, with a given step. * @@ -1603,7 +1605,11 @@ export class UserAPI { return result; }; - sine = (freq: number = 1, times: number = 1, offset: number = 0): number => { + public sine = ( + freq: number = 1, + times: number = 1, + offset: number = 0, + ): number => { /** * Returns a sine wave between -1 and 1. * @@ -1617,7 +1623,11 @@ export class UserAPI { ); }; - usine = (freq: number = 1, times: number = 1, offset: number = 0): number => { + public usine = ( + freq: number = 1, + times: number = 1, + offset: number = 0, + ): number => { /** * Returns a sine wave between 0 and 1. * diff --git a/src/Clock.ts b/src/Clock.ts index 6568cb6..6583bf5 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -4,7 +4,8 @@ import { tryEvaluate } from "./Evaluator"; import { getAudioContext } from "superdough"; // @ts-ignore import "zyklus"; -const zeroPad = (num: number, places: number) => String(num).padStart(places, "0"); +const zeroPad = (num: number, places: number) => + String(num).padStart(places, "0"); export interface TimePosition { /** @@ -61,35 +62,37 @@ export class Clock { this.running = true; this.deadline = 0; this.timeviewer = document.getElementById("timeviewer")!; - this.clock = getAudioContext().createClock(this.clockCallback, this.pulse_duration) - } + this.clock = getAudioContext().createClock( + this.clockCallback, + this.pulse_duration, + ); + } clockCallback = (time: number, duration: number, tick: number) => { let deadline = time - getAudioContext().currentTime; this.deadline = deadline; this.tick = tick; - 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; - if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) { - this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${ - futureTimeStamp.beat + 1 - } / ${this.app.clock.bpm}`; - } - if (this.app.exampleIsPlaying) { - tryEvaluate(this.app, this.app.example_buffer); - } else { - tryEvaluate(this.app, this.app.global_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; + if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) { + this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${ + futureTimeStamp.beat + 1 + } / ${this.app.clock.bpm}`; + } + if (this.app.exampleIsPlaying) { + tryEvaluate(this.app, this.app.example_buffer); + } else { + tryEvaluate(this.app, this.app.global_buffer); + } + } // Implement TransportNode clock callback and update clock info with it - }; convertTicksToTimeposition(ticks: number): TimePosition { @@ -108,27 +111,27 @@ export class Clock { } get next_beat_in_ticks(): number { - return this.app.clock.pulses_since_origin + this.time_position.pulse; + return this.app.clock.pulses_since_origin + this.time_position.pulse; } get beats_per_bar(): number { - return this.time_signature[0]; + return this.time_signature[0]; } get beats_since_origin(): number { - return Math.floor(this.tick / this.ppqn); + return Math.floor(this.tick / this.ppqn); } get pulses_since_origin(): number { - return this.tick; + return this.tick; } get pulse_duration(): number { - return 60 / this.bpm / this.ppqn; + return 60 / this.bpm / this.ppqn; } public pulse_duration_at_bpm(bpm: number = this.bpm): number { - return 60 / bpm / this.ppqn; + return 60 / bpm / this.ppqn; } get bpm(): number { @@ -162,7 +165,7 @@ export class Clock { } public nextTickFrom(time: number, nudge: number): number { - const pulseDuration = this.pulse_duration; + const pulseDuration = this.pulse_duration; const nudgedTime = time + nudge; const nextTickTime = Math.ceil(nudgedTime / pulseDuration) * pulseDuration; const remainingTime = nextTickTime - nudgedTime; @@ -183,13 +186,13 @@ export class Clock { this.app.audioContext.resume(); this.running = true; this.app.api.MidiConnection.sendStartMessage(); - this.clock.start() + this.clock.start(); } public pause(): void { this.running = false; this.app.api.MidiConnection.sendStopMessage(); - this.clock.pause() + this.clock.pause(); } public stop(): void { @@ -204,4 +207,4 @@ export class Clock { this.app.api.MidiConnection.sendStopMessage(); this.clock.stop(); } -} \ No newline at end of file +} diff --git a/src/TransportNode.js b/src/TransportNode.js deleted file mode 100644 index 7dd5e21..0000000 --- a/src/TransportNode.js +++ /dev/null @@ -1,68 +0,0 @@ -import { tryEvaluate } from "./Evaluator"; -const zeroPad = (num, places) => String(num).padStart(places, "0"); - -export class TransportNode extends AudioWorkletNode { - constructor(context, options, application) { - super(context, "transport", options); - this.app = application; - this.port.addEventListener("message", this.handleMessage); - this.port.start(); - this.timeviewer = document.getElementById("timeviewer"); - } - - /** @type {(this: MessagePort, ev: MessageEvent) => any} */ - handleMessage = (message) => { - if (message.data) { - if (message.data.type === "bang") { - 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; - if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) { - this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${ - futureTimeStamp.beat + 1 - } / ${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(message.data.bpm); - } - } - } - }; - - start() { - this.port.postMessage({ type: "start" }); - } - - pause() { - this.port.postMessage({ type: "pause" }); - } - - resume() { - this.port.postMessage({ type: "resume" }); - } - - setBPM(bpm) { - this.port.postMessage({ type: "bpm", value: bpm }); - } - - setPPQN(ppqn) { - this.port.postMessage({ type: "ppqn", value: ppqn }); - } - - setNudge(nudge) { - this.port.postMessage({ type: "nudge", value: nudge }); - } - - stop() { - this.port.postMessage({ type: "stop" }); - } -} diff --git a/src/classes/AbstractEvents.ts b/src/classes/AbstractEvents.ts index 72aa7e6..84f5537 100644 --- a/src/classes/AbstractEvents.ts +++ b/src/classes/AbstractEvents.ts @@ -1,5 +1,11 @@ import { type Editor } from "../main"; -import { freqToMidi, chord as parseChord, noteNameToMidi, resolvePitchBend, safeScale } from "zifferjs"; +import { + freqToMidi, + chord as parseChord, + noteNameToMidi, + resolvePitchBend, + safeScale, +} from "zifferjs"; import { SkipEvent } from "./SkipEvent"; export type EventOperation = (instance: T, ...args: any[]) => void; @@ -311,16 +317,16 @@ export abstract class AudibleEvent extends AbstractEvent { return this; }; - protected updateValue( - key: string, - value: T | T[] | null - ): this { + protected updateValue(key: string, value: T | T[] | null): this { if (value == null) return this; this.values[key] = value; return this; } - public note = (value: number | string | null, ...kwargs: number[]|string[]) => { + public note = ( + value: number | string | null, + ...kwargs: number[] | string[] + ) => { if (typeof value === "string") { const parsedNote = noteNameToMidi(value); return this.updateValue("note", [parsedNote, ...kwargs].flat(Infinity)); @@ -331,8 +337,8 @@ export abstract class AudibleEvent extends AbstractEvent { } }; - public chord = (value: number|string, ...kwargs: number[]) => { - if(typeof value === "string") { + public chord = (value: number | string, ...kwargs: number[]) => { + if (typeof value === "string") { const chord = parseChord(value); return this.updateValue("note", chord); } else { diff --git a/src/classes/SoundEvent.ts b/src/classes/SoundEvent.ts index 74a9e27..cc210ee 100644 --- a/src/classes/SoundEvent.ts +++ b/src/classes/SoundEvent.ts @@ -5,10 +5,7 @@ import { arrayOfObjectsToObjectWithArrays, objectWithArraysToArrayOfObjects, } from "../Utils/Generic"; -import { - midiToFreq, - noteFromPc, -} from "zifferjs"; +import { midiToFreq, noteFromPc } from "zifferjs"; import { superdough, @@ -66,7 +63,7 @@ export class SoundEvent extends AudibleEvent { phaserDepth: ["phaserDepth", "phasdepth"], phaserSweep: ["phaserSweep", "phassweep"], phaserCenter: ["phaserCenter", "phascenter"], - fmadsr: function( + fmadsr: function ( self: SoundEvent, a: number, d: number, @@ -79,7 +76,7 @@ export class SoundEvent extends AudibleEvent { self.updateValue("fmrelease", r); return self; }, - fmad: function(self: SoundEvent, a: number, d: number) { + fmad: function (self: SoundEvent, a: number, d: number) { self.updateValue("fmattack", a); self.updateValue("fmdecay", d); return self; @@ -90,7 +87,7 @@ export class SoundEvent extends AudibleEvent { decay: ["decay", "dec"], sustain: ["sustain", "sus"], release: ["release", "rel"], - adsr: function( + adsr: function ( self: SoundEvent, a: number, d: number, @@ -103,21 +100,21 @@ export class SoundEvent extends AudibleEvent { self.updateValue("release", r); return self; }, - ad: function(self: SoundEvent, a: number, d: number) { + ad: function (self: SoundEvent, a: number, d: number) { self.updateValue("attack", a); self.updateValue("decay", d); self.updateValue("sustain", 0.0); self.updateValue("release", 0.0); return self; }, - scope: function(self: SoundEvent) { - self.updateValue("analyze", true) - return self + scope: function (self: SoundEvent) { + self.updateValue("analyze", true); + return self; }, - debug: function(self: SoundEvent, callback?: Function) { - self.updateValue("debug", true) + debug: function (self: SoundEvent, callback?: Function) { + self.updateValue("debug", true); if (callback) { - self.updateValue("debugFunction", callback) + self.updateValue("debugFunction", callback); } return self; }, @@ -126,27 +123,27 @@ export class SoundEvent extends AudibleEvent { lpdecay: ["lpdecay", "lpd"], lpsustain: ["lpsustain", "lps"], lprelease: ["lprelease", "lpr"], - cutoff: function(self: SoundEvent, value: number, resonance?: number) { + cutoff: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("cutoff", value); if (resonance) { self.updateValue("resonance", resonance); } return self; }, - lpf: function(self: SoundEvent, value: number, resonance?: number) { + lpf: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("cutoff", value); if (resonance) { self.updateValue("resonance", resonance); } return self; }, - resonance: function(self: SoundEvent, value: number) { + resonance: function (self: SoundEvent, value: number) { if (value >= 0 && value <= 1) { self.updateValue("resonance", 50 * value); } return self; }, - lpadsr: function( + lpadsr: function ( self: SoundEvent, depth: number, a: number, @@ -161,7 +158,7 @@ export class SoundEvent extends AudibleEvent { self.updateValue("lprelease", r); return self; }, - lpad: function(self: SoundEvent, depth: number, a: number, d: number) { + lpad: function (self: SoundEvent, depth: number, a: number, d: number) { self.updateValue("lpenv", depth); self.updateValue("lpattack", a); self.updateValue("lpdecay", d); @@ -174,25 +171,25 @@ export class SoundEvent extends AudibleEvent { hpdecay: ["hpdecay", "hpd"], hpsustain: ["hpsustain", "hpsus"], hprelease: ["hprelease", "hpr"], - hcutoff: function(self: SoundEvent, value: number, resonance?: number) { + hcutoff: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("hcutoff", value); if (resonance) { self.updateValue("hresonance", resonance); } return self; }, - hpf: function(self: SoundEvent, value: number, resonance?: number) { + hpf: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("hcutoff", value); if (resonance) { self.updateValue("hresonance", resonance); } return self; }, - hpq: function(self: SoundEvent, value: number) { + hpq: function (self: SoundEvent, value: number) { self.updateValue("hresonance", value); return self; }, - hpadsr: function( + hpadsr: function ( self: SoundEvent, depth: number, a: number, @@ -207,7 +204,7 @@ export class SoundEvent extends AudibleEvent { self.updateValue("hprelease", r); return self; }, - hpad: function(self: SoundEvent, depth: number, a: number, d: number) { + hpad: function (self: SoundEvent, depth: number, a: number, d: number) { self.updateValue("hpenv", depth); self.updateValue("hpattack", a); self.updateValue("hpdecay", d); @@ -220,14 +217,14 @@ export class SoundEvent extends AudibleEvent { bpdecay: ["bpdecay", "bpd"], bpsustain: ["bpsustain", "bps"], bprelease: ["bprelease", "bpr"], - bandf: function(self: SoundEvent, value: number, resonance?: number) { + bandf: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("bandf", value); if (resonance) { self.updateValue("bandq", resonance); } return self; }, - bpf: function(self: SoundEvent, value: number, resonance?: number) { + bpf: function (self: SoundEvent, value: number, resonance?: number) { self.updateValue("bandf", value); if (resonance) { self.updateValue("bandq", resonance); @@ -235,7 +232,7 @@ export class SoundEvent extends AudibleEvent { return self; }, bandq: ["bandq", "bpq"], - bpadsr: function( + bpadsr: function ( self: SoundEvent, depth: number, a: number, @@ -250,7 +247,7 @@ export class SoundEvent extends AudibleEvent { self.updateValue("bprelease", r); return self; }, - bpad: function(self: SoundEvent, depth: number, a: number, d: number) { + bpad: function (self: SoundEvent, depth: number, a: number, d: number) { self.updateValue("bpenv", depth); self.updateValue("bpattack", a); self.updateValue("bpdecay", d); @@ -260,7 +257,7 @@ export class SoundEvent extends AudibleEvent { }, vib: ["vib"], vibmod: ["vibmod"], - fm: function(self: SoundEvent, value: number | string) { + fm: function (self: SoundEvent, value: number | string) { if (typeof value === "number") { self.values["fmi"] = value; } else { @@ -276,11 +273,11 @@ export class SoundEvent extends AudibleEvent { begin: ["begin"], end: ["end"], gain: ["gain"], - dbgain: function(self: SoundEvent, value: number) { + dbgain: function (self: SoundEvent, value: number) { self.updateValue("gain", Math.min(Math.pow(10, value / 20), 10)); return self; }, - db: function(self: SoundEvent, value: number) { + db: function (self: SoundEvent, value: number) { self.updateValue("gain", Math.min(Math.pow(10, value / 20), 10)); return self; }, @@ -303,32 +300,32 @@ export class SoundEvent extends AudibleEvent { roomlp: ["roomlp", "rlp"], roomdim: ["roomdim", "rdim"], sound: ["s", "sound"], - size: function(self: SoundEvent, value: number) { + size: function (self: SoundEvent, value: number) { self.updateValue("roomsize", value); return self; }, - sz: function(self: SoundEvent, value: number) { + sz: function (self: SoundEvent, value: number) { self.updateValue("roomsize", value); return self; }, comp: ["compressor", "cmp"], - ratio: function(self: SoundEvent, value: number) { + ratio: function (self: SoundEvent, value: number) { self.updateValue("compressorRatio", value); return self; }, - knee: function(self: SoundEvent, value: number) { + knee: function (self: SoundEvent, value: number) { self.updateValue("compressorKnee", value); return self; }, - compAttack: function(self: SoundEvent, value: number) { + compAttack: function (self: SoundEvent, value: number) { self.updateValue("compressorAttack", value); return self; }, - compRelease: function(self: SoundEvent, value: number) { + compRelease: function (self: SoundEvent, value: number) { self.updateValue("compressorRelease", value); return self; }, - stretch: function(self: SoundEvent, beat: number) { + stretch: function (self: SoundEvent, beat: number) { self.updateValue("unit", "c"); self.updateValue("speed", 1 / beat); self.updateValue("cut", beat); @@ -467,16 +464,12 @@ export class SoundEvent extends AudibleEvent { } if (this.values["debug"]) { if (this.values["debugFunction"]) { - this.values["debugFunction"](filteredEvent) + this.values["debugFunction"](filteredEvent); } else { - console.log(filteredEvent) + console.log(filteredEvent); } } - superdough( - filteredEvent, - this.app.clock.deadline, - filteredEvent.dur, - ); + superdough(filteredEvent, this.app.clock.deadline, filteredEvent.dur); } }; } diff --git a/src/documentation/more/oscilloscope.ts b/src/documentation/more/oscilloscope.ts index 22c2d90..7e43a23 100644 --- a/src/documentation/more/oscilloscope.ts +++ b/src/documentation/more/oscilloscope.ts @@ -10,17 +10,18 @@ You can turn on the oscilloscope to generate interesting visuals or to inspect a You need to manually feed the scope with the sounds you want to inspect: ${makeExample( - "Feeding a sine to the oscilloscope", - ` + "Feeding a sine to the oscilloscope", + ` beat(1)::sound('sine').freq(200).ad(0, .2).scope().out() -`, true - )} +`, + true, +)} Here is a layout of the scope configuration options: ${makeExample( - "Oscilloscope configuration", - ` + "Oscilloscope configuration", + ` scope({ enabled: true, // off by default color: "#fdba74", // any valid CSS color or "random" @@ -34,12 +35,12 @@ scope({ refresh: 1 // refresh rate (in pulses) }) `, - true, - )} + true, +)} ${makeExample( - "Demo with multiple scope mode", - ` + "Demo with multiple scope mode", + ` rhythm(.5, [4,5].dur(4*3, 4*1), 8)::sound('fhardkick').out() beat(0.25)::sound('square').freq([ [250, 250/2, 250/4].pick(), @@ -55,8 +56,8 @@ scope({enabled: true, thickness: 8, color: ['purple', 'green', 'random'].beat(), size: 0.5, fftSize: 2048}) `, - true, - )} + true, +)} Note that these values can be patterned as well! You can transform the oscilloscope into its own light show if you want. The picture is not stable anyway so you won't have much use of it for precision work :) diff --git a/src/extensions/NumberExtensions.ts b/src/extensions/NumberExtensions.ts index 84a781b..6c592cd 100644 --- a/src/extensions/NumberExtensions.ts +++ b/src/extensions/NumberExtensions.ts @@ -25,7 +25,7 @@ declare global { z15(): Player; z16(): Player; midi(): MidiEvent; - sound(name: string): SoundEvent|SkipEvent; + sound(name: string): SoundEvent | SkipEvent; } } @@ -102,11 +102,11 @@ export const makeNumberExtensions = (api: UserAPI) => { return api.midi(this.valueOf(), ...kwargs); }; - Number.prototype.sound = function (name: string): SoundEvent|SkipEvent { + Number.prototype.sound = function (name: string): SoundEvent | SkipEvent { if (Number.isInteger(this.valueOf())) { return (api.sound(name) as SoundEvent).note(this.valueOf()); } else { return (api.sound(name) as SoundEvent).freq(this.valueOf()); - } + } }; }; From e5a331c6cf31c8fe3a05a23801dc87118985116c Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 12:19:42 +0100 Subject: [PATCH 08/10] clean --- src/main.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4b5569a..c541883 100644 --- a/src/main.ts +++ b/src/main.ts @@ -246,20 +246,17 @@ export class Editor { "ui-known-universe-item-template", ) as HTMLTemplateElement; if (!itemTemplate) { - console.warn("Missing template #ui-known-universe-item-template"); return; } let existing_universes = document.getElementById("existing-universes"); if (!existing_universes) { - console.warn("Missing element #existing-universes"); return; } let list = document.createElement("ul"); list.className = "lg:h-80 lg:text-normal text-sm h-auto lg:w-80 w-auto lg:pb-2 lg:pt-2 overflow-y-scroll text-white lg:mb-4 border rounded-lg bg-neutral-800"; - list.append( ...Object.keys(this.universes).map((it) => { let item = itemTemplate.content.cloneNode(true) as DocumentFragment; From bcb0ddc1cb88a0ae742465500ba2a7b4bb74d00b Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Fri, 1 Dec 2023 12:30:33 +0100 Subject: [PATCH 09/10] document clock --- src/Clock.ts | 111 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/src/Clock.ts b/src/Clock.ts index 6583bf5..7bc162b 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -22,27 +22,25 @@ export interface TimePosition { export class Clock { /** - * The Clock Class is responsible for keeping track of the current time. - * It is also responsible for starting and stopping the Clock TransportNode. * - * @param app - The main application instance - * @param clock - The zyklus clock - * @param ctx - The current AudioContext used by app - * @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 app - main application instance + * @param clock - zyklus clock + * @param ctx - current AudioContext used by app + * @param bpm - current beats per minute value + * @param time_signature - time signature + * @param time_position - current time position + * @param ppqn - pulses per quarter note + * @param tick - current tick since origin * @param running - Is the clock running? */ + private _bpm: number; + private _ppqn: number; clock: any; ctx: AudioContext; logicalTime: number; - private _bpm: number; time_signature: number[]; time_position: TimePosition; - private _ppqn: number; tick: number; running: boolean; timeviewer: HTMLElement; @@ -69,6 +67,14 @@ export class Clock { } clockCallback = (time: number, duration: number, tick: number) => { + /** + * Callback function for the zyklus clock. Updates the clock info and sends a + * MIDI clock message if the setting is enabled. Also evaluates the global buffer. + * + * @param time - precise AudioContext time when the tick should happen + * @param duration - seconds between each tick + * @param tick - count of the current tick + */ let deadline = time - getAudioContext().currentTime; this.deadline = deadline; this.tick = tick; @@ -96,6 +102,12 @@ export class Clock { }; convertTicksToTimeposition(ticks: number): TimePosition { + /** + * Converts ticks to a time position. + * + * @param ticks - ticks to convert + * @returns TimePosition + */ const beatsPerBar = this.app.clock.time_signature[0]; const ppqnPosition = ticks % this.app.clock.ppqn; const beatNumber = Math.floor(ticks / this.app.clock.ppqn); @@ -105,71 +117,121 @@ export class Clock { } get ticks_before_new_bar(): number { + /** + * Calculates the number of ticks before the next bar. + * + * @returns number - ticks before the next bar + */ const ticskMissingFromBeat = this.ppqn - this.time_position.pulse; const beatsMissingFromBar = this.beats_per_bar - this.time_position.beat; return beatsMissingFromBar * this.ppqn + ticskMissingFromBeat; } get next_beat_in_ticks(): number { + /** + * Calculates the number of ticks before the next beat. + * + * @returns number - ticks before the next beat + */ return this.app.clock.pulses_since_origin + this.time_position.pulse; } get beats_per_bar(): number { + /** + * Returns the number of beats per bar. + * + * @returns number - beats per bar + */ return this.time_signature[0]; } get beats_since_origin(): number { + /** + * Returns the number of beats since the origin. + * + * @returns number - beats since the origin + */ return Math.floor(this.tick / this.ppqn); } get pulses_since_origin(): number { + /** + * Returns the number of pulses since the origin. + * + * @returns number - pulses since the origin + */ return this.tick; } get pulse_duration(): number { + /** + * Returns the duration of a pulse in seconds. + * @returns number - duration of a pulse in seconds + */ 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 given bpm. + * + * @param bpm - bpm to calculate the pulse duration for + * @returns number - duration of a pulse in seconds + */ return 60 / bpm / this.ppqn; } get bpm(): number { + /** + * Returns the current bpm. + * @returns number - current bpm + */ return this._bpm; } - get tickDuration() { + get tickDuration(): number { + /** + * Returns the duration of a tick in seconds. + * @returns number - duration of a tick in seconds + */ return 1 / this.ppqn; } set bpm(bpm: number) { + /** + * Sets the bpm. + * @param bpm - bpm to set + */ if (bpm > 0 && this._bpm !== bpm) { this._bpm = bpm; - this.logicalTime = this.realTime; this.clock.setDuration(() => (this.tickDuration * 60) / this.bpm); } } get ppqn(): number { + /** + * Returns the current ppqn. + * @returns number - current ppqn + */ return this._ppqn; } set ppqn(ppqn: number) { + /** + * Sets the ppqn. + * @param ppqn - ppqn to set + * @returns number - current ppqn + */ if (ppqn > 0 && this._ppqn !== ppqn) { this._ppqn = ppqn; } } - public incrementTick() { - this.tick++; - } - public nextTickFrom(time: number, nudge: number): number { const pulseDuration = this.pulse_duration; const nudgedTime = time + nudge; const nextTickTime = Math.ceil(nudgedTime / pulseDuration) * pulseDuration; const remainingTime = nextTickTime - nudgedTime; - return remainingTime; } @@ -179,8 +241,8 @@ export class Clock { public start(): void { /** - * Starts the TransportNode (starts the clock). - * + * Start the clock + * * @remark also sends a MIDI message if a port is declared */ this.app.audioContext.resume(); @@ -190,6 +252,11 @@ export class Clock { } public pause(): void { + /** + * Pause the clock. + * + * @remark also sends a MIDI message if a port is declared + */ this.running = false; this.app.api.MidiConnection.sendStopMessage(); this.clock.pause(); @@ -197,7 +264,7 @@ export class Clock { public stop(): void { /** - * Stops the TransportNode (stops the clock). + * Stops the clock. * * @remark also sends a MIDI message if a port is declared */ From 0e63f872710eee4900bef39a96e8d61126003d2e Mon Sep 17 00:00:00 2001 From: Raphael Forment Date: Sat, 2 Dec 2023 10:44:12 +0100 Subject: [PATCH 10/10] prepare version --- src/API.ts | 31 +++---------------------------- src/Clock.ts | 6 +++--- src/InterfaceLogic.ts | 7 ++++--- 3 files changed, 10 insertions(+), 34 deletions(-) diff --git a/src/API.ts b/src/API.ts index 63699e5..8e4950a 100644 --- a/src/API.ts +++ b/src/API.ts @@ -1298,7 +1298,7 @@ export class UserAPI { const results: boolean[] = nArray.map( (value) => (this.app.clock.pulses_since_origin - Math.floor(nudge * this.ppqn())) % - Math.floor(value * this.ppqn()) === + Math.floor(value * this.ppqn()) === 0, ); return results.some((value) => value === true); @@ -1318,7 +1318,7 @@ export class UserAPI { const results: boolean[] = nArray.map( (value) => (this.app.clock.pulses_since_origin - nudgeInPulses) % - Math.floor(value * barLength) === + Math.floor(value * barLength) === 0, ); return results.some((value) => value === true); @@ -1790,18 +1790,6 @@ export class UserAPI { return sum / values.length; }; - public range = ( - inputY: number, - yMin: number, - yMax: number, - xMin: number, - xMax: number, - ): number => { - const percent = (inputY - yMin) / (yMax - yMin); - const outputX = percent * (xMax - xMin) + xMin; - return outputX; - }; - limit = (value: number, min: number, max: number): number => { /** * Limits a value between a minimum and a maximum. @@ -1928,7 +1916,7 @@ export class UserAPI { // ============================================================= register = (name: string, operation: EventOperation): void => { - AbstractEvent.prototype[name] = function ( + AbstractEvent.prototype[name] = function( this: AbstractEvent, ...args: any[] ) { @@ -2111,19 +2099,6 @@ export class UserAPI { // Transport functions // ============================================================= - public nudge = (nudge?: number): number => { - /** - * Sets or returns the current clock nudge. - * - * @param nudge - [optional] the nudge to set - * @returns The current nudge - */ - if (nudge) { - this.app.clock.nudge = nudge; - } - return this.app.clock.nudge; - }; - public tempo = (n?: number): number => { /** * Sets or returns the current bpm. diff --git a/src/Clock.ts b/src/Clock.ts index 7bc162b..e47c730 100644 --- a/src/Clock.ts +++ b/src/Clock.ts @@ -66,6 +66,7 @@ export class Clock { ); } + // @ts-ignore clockCallback = (time: number, duration: number, tick: number) => { /** * Callback function for the zyklus clock. Updates the clock info and sends a @@ -87,9 +88,8 @@ export class Clock { ); this.app.clock.time_position = futureTimeStamp; if (futureTimeStamp.pulse % this.app.clock.ppqn == 0) { - this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${ - futureTimeStamp.beat + 1 - } / ${this.app.clock.bpm}`; + this.timeviewer.innerHTML = `${zeroPad(futureTimeStamp.bar, 2)}:${futureTimeStamp.beat + 1 + } / ${this.app.clock.bpm}`; } if (this.app.exampleIsPlaying) { tryEvaluate(this.app, this.app.example_buffer); diff --git a/src/InterfaceLogic.ts b/src/InterfaceLogic.ts index 0f55f3d..290a757 100644 --- a/src/InterfaceLogic.ts +++ b/src/InterfaceLogic.ts @@ -144,9 +144,10 @@ export const installInterfaceLogic = (app: Editor) => { }); app.interface.audio_nudge_range.addEventListener("input", () => { - app.clock.nudge = parseInt( - (app.interface.audio_nudge_range as HTMLInputElement).value, - ); + // TODO: rebuild this + // app.clock.nudge = parseInt( + // (app.interface.audio_nudge_range as HTMLInputElement).value, + // ); }); app.interface.dough_nudge_range.addEventListener("input", () => {