diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 5d67026c..a65a72e9 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -1415,25 +1415,32 @@ export function register(name, func, patternify = true) { const arity = func.length; var pfunc; // the patternified function - pfunc = function (...args) { - args = args.map(reify); - const pat = args[args.length - 1]; - if (arity === 1) { - return func(pat); - } - const [left, ...right] = args.slice(0, -1); - let mapFn = (...args) => { - // make sure to call func with the correct argument count - // args.length is expected to be <= arity-1 - // so we set undefined args explicitly undefined - Array(arity - 1) - .fill() - .map((_, i) => args[i] ?? undefined); - return func(...args, pat); + if (patternify) { + pfunc = function (...args) { + args = args.map(reify); + const pat = args[args.length - 1]; + if (arity === 1) { + return func(pat); + } + const [left, ...right] = args.slice(0, -1); + let mapFn = (...args) => { + // make sure to call func with the correct argument count + // args.length is expected to be <= arity-1 + // so we set undefined args explicitly undefined + Array(arity - 1) + .fill() + .map((_, i) => args[i] ?? undefined); + return func(...args, pat); + }; + mapFn = curry(mapFn, null, arity - 1); + return right.reduce((acc, p) => acc.appLeft(p), left.fmap(mapFn)).innerJoin(); }; - mapFn = curry(mapFn, null, arity - 1); - return right.reduce((acc, p) => acc.appLeft(p), left.fmap(mapFn)).innerJoin(); - }; + } else { + pfunc = function (...args) { + args = args.map(reify); + return func(...args); + }; + } Pattern.prototype[name] = function (...args) { // For methods that take a single argument (plus 'this'), allow @@ -2231,11 +2238,13 @@ const _loopAt = function (factor, pat, cps = 1) { * @example * await samples('github:tidalcycles/Dirt-Samples/master') * s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(1.5) + */ + const slice = register( 'slice', function (npat, ipat, opat) { return npat.innerBind((n) => - ipat.outerBind((i) => + ipat.outerBind((i) => opat.outerBind((o) => { // If it's not an object, assume it's a string and make it a 's' control parameter o = o instanceof Object ? o : { s: o }; @@ -2248,7 +2257,6 @@ const slice = register( }, false, // turns off auto-patternification ); -*/ /* * Works the same as slice, but changes the playback speed of each slice to match the duration of its step. @@ -2258,6 +2266,8 @@ const slice = register( * @example * await samples('github:tidalcycles/Dirt-Samples/master') * s("breaks165").splice(8, "0 1 [2 3 0]@2 3 0@2 7").hurry(0.65) + */ + const splice = register( 'splice', function (npat, ipat, opat) { @@ -2273,8 +2283,7 @@ const splice = register( }); }, false, // turns off auto-patternification - ); - */ +); const { loopAt, loopat } = register(['loopAt', 'loopat'], function (factor, pat) { return _loopAt(factor, pat, 1); diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs index b5d8cb92..308b76ce 100644 --- a/packages/core/repl.mjs +++ b/packages/core/repl.mjs @@ -21,7 +21,7 @@ export function repl({ onTrigger: async (hap, deadline, duration, cps) => { try { if (!hap.context.onTrigger || !hap.context.dominantTrigger) { - await defaultOutput(hap, deadline, duration); + await defaultOutput(hap, deadline, duration, cps); } if (hap.context.onTrigger) { // call signature of output / onTrigger is different... diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 43838c53..c8267306 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -976,6 +976,7 @@ describe('Pattern', () => { sameFirst(n(0, 1).weave(2, s('bd', silence), s(silence, 'sd')), sequence(s('bd').n(0), s('sd').n(1))); }); }); + */ describe('slice', () => { it('Can slice a sample', () => { sameFirst( @@ -1001,5 +1002,5 @@ describe('Pattern', () => { ), ); }); - });*/ + }); }); diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index b377b9e3..1f4e3375 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -191,7 +191,7 @@ function effectSend(input, effect, wet) { } // export const webaudioOutput = async (t, hap, ct, cps) => { -export const webaudioOutput = async (hap, deadline, hapDuration) => { +export const webaudioOutput = async (hap, deadline, hapDuration, cps) => { const ac = getAudioContext(); hap.ensureObjectValue(); @@ -305,7 +305,7 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => { bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value; if (unit === 'c') { // are there other units? - bufferSource.playbackRate.value = bufferSource.playbackRate.value * bufferSource.buffer.duration; + bufferSource.playbackRate.value = bufferSource.playbackRate.value * bufferSource.buffer.duration * cps; } let duration = soundfont || clip ? hapDuration : bufferSource.buffer.duration / bufferSource.playbackRate.value; // "The computation of the offset into the sound is performed using the sound buffer's natural sample rate, @@ -378,7 +378,7 @@ export const webaudioOutput = async (hap, deadline, hapDuration) => { chain[0].onended = () => chain.concat([delaySend, reverbSend]).forEach((n) => n?.disconnect()); }; -export const webaudioOutputTrigger = (t, hap, ct, cps) => webaudioOutput(hap, t - ct, hap.duration / cps); +export const webaudioOutputTrigger = (t, hap, ct, cps) => webaudioOutput(hap, t - ct, hap.duration / cps, cps); Pattern.prototype.webaudio = function () { // TODO: refactor (t, hap, ct, cps) to (hap, deadline, duration) ?