diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 4874a35f..72596b33 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -3112,3 +3112,25 @@ export let xfade = (a, pos, b) => { Pattern.prototype.xfade = function (pos, b) { return xfade(this, pos, b); }; + +/** + * creates a structure pattern from divisions of a cycle + * especially useful for creating rhythms + * @name beat + * @example + * s("bd").beat("0:7:10", 16) + * @example + * s("sd").beat("4:12", 16) + */ +const __beat = (join) => (t, div, pat) => { + t = Fraction(t).mod(div); + div = Fraction(div); + const b = t.div(div); + const e = t.add(1).div(div); + return join(pat.fmap((x) => pure(x)._compress(b, e))); +}; + +export const { beat } = register( + ['beat'], + __beat((x) => x.innerJoin()), +); diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 761c95fa..6b149bc1 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -954,6 +954,24 @@ exports[`runs examples > example "bank" example index 0 1`] = ` ] `; +exports[`runs examples > example "beat" example index 0 1`] = ` +[ + "[ 0/1 → 1/16 | s:bd ]", + "[ 1/1 → 17/16 | s:bd ]", + "[ 2/1 → 33/16 | s:bd ]", + "[ 3/1 → 49/16 | s:bd ]", +] +`; + +exports[`runs examples > example "beat" example index 1 1`] = ` +[ + "[ 1/48 → 1/12 | s:sd ]", + "[ 49/48 → 13/12 | s:sd ]", + "[ 97/48 → 25/12 | s:sd ]", + "[ 145/48 → 37/12 | s:sd ]", +] +`; + exports[`runs examples > example "begin" example index 0 1`] = ` [ "[ 0/1 → 1/2 | s:rave begin:0 ]",