Skip to content

Commit

Permalink
Match behaviour of chunk with tidal, add fastChunk for old strudel be…
Browse files Browse the repository at this point in the history
…haviour. Also adds repeatCycles. fixes #689
  • Loading branch information
yaxu committed Sep 29, 2023
1 parent 80ea9e8 commit 67ef449
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 12 deletions.
33 changes: 29 additions & 4 deletions packages/core/pattern.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2100,25 +2100,50 @@ export const { iterBack, iterback } = register(['iterBack', 'iterback'], functio
return _iter(times, pat, true);
});

/**
* Repeats each cycle the given number of times.
* @name repeatCycles
* @memberof Pattern
* @returns Pattern
* @example
* note(irand(12).add(34)).segment(4).repeatCycles(2).s("gm_acoustic_guitar_nylon")
*/
const _repeatCycles = function (n, pat) {
return slowcat(...Array(n).fill(pat));
}

const { repeatCycles } = register('repeatCycles', _repeatCycles);

/**
* Divides a pattern into a given number of parts, then cycles through those parts in turn, applying the given function to each part in turn (one part per cycle).
* @name chunk
* @synonyms slowChunk, slowchunk
* @memberof Pattern
* @returns Pattern
* @example
* "0 1 2 3".chunk(4, x=>x.add(7)).scale('A minor').note()
*/
const _chunk = function (n, func, pat, back = false) {
const _chunk = function (n, func, pat, back = false, fast = false) {
const binary = Array(n - 1).fill(false);
binary.unshift(true);
const binary_pat = _iter(n, sequence(...binary), back);
// Invert the 'back' because we want to shift the pattern forwards,
// and so time backwards
const binary_pat = _iter(n, sequence(...binary), !back);
if (!fast) {
pat = pat.repeatCycles(n);
}
return pat.when(binary_pat, func);
};

export const chunk = register('chunk', function (n, func, pat) {
return _chunk(n, func, pat, false);
const {chunk, slowchunk, slowChunk} = register(['chunk', 'slowchunk', 'slowChunk'], function (n, func, pat) {
return _chunk(n, func, pat, false, false);
});

const {fastchunk, fastChunk} = register(['fastchunk', 'fastChunk'], function (n, func, pat) {
return _chunk(n, func, pat, false, true);
});


/**
* Like `chunk`, but cycles through the parts in reverse order. Known as chunk' in tidalcycles
* @name chunkBack
Expand Down
16 changes: 16 additions & 0 deletions packages/core/test/pattern.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,4 +1003,20 @@ describe('Pattern', () => {
);
});
});
describe('chunk', () => {
it('Processes each cycle of the source pattern multiple times, once for each chunk', () => {
expect(sequence(0, 1, 2, 3).slow(2).chunk(2, add(10)).fast(4).firstCycleValues).toStrictEqual([ 10, 1, 0, 11, 12, 3, 2, 13 ])
});
});
describe('fastChunk', () => {
it('Unlike chunk, cycles of the source pattern proceed cycle-by-cycle', () => {
expect(sequence(0, 1, 2, 3).slow(2).fastChunk(2, add(10)).fast(4).firstCycleValues).toStrictEqual([ 10,1,2,13,10,1,2,13 ])
});
});
describe('repeatCycles', () => {
it('Repeats each cycle of the source pattern the given number of times', () => {
expect(slowcat(0, 1).repeatCycles(2).fast(6).firstCycleValues).toStrictEqual([ 0,0,1,1,0,0 ])
});
});

});
37 changes: 29 additions & 8 deletions test/__snapshots__/examples.test.mjs.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1087,17 +1087,17 @@ exports[`runs examples > example "chunk" example index 0 1`] = `
"[ 1/2 → 3/4 | note:C4 ]",
"[ 3/4 → 1/1 | note:D4 ]",
"[ 1/1 → 5/4 | note:A3 ]",
"[ 5/4 → 3/2 | note:B3 ]",
"[ 5/4 → 3/2 | note:B4 ]",
"[ 3/2 → 7/4 | note:C4 ]",
"[ 7/4 → 2/1 | note:D5 ]",
"[ 7/4 → 2/1 | note:D4 ]",
"[ 2/1 → 9/4 | note:A3 ]",
"[ 9/4 → 5/2 | note:B3 ]",
"[ 5/2 → 11/4 | note:C5 ]",
"[ 11/4 → 3/1 | note:D4 ]",
"[ 3/1 → 13/4 | note:A3 ]",
"[ 13/4 → 7/2 | note:B4 ]",
"[ 13/4 → 7/2 | note:B3 ]",
"[ 7/2 → 15/4 | note:C4 ]",
"[ 15/4 → 4/1 | note:D4 ]",
"[ 15/4 → 4/1 | note:D5 ]",
]
`;

Expand All @@ -1108,17 +1108,17 @@ exports[`runs examples > example "chunkBack" example index 0 1`] = `
"[ 1/2 → 3/4 | note:C4 ]",
"[ 3/4 → 1/1 | note:D4 ]",
"[ 1/1 → 5/4 | note:A3 ]",
"[ 5/4 → 3/2 | note:B4 ]",
"[ 5/4 → 3/2 | note:B3 ]",
"[ 3/2 → 7/4 | note:C4 ]",
"[ 7/4 → 2/1 | note:D4 ]",
"[ 7/4 → 2/1 | note:D5 ]",
"[ 2/1 → 9/4 | note:A3 ]",
"[ 9/4 → 5/2 | note:B3 ]",
"[ 5/2 → 11/4 | note:C5 ]",
"[ 11/4 → 3/1 | note:D4 ]",
"[ 3/1 → 13/4 | note:A3 ]",
"[ 13/4 → 7/2 | note:B3 ]",
"[ 13/4 → 7/2 | note:B4 ]",
"[ 7/2 → 15/4 | note:C4 ]",
"[ 15/4 → 4/1 | note:D5 ]",
"[ 15/4 → 4/1 | note:D4 ]",
]
`;

Expand Down Expand Up @@ -3528,6 +3528,27 @@ exports[`runs examples > example "release" example index 0 1`] = `
]
`;

exports[`runs examples > example "repeatCycles" example index 0 1`] = `
[
"[ 0/1 → 1/4 | note:42 s:gm_acoustic_guitar_nylon ]",
"[ 1/4 → 1/2 | note:38 s:gm_acoustic_guitar_nylon ]",
"[ 1/2 → 3/4 | note:35 s:gm_acoustic_guitar_nylon ]",
"[ 3/4 → 1/1 | note:38 s:gm_acoustic_guitar_nylon ]",
"[ 1/1 → 5/4 | note:42 s:gm_acoustic_guitar_nylon ]",
"[ 5/4 → 3/2 | note:38 s:gm_acoustic_guitar_nylon ]",
"[ 3/2 → 7/4 | note:35 s:gm_acoustic_guitar_nylon ]",
"[ 7/4 → 2/1 | note:38 s:gm_acoustic_guitar_nylon ]",
"[ 2/1 → 9/4 | note:42 s:gm_acoustic_guitar_nylon ]",
"[ 9/4 → 5/2 | note:36 s:gm_acoustic_guitar_nylon ]",
"[ 5/2 → 11/4 | note:39 s:gm_acoustic_guitar_nylon ]",
"[ 11/4 → 3/1 | note:41 s:gm_acoustic_guitar_nylon ]",
"[ 3/1 → 13/4 | note:42 s:gm_acoustic_guitar_nylon ]",
"[ 13/4 → 7/2 | note:36 s:gm_acoustic_guitar_nylon ]",
"[ 7/2 → 15/4 | note:39 s:gm_acoustic_guitar_nylon ]",
"[ 15/4 → 4/1 | note:41 s:gm_acoustic_guitar_nylon ]",
]
`;

exports[`runs examples > example "reset" example index 0 1`] = `
[
"[ 0/1 → 1/4 | s:hh ]",
Expand Down

0 comments on commit 67ef449

Please sign in to comment.