diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 07f763c3..9b08778b 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -787,6 +787,20 @@ export class Pattern { return this.fmap((x) => pure(x)._fast(factor))._squeezeJoin(); } + /** + * Cuts each sample into the given number of parts, allowing you to explore a technique known as 'granular synthesis'. + * It turns a pattern of samples into a pattern of parts of samples. + * @name chop + * @memberof Pattern + * @returns Pattern + * @example + * samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' }) + * s("p") + * .chop(128) + * .loopAt(32,1) + * .jux(rev) + * .out() + */ _chop(n) { const slices = Array.from({ length: n }, (x, i) => i); const slice_objects = slices.map((i) => ({ begin: i / n, end: (i + 1) / n })); @@ -1242,7 +1256,17 @@ export class Pattern { return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity })); } - // move this to controls? (speed and unit are controls) + /** + * Makes the sample fit the given number of cycles by changing the speed. + * @name loopAt + * @memberof Pattern + * @returns Pattern + * @example + * samples({ p: 'https://cdn.freesound.org/previews/648/648433_11943129-lq.mp3' }) + * s("p") + * .loopAt(8,1) + * .out() + */ _loopAt(factor, cps = 1) { return this.speed((1 / factor) * cps) .unit('c') diff --git a/tutorial/tutorial.mdx b/tutorial/tutorial.mdx index 61c6e398..6ed38e8c 100644 --- a/tutorial/tutorial.mdx +++ b/tutorial/tutorial.mdx @@ -365,7 +365,13 @@ note("g2!2 !2, g4 f4]>") The sampler will always pick the closest matching sample for the current note! -## Effects +## Sampler Effects + +{{ 'Pattern.loopAt' | jsdoc }} + +{{ 'Pattern.chop' | jsdoc }} + +## Audio Effects Wether you're using a synth or a sample, you can apply these effects: