diff --git a/packages/core/util.mjs b/packages/core/util.mjs index c375de7b..1958a896 100644 --- a/packages/core/util.mjs +++ b/packages/core/util.mjs @@ -366,7 +366,7 @@ export function objectMap(obj, fn) { // utility for averaging two clocks together to account for drift export class ClockCollator { - constructor({ getTargetClockTime = () => Date.now() / 1000, weight = 16, offsetDelta = 0.005, checkAfterTime = 2 }) { + constructor({ getTargetClockTime = () => Date.now() / 1000, weight = 16, offsetDelta = 0.005, checkAfterTime = 2, resetAfterTime = 8 }) { this.offsetTime; this.timeAtPrevOffsetSample; this.prevOffsetTimes = []; @@ -374,12 +374,18 @@ export class ClockCollator { this.weight = weight; this.offsetDelta = offsetDelta; this.checkAfterTime = checkAfterTime; + this.resetAfterTime = resetAfterTime } calculateTimestamp(currentTime, targetTime) { const targetClockTime = this.getTargetClockTime(); - // const unixTimeSecs = Date.now() / 1000; + const diffBetweenTimeSamples = targetClockTime - this.timeAtPrevOffsetSample; const newOffsetTime = targetClockTime - currentTime; + // recalcuate the diff from scratch if the clock has been paused for some time. + if (diffBetweenTimeSamples > this.resetAfterTime) { + this.prevOffsetTimes = [] + } + if (this.offsetTime == null) { this.offsetTime = newOffsetTime; } @@ -387,9 +393,12 @@ export class ClockCollator { if (this.prevOffsetTimes.length > this.weight) { this.prevOffsetTimes.shift(); } + // after X time has passed, the average of the previous weight offset times is calculated and used as a stable reference // for calculating the timestamp - if (this.timeAtPrevOffsetSample == null || targetClockTime - this.timeAtPrevOffsetSample > this.checkAfterTime) { + if (this.timeAtPrevOffsetSample == null || diffBetweenTimeSamples > this.checkAfterTime) { + + this.timeAtPrevOffsetSample = targetClockTime; const rollingOffsetTime = averageArray(this.prevOffsetTimes); //when the clock offsets surpass the delta, set the new reference time diff --git a/website/src/repl/useReplContext.jsx b/website/src/repl/useReplContext.jsx index d61699b6..55f12faa 100644 --- a/website/src/repl/useReplContext.jsx +++ b/website/src/repl/useReplContext.jsx @@ -14,7 +14,6 @@ import { resetLoadedSounds, initAudioOnFirstClick, } from '@strudel/webaudio'; -import { defaultAudioDeviceName } from '../settings.mjs'; import { getAudioDevices, setAudioDevice, setVersionDefaultsFrom } from './util.mjs'; import { StrudelMirror, defaultSettings } from '@strudel/codemirror'; import { clearHydra } from '@strudel/hydra'; @@ -28,6 +27,8 @@ import { getViewingPatternData, setViewingPatternData, } from '../user_pattern_utils.mjs'; +import { superdirtOutput } from '@strudel/osc/superdirtoutput'; +import { audioEngineTargets, defaultAudioDeviceName } from '../settings.mjs'; import { useStore } from '@nanostores/react'; import { prebake } from './prebake.mjs'; import { getRandomTune, initCode, loadModules, shareCode } from './util.mjs'; @@ -55,13 +56,15 @@ async function getModule(name) { } export function useReplContext() { - const { isSyncEnabled } = useSettings(); + const { panelPosition, isZen, isSyncEnabled, audioEngineTarget } = useSettings(); + const defaultOutput = audioEngineTarget === audioEngineTargets.superdirt ? superdirtOutput : webaudioOutput; + const init = useCallback(() => { const drawTime = [-2, 2]; const drawContext = getDrawContext(); const editor = new StrudelMirror({ sync: isSyncEnabled, - defaultOutput: webaudioOutput, + defaultOutput, getTime: () => getAudioContext().currentTime, setInterval, clearInterval, diff --git a/website/src/repl/util.mjs b/website/src/repl/util.mjs index 25d481f1..905e16b0 100644 --- a/website/src/repl/util.mjs +++ b/website/src/repl/util.mjs @@ -2,14 +2,11 @@ import { evalScope, hash2code, logger } from '@strudel/core'; import { settingPatterns, defaultAudioDeviceName } from '../settings.mjs'; import { getAudioContext, initializeAudioOutput, setDefaultAudioContext, setVersionDefaults } from '@strudel/webaudio'; import { getMetadata } from '../metadata_parser'; - import { isTauri } from '../tauri.mjs'; import './Repl.css'; - import { createClient } from '@supabase/supabase-js'; import { nanoid } from 'nanoid'; import { writeText } from '@tauri-apps/api/clipboard'; -import { createContext } from 'react'; import { $featuredPatterns, loadDBPatterns } from '@src/user_pattern_utils.mjs'; // Create a single supabase client for interacting with your database