diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 2d7a8f43..dd02e529 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -1603,6 +1603,15 @@ export const { fast, density } = register(['fast', 'density'], function (factor, return fastQuery.withHapTime((t) => t.div(factor)); }); +/** + * Both speeds up the pattern (like 'fast') and the sample playback (like 'speed'). + * @example + * s("bd sd:2").hurry("<1 2 4 3>").slow(1.5) + */ +export const hurry = register('hurry', function (r, pat) { + return pat._fast(r).mul(pure({ speed: r })); +}); + /** * Slow down a pattern over the given number of cycles. Like the "/" operator in mini notation. * @@ -1857,6 +1866,29 @@ export const rev = register('rev', function (pat) { return new Pattern(query).splitQueries(); }); +/** Like press, but allows you to specify the amount by which each + * event is shifted. pressBy(0.5) is the same as press, while + * pressBy(1/3) shifts each event by a third of its timespan. + * @example + * stack(s("hh*4"), + * s("bd mt sd ht").pressBy("<0 0.5 0.25>") + * ).slow(2) + */ +export const pressBy = register('pressBy', function (r, pat) { + return pat.fmap((x) => pure(x).compress(r, 1)).squeezeJoin(); +}); + +/** + * Syncopates a rhythm, by shifting each event halfway into its timespan. + * @example + * stack(s("hh*4"), + * s("bd mt sd ht").every(4, press) + * ).slow(2) + */ +export const press = register('press', function (pat) { + return pat._pressBy(0.5); +}); + /** * Silences a pattern. * @example diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index 31b080b6..08638d18 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -949,4 +949,14 @@ describe('Pattern', () => { expect(stack(sequence('a', silence), pure('a').mask(0, 1)).defragmentHaps().firstCycle().length).toStrictEqual(2); }); }); + describe('press', () => { + it('Can syncopate events', () => { + sameFirst(sequence('a', 'b', 'c', 'd').press(), sequence(silence, 'a', silence, 'b', silence, 'c', silence, 'd')); + }); + }); + describe('hurry', () => { + it('Can speed up patterns and sounds', () => { + sameFirst(s('a', 'b').hurry(2), s('a', 'b').fast(2).speed(2)); + }); + }); });