Removed latency calculation

This commit is contained in:
2023-08-30 00:21:50 +03:00
parent 287fdbbad4
commit f8a0a8e6f5
5 changed files with 62 additions and 123 deletions

View File

@ -366,7 +366,7 @@ export class UserAPI {
const key = id==="" ? this.generateCacheKey(input, options) : zid; const key = id==="" ? this.generateCacheKey(input, options) : zid;
let player; let player;
if (this.app.api.patternCache.has(key)) { if (this.app.api.patternCache.has(key)) {
player = this.app.api.patternCache.get(key) as Player; player = this.app.api.patternCache.get(key) as Player;
if(player.input!==input) { if(player.input!==input) {
@ -379,7 +379,6 @@ export class UserAPI {
this.app.api.patternCache.set(key, player); this.app.api.patternCache.set(key, player);
} }
if(typeof id === "number") player.zid = zid; if(typeof id === "number") player.zid = zid;
player.updateLastCallTime(); player.updateLastCallTime();
@ -950,16 +949,12 @@ export class UserAPI {
*/ */
let final_pulses: boolean[] = []; let final_pulses: boolean[] = [];
beat.forEach((b) => { beat.forEach((b) => {
b = b % this.app.clock.time_signature[0] || this.app.clock.time_signature[0]; const beat = b % this.app.clock.time_signature[0] || this.app.clock.time_signature[0];
let integral_part = Math.floor(b); const integral_part = Math.floor(beat);
console.log("INTEGRAL: ", integral_part, this.app.clock.time_position.beat) const decimal_part = ((beat - integral_part) * this.app.clock.ppqn) + 1;
let decimal_part = (b - integral_part)+1;
console.log("HUH?", this.app.clock.time_position);
console.log("DECIMAL:",decimal_part, this.app.clock.time_position.pulse)
final_pulses.push( final_pulses.push(
integral_part === this.app.clock.time_position.beat && integral_part === this.app.clock.time_position.beat &&
this.app.clock.time_position.pulse === this.app.clock.time_position.pulse === decimal_part
decimal_part * this.app.clock.ppqn
); );
}); });
return final_pulses.some((p) => p == true); return final_pulses.some((p) => p == true);

View File

@ -43,7 +43,7 @@ export class Clock {
constructor(public app: Editor, ctx: AudioContext) { constructor(public app: Editor, ctx: AudioContext) {
this.time_position = { bar: 0, beat: 0, pulse: 0 } this.time_position = { bar: 0, beat: 0, pulse: 0 }
this.time_signature = [4, 4]; this.time_signature = [4, 4];
this.tick = -1; this.tick = 0;
this._bpm = 120; this._bpm = 120;
this._ppqn = 48; this._ppqn = 48;
this.transportNode = null; this.transportNode = null;
@ -65,9 +65,9 @@ export class Clock {
* *
* @returns number of ticks until next bar * @returns number of ticks until next bar
*/ */
const currentBeatInTicks = ((this.app.clock.beats_since_origin * this.ppqn) + this.time_position.pulse); const ticskMissingFromBeat = this.ppqn - this.time_position.pulse;
const nextBarinTicks = (this.beats_per_bar * this.ppqn) * this.time_position.bar; const beatsMissingFromBar = this.beats_per_bar - this.time_position.beat;
return nextBarinTicks - currentBeatInTicks; return (beatsMissingFromBar * this.ppqn) + ticskMissingFromBeat;
} }
get next_beat_in_ticks(): number { get next_beat_in_ticks(): number {
@ -77,8 +77,7 @@ export class Clock {
* *
* @returns number of ticks until next beat * @returns number of ticks until next beat
*/ */
const ticksMissingToNextBeat = (this.time_position.pulse) % this.ppqn; return this.app.clock.pulses_since_origin + this.time_position.pulse;
return this.app.clock.pulses_since_origin + ticksMissingToNextBeat;
} }
get beats_per_bar(): number { get beats_per_bar(): number {
@ -143,9 +142,7 @@ export class Clock {
/** /**
* Starts the TransportNode (starts the clock). * Starts the TransportNode (starts the clock).
*/ */
// @ts-ignore this.app.audioContext.resume();
console.log("STARTING?");
this.app.audioContext.resume()
this.transportNode?.start(); this.transportNode?.start();
} }
@ -161,6 +158,7 @@ export class Clock {
/** /**
* Stops the TransportNode (stops the clock). * Stops the TransportNode (stops the clock).
*/ */
this.app.clock.tick = 0;
this.transportNode?.stop(); this.transportNode?.stop();
} }
} }

View File

@ -8,17 +8,6 @@ export class TransportNode extends AudioWorkletNode {
this.app = application this.app = application
this.port.addEventListener("message", this.handleMessage); this.port.addEventListener("message", this.handleMessage);
this.port.start(); this.port.start();
/** @type {HTMLSpanElement} */
this.$clock = document.getElementById("clockviewer");
this.currentPulsePosition = 0;
this.executionLatency = 0;
this.lastLatencies = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
this.indexOfLastLatencies = 0;
this.logicalTime = 0; this.logicalTime = 0;
} }
@ -26,25 +15,26 @@ export class TransportNode extends AudioWorkletNode {
handleMessage = (message) => { handleMessage = (message) => {
if (message.data && message.data.type === "bang") { if (message.data && message.data.type === "bang") {
this.logicalTime = message.data.logicalTime; this.logicalTime = message.data.logicalTime;
this.app.clock.tick++
let futureTimeStamp = this.convertTicksToTimeposition(this.app.clock.tick); let futureTimeStamp = this.convertTicksToTimeposition(this.app.clock.tick);
console.log("BANG", this.logicalTime, futureTimeStamp); // console.log("BANG", this.logicalTime, futureTimeStamp);
setTimeout(() => {
console.log("EVALUATING");
const now = this.app.audioContext.currentTime;
this.app.clock.time_position = futureTimeStamp;
tryEvaluate(this.app, this.app.global_buffer);
const then = this.app.audioContext.currentTime;
this.lastLatencies[this.indexOfLastLatencies] = then - now;
this.indexOfLastLatencies = (this.indexOfLastLatencies + 1) % this.lastLatencies.length;
const averageLatency = this.lastLatencies.reduce((a, b) => a + b) / this.lastLatencies.length;
this.executionLatency = averageLatency / 1000;
}, (this.app.clock.pulse_duration + this.executionLatency) * 1000);
this.app.clock.time_position = futureTimeStamp;
tryEvaluate(this.app, this.app.global_buffer);
} }
}; };
convertTicksToTimeposition(ticks) {
const beatsPerBar = this.app.clock.time_signature[0];
const ppqnPosition = (ticks % this.app.clock.ppqn)+1;
const beatNumber = Math.floor(ticks / this.app.clock.ppqn);
const barNumber = Math.floor(beatNumber / beatsPerBar)+1;
const beatWithinBar = Math.floor(beatNumber % beatsPerBar)+1;
this.app.clock.tick++
return {bar: barNumber, beat: beatWithinBar, pulse: ppqnPosition};
}
start() { start() {
this.port.postMessage("start"); this.port.postMessage("start");
} }
@ -62,46 +52,7 @@ export class TransportNode extends AudioWorkletNode {
} }
stop() { stop() {
this.app.clock.tick = 0;
// this.$clock.innerHTML = `[${1} | ${1} | ${zeroPad(1, '2')}]`;
this.port.postMessage("stop"); this.port.postMessage("stop");
} }
convertTimeToBarsBeats(currentTime) {
const beatDuration = 60 / this.app.clock.bpm;
const beatNumber = (currentTime) / beatDuration;
const beatsPerBar = this.app.clock.time_signature[0];
const barNumber = Math.floor(beatNumber / beatsPerBar) + 1;
const beatWithinBar = Math.floor(beatNumber % beatsPerBar) + 1;
const ppqnPosition = Math.floor((beatNumber % 1) * this.app.clock.ppqn);
this.app.clock.tick++
return { bar: barNumber, beat: beatWithinBar, ppqn: ppqnPosition };
}
convertTimeToNextBarsBeats(currentTime) {
const beatDuration = 60 / this.app.clock.bpm;
const beatNumber = (currentTime) / beatDuration;
const beatsPerBar = this.app.clock.time_signature[0];
this.currentPulsePosition = beatNumber * this.app.clock.ppqn;
const nextPulsePosition = Math.ceil(this.currentPulsePosition);
const timeToNextPulse = this.app.clock.convertPulseToSecond(this.nextPulsePosition - this.currentPulsePosition);
const futureBeatNumber = this.nextPulsePosition / this.app.clock.ppqn;
const futureBarNumber = futureBeatNumber / beatsPerBar;
}
convertTicksToTimeposition(ticks) {
const beatsPerBar = this.app.clock.time_signature[0];
const ppqnPosition = (ticks % this.app.clock.ppqn)+1;
const beatNumber = Math.floor(ticks / this.app.clock.ppqn);
const barNumber = Math.floor(beatNumber / beatsPerBar)+1;
const beatWithinBar = Math.floor(beatNumber % beatsPerBar)+1;
return {bar: barNumber, beat: beatWithinBar, pulse: ppqnPosition};
}
} }

View File

@ -48,15 +48,13 @@ class TransportProcessor extends AudioWorkletProcessor {
this.startedAgainTime = currentTime; this.startedAgainTime = currentTime;
this.wasStopped = false; this.wasStopped = false;
} }
const logicalTime = currentTime-this.totalPausedTime-this.startedAgainTime; const logicalTime = currentTime-this.totalPausedTime-this.startedAgainTime;
//console.log(currentTime, this.totalPausedTime, this.startedAgainTime);
//console.log("Logical/Current:", logicalTime, currentTime);
const beatNumber = logicalTime / (60 / this.bpm); const beatNumber = logicalTime / (60 / this.bpm);
const nextPulsePosition = Math.ceil(beatNumber * this.ppqn); const currentPulsePosition = Math.ceil(beatNumber * this.ppqn);
if(nextPulsePosition > this.currentPulsePosition) { if(currentPulsePosition > this.currentPulsePosition) {
this.currentPulsePosition = nextPulsePosition; this.currentPulsePosition = currentPulsePosition;
this.port.postMessage({ type: "bang", logicalTime }); this.port.postMessage({ type: "bang", logicalTime });
} }
} }

View File

@ -11,17 +11,19 @@ export type InputOptions = { [key: string]: string | number };
export class Player extends Event { export class Player extends Event {
input: string; input: string;
ziffers: Ziffers; ziffers: Ziffers;
initCallTime: number = 0; initCallTime: number = 1;
startCallTime: number = 0; startCallTime: number = 1;
lastCallTime: number = 0; lastCallTime: number = 1;
waitTime = 0; waitTime = 0;
startBeat: number = 0; startBeat: number = 0;
played: boolean = false; played: boolean = false;
current!: Pitch|Chord|ZRest; current!: Pitch|Chord|ZRest;
retro: boolean = false; retro: boolean = false;
index: number = -1; index: number = -1;
zid: string|undefined = undefined; zid: string = "";
options: InputOptions = {}; options: InputOptions = {};
skipIndex = 0;
endTime = 0;
constructor(input: string, options: InputOptions, public app: Editor) { constructor(input: string, options: InputOptions, public app: Editor) {
super(app); super(app);
@ -61,15 +63,15 @@ export class Player extends Event {
} }
firstRun = (): boolean => { firstRun = (): boolean => {
return this.origin()<=0 && this.notStarted(); return this.notStarted();
} }
atTheBeginning = (): boolean => { atTheBeginning = (): boolean => {
return this.ziffers.index===0; return this.skipIndex === 0 && this.ziffers.index<=0;
} }
origin = (): number => { origin = (): number => {
return this.app.clock.pulses_since_origin+1; return this.app.clock.pulses_since_origin;
} }
pulse = (): number => { pulse = (): number => {
@ -86,10 +88,13 @@ export class Player extends Event {
// Check if it's time to play the event // Check if it's time to play the event
areWeThereYet = (): boolean => { areWeThereYet = (): boolean => {
// If clock has stopped // If clock has stopped
if(this.app.clock.pulses_since_origin<this.lastCallTime) { if(this.app.clock.pulses_since_origin<this.lastCallTime) {
this.lastCallTime = 0; this.lastCallTime = 1;
this.startCallTime = 1;
this.index = 0; this.index = 0;
this.waitTime = 0;
} }
// Main logic // Main logic
@ -97,24 +102,28 @@ export class Player extends Event {
( // If pattern is just starting ( // If pattern is just starting
this.notStarted() && this.notStarted() &&
(this.app.clock.time_position.pulse === 1 || (this.app.clock.time_position.pulse === 1 ||
this.app.clock.pulses_since_origin+1 >= this.app.clock.next_beat_in_ticks) && this.app.clock.pulses_since_origin >= this.app.clock.next_beat_in_ticks) &&
(this.app.clock.pulses_since_origin+1 >= this.waitTime) (this.app.clock.pulses_since_origin >= this.waitTime)
) )
|| ||
( // If pattern is already playing ( // If pattern is already playing
this.current && this.current &&
(this.pulseToSecond(this.app.clock.pulses_since_origin+1) >= (this.pulseToSecond(this.app.clock.pulses_since_origin) >=
this.pulseToSecond(this.lastCallTime) + this.pulseToSecond(this.lastCallTime) +
(this.current.duration*4) * this.pulseToSecond(this.app.api.ppqn())) && (this.current.duration*4) * this.pulseToSecond(this.app.api.ppqn())) &&
(this.app.clock.pulses_since_origin+1 >= this.waitTime) (this.app.clock.pulses_since_origin >= this.waitTime)
) )
); );
// Increment index of how many times call is skipped
this.skipIndex = howAboutNow ? 0 : this.skipIndex+1;
// Increment index of how many times sound/midi have been called // Increment index of how many times sound/midi have been called
this.index = howAboutNow ? this.index+1 : this.index; this.index = howAboutNow ? this.index+1 : this.index;
if(howAboutNow && this.notStarted()) { if(howAboutNow && this.notStarted()) {
this.initCallTime = this.app.clock.pulses_since_origin+1; this.initCallTime = this.app.clock.pulses_since_origin;
} }
if(this.atTheBeginning()) { if(this.atTheBeginning()) {
@ -159,10 +168,7 @@ export class Player extends Event {
} }
key(name: string) { key(name: string) {
if(this.firstRun() || this.atTheBeginning()) { if(this.atTheBeginning()) this.ziffers.key(name);
console.log("At", this.app.clock.time_position);
this.ziffers.key(name);
}
return this; return this;
} }
@ -176,23 +182,14 @@ export class Player extends Event {
return this; return this;
} }
wait(value: number) { wait(value: number|Function) {
if(this.index === -1 && this.ziffers.index === -1) { if(this.atTheBeginning()) {
if(typeof value === "function") {
// TODO: THIS LATER! const refPat = this.app.api.patternCache.get(value.name) as Player;
if(refPat) this.waitTime = refPat.nextEndTime();
/* if(typeof value === "string") { return this;
const cueKey = this.app.api.patternCues.get(value); }
if(cueKey) {
const waitedPatter = this.app.api.patternCache.get(cueKey) as Player;
if(waitedPatter) {
this.waitTime = waitedPatter.nextEndTime();
}
}
} */
this.waitTime = this.origin() + Math.ceil(value*4*this.app.clock.ppqn); this.waitTime = this.origin() + Math.ceil(value*4*this.app.clock.ppqn);
} }
return this; return this;
} }