diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 6bd05e28..59b33816 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -973,6 +973,10 @@ export class Pattern { _velocity(velocity) { return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity })); } + + _loopAt(factor,cps=1) { + return this.speed((1/factor)*cps).unit("c").slow(factor) + } } // TODO - adopt value.mjs fully.. @@ -1396,6 +1400,10 @@ Pattern.prototype.chunkBack = function (...args) { args = args.map(reify); return patternify2(Pattern.prototype._chunkBack)(...args, this); }; +Pattern.prototype.loopAt = function (...args) { + args = args.map(reify); + return patternify2(Pattern.prototype._loopAt)(...args, this); +}; Pattern.prototype.zoom = function (...args) { args = args.map(reify); return patternify2(Pattern.prototype._zoom)(...args, this); diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs index 95030d6a..4d4ed55b 100644 --- a/packages/osc/osc.mjs +++ b/packages/osc/osc.mjs @@ -10,15 +10,19 @@ import { Pattern } from '@strudel.cycles/core'; const comm = new OSC(); comm.open(); const latency = 0.1; +let startedAt = -1; Pattern.prototype.osc = function () { return this._withHap((hap) => { - const onTrigger = (time, hap, currentTime) => { + const onTrigger = (time, hap, currentTime, cps, cycle, delta) => { // time should be audio time of onset // currentTime should be current time of audio context (slightly before time) - const keyvals = Object.entries(hap.value).flat(); - const offset = (time - currentTime + latency) * 1000; - const ts = Math.floor(Date.now() + offset); + if (startedAt < 0) { + startedAt = Date.now() - (currentTime * 1000); + } + const controls = Object.assign({}, { cps: cps, cycle: cycle, delta: delta }, hap.value); + const keyvals = Object.entries(controls).flat(); + const ts = Math.floor(startedAt + ((time + latency) * 1000)); const message = new OSC.Message('/dirt/play', ...keyvals); const bundle = new OSC.Bundle([message], ts); bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60 diff --git a/packages/react/src/hooks/useRepl.mjs b/packages/react/src/hooks/useRepl.mjs index 4f3791d6..8db4bb0c 100644 --- a/packages/react/src/hooks/useRepl.mjs +++ b/packages/react/src/hooks/useRepl.mjs @@ -57,7 +57,14 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP /* console.warn('no instrument chosen', event); throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ } else { - onTrigger(time, event, currentTime); + onTrigger( + time, + event, + currentTime, + 1 /* cps */, + event.wholeOrPart().begin.valueOf(), + event.duration.valueOf(), + ); } } catch (err) { console.warn(err);