From abaab89061137380e4dff74a3d5a3f0499655ac8 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Thu, 19 Sep 2024 23:26:30 +0100 Subject: [PATCH 1/2] Add bite function (#1187) For patterning slices of patterns. ref #31. --- packages/core/pattern.mjs | 28 ++++ test/__snapshots__/examples.test.mjs.snap | 150 ++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 7ef605d51..b94198f34 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -2046,6 +2046,34 @@ export const { zoomArc, zoomarc } = register(['zoomArc', 'zoomarc'], function (a return pat.zoom(a.begin, a.end); }); +/** + * Splits a pattern into the given number of slices, and plays them according to a pattern of slice numbers. + * Similar to `slice`, but slices up patterns rather than sound samples. + * @param {number} number of slices + * @param {number} slices to play + * @example + * note("0 1 2 3 4 5 6 7".scale('c:mixolydian')) + *.bite(4, "3 2 1 0") + * @example + * sound("bd - bd bd*2, - sd:6 - sd:5 sd:1 - [- sd:2] -, hh [- cp:7]") + .bank("RolandTR909").speed(1.2) + .bite(4, "0 0 [1 2] <3 2> 0 0 [2 1] 3") + */ +export const bite = register( + 'bite', + (npat, ipat, pat) => { + return ipat + .fmap((i) => (n) => { + const a = Fraction(i).div(n).mod(1); + const b = a.add(Fraction(1).div(n)); + return pat.zoom(a, b); + }) + .appLeft(npat) + .squeezeJoin(); + }, + false, +); + /** * Selects the given fraction of the pattern and repeats that part to fill the remainder of the cycle. * @param {number} fraction fraction to select diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 56da88365..a74987d98 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -967,6 +967,156 @@ exports[`runs examples > example "begin" example index 0 1`] = ` ] `; +exports[`runs examples > example "bite" example index 0 1`] = ` +[ + "[ 0/1 → 1/8 | note:Bb3 ]", + "[ 1/8 → 1/4 | note:C4 ]", + "[ 1/4 → 3/8 | note:G3 ]", + "[ 3/8 → 1/2 | note:A3 ]", + "[ 1/2 → 5/8 | note:E3 ]", + "[ 5/8 → 3/4 | note:F3 ]", + "[ 3/4 → 7/8 | note:C3 ]", + "[ 7/8 → 1/1 | note:D3 ]", + "[ 1/1 → 9/8 | note:Bb3 ]", + "[ 9/8 → 5/4 | note:C4 ]", + "[ 5/4 → 11/8 | note:G3 ]", + "[ 11/8 → 3/2 | note:A3 ]", + "[ 3/2 → 13/8 | note:E3 ]", + "[ 13/8 → 7/4 | note:F3 ]", + "[ 7/4 → 15/8 | note:C3 ]", + "[ 15/8 → 2/1 | note:D3 ]", + "[ 2/1 → 17/8 | note:Bb3 ]", + "[ 17/8 → 9/4 | note:C4 ]", + "[ 9/4 → 19/8 | note:G3 ]", + "[ 19/8 → 5/2 | note:A3 ]", + "[ 5/2 → 21/8 | note:E3 ]", + "[ 21/8 → 11/4 | note:F3 ]", + "[ 11/4 → 23/8 | note:C3 ]", + "[ 23/8 → 3/1 | note:D3 ]", + "[ 3/1 → 25/8 | note:Bb3 ]", + "[ 25/8 → 13/4 | note:C4 ]", + "[ 13/4 → 27/8 | note:G3 ]", + "[ 27/8 → 7/2 | note:A3 ]", + "[ 7/2 → 29/8 | note:E3 ]", + "[ 29/8 → 15/4 | note:F3 ]", + "[ 15/4 → 31/8 | note:C3 ]", + "[ 31/8 → 4/1 | note:D3 ]", +] +`; + +exports[`runs examples > example "bite" example index 1 1`] = ` +[ + "[ 0/1 → 1/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 0/1 → 1/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 1/16 → 1/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 1/8 → 1/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 1/8 → 1/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 3/16 → 1/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 1/4 → 5/16 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 9/32 → 5/16 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 5/16 → 11/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 5/16 → 3/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/8 → 7/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/8 → 1/2 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 13/32 → 7/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 7/16 → 1/2 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 1/2 → 5/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 1/2 → 5/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 9/16 → 5/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 5/8 → 3/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 5/8 → 3/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 11/16 → 3/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 3/4 → 25/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 3/4 → 13/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 13/16 → 7/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 27/32 → 7/8 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 7/8 → 15/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 7/8 → 1/1 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 29/32 → 15/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 15/16 → 1/1 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 1/1 → 9/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 1/1 → 9/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 17/16 → 9/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 9/8 → 5/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 9/8 → 5/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 19/16 → 5/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 5/4 → 21/16 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 41/32 → 21/16 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 21/16 → 43/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 21/16 → 11/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 11/8 → 23/16 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 11/8 → 3/2 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/2 → 13/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/2 → 13/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 25/16 → 13/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 13/8 → 7/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 13/8 → 7/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 27/16 → 7/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 7/4 → 57/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 7/4 → 29/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 29/16 → 15/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 59/32 → 15/8 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 15/8 → 31/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 15/8 → 2/1 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 61/32 → 31/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 31/16 → 2/1 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 2/1 → 17/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 2/1 → 17/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 33/16 → 17/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 17/8 → 9/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 17/8 → 9/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 35/16 → 9/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 9/4 → 37/16 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 73/32 → 37/16 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 37/16 → 75/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 37/16 → 19/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 19/8 → 39/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 19/8 → 5/2 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 77/32 → 39/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 39/16 → 5/2 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 5/2 → 21/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 5/2 → 21/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 41/16 → 21/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 21/8 → 11/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 21/8 → 11/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 43/16 → 11/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 11/4 → 89/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 11/4 → 45/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 45/16 → 23/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 91/32 → 23/8 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 23/8 → 47/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 23/8 → 3/1 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 93/32 → 47/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 47/16 → 3/1 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/1 → 25/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 3/1 → 25/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 49/16 → 25/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 25/8 → 13/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 25/8 → 13/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 51/16 → 13/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 13/4 → 53/16 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 105/32 → 53/16 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 53/16 → 107/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 53/16 → 27/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 27/8 → 55/16 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 27/8 → 7/2 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 7/2 → 29/8 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 7/2 → 29/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 57/16 → 29/8 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 29/8 → 15/4 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 29/8 → 15/4 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 59/16 → 15/4 | s:sd n:6 bank:RolandTR909 speed:1.2 ]", + "[ 15/4 → 121/32 | s:sd n:1 bank:RolandTR909 speed:1.2 ]", + "[ 15/4 → 61/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 61/16 → 31/8 | s:hh bank:RolandTR909 speed:1.2 ]", + "[ 123/32 → 31/8 | s:sd n:5 bank:RolandTR909 speed:1.2 ]", + "[ 31/8 → 63/16 | s:bd bank:RolandTR909 speed:1.2 ]", + "[ 31/8 → 4/1 | s:cp n:7 bank:RolandTR909 speed:1.2 ]", + "[ 125/32 → 63/16 | s:sd n:2 bank:RolandTR909 speed:1.2 ]", + "[ 63/16 → 4/1 | s:bd bank:RolandTR909 speed:1.2 ]", +] +`; + exports[`runs examples > example "bpattack" example index 0 1`] = ` [ "[ 0/1 → 1/4 | note:c2 s:sawtooth bandf:500 bpattack:0.5 bpenv:4 ]", From b75561e3c79dacadf66b1c8b1e3b577a7b43d2c6 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Fri, 20 Sep 2024 21:26:41 +0100 Subject: [PATCH 2/2] Fix serial timing (#1188) * fix serial timing * format --- packages/serial/serial.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/serial/serial.mjs b/packages/serial/serial.mjs index 81eb42f26..e0eeacedd 100644 --- a/packages/serial/serial.mjs +++ b/packages/serial/serial.mjs @@ -68,7 +68,7 @@ Pattern.prototype.serial = function (br = 115200, sendcrc = false, singlecharids if (!(name in writeMessagers)) { getWriter(name, br); } - const onTrigger = (time, hap, currentTime) => { + const onTrigger = (t_deprecate, hap, currentTime, cps, targetTime) => { var message = ''; var chk = 0; if (typeof hap.value === 'object') { @@ -105,7 +105,7 @@ Pattern.prototype.serial = function (br = 115200, sendcrc = false, singlecharids } else { message = hap.value; } - const offset = (time - currentTime + latency) * 1000; + const offset = (targetTime - currentTime + latency) * 1000; window.setTimeout(function () { writeMessagers[name](message, chk);