diff --git a/js/strudel.mjs b/js/strudel.mjs index 13d4aef8..af50b44e 100644 --- a/js/strudel.mjs +++ b/js/strudel.mjs @@ -483,12 +483,6 @@ class Pattern { return stack([left,func(right)]) } - -// def first_cycle(self): -// return self.query(TimeSpan(Fraction(0), Fraction(1))) - -// def __repr__(self): -// return str(self.first_cycle()) } function reify(thing) { @@ -506,6 +500,10 @@ function pure(value) { return new Pattern(query) } +function steady(value) { + return new Pattern(span => Hap(undefined, span, value)) +} + function stack(pats) { var pats = pats.map(reify) var query = function(span) { @@ -536,5 +534,65 @@ function cat(pats) { return fastcat(pats) } -export {Fraction, TimeSpan, Hap, Pattern, pure, stack, slowcat, fastcat, cat} +function _sequenceCount(x) { + if(Array.isArray(x)) { + if (x.length == 0) { + return [silence(),0] + } + if (x.length == 1) { + return _sequenceCount(x[0]) + } + return [fastcat(x.map(a => _sequenceCount(a)[0])), x.length] + } + return [reify(x), 1] +} + +function sequence(...xs) { + return _sequenceCount(xs)[0] +} + +function polymeter(steps=0, ...args) { + var seqs = args.map(_sequenceCount) + if (seqs.length == 0) { + return silence() + } + if (steps == 0) { + steps = seqs[0][1] + } + var pats = [] + for (var seq of seqs) { + if (seq[1] == 0) { + next + } + if (steps == seq[1]) { + pats.push(seq[0]) + } + else { + pats.push(seq[0]._fast(Fraction(steps).div(Fraction(seq[1])))) + } + } + return stack(pats) +} + +function silence() { + return new Pattern(_ => []) +} + +// # alias +// pm = polymeter + +// def polyrhythm(*xs): +// seqs = [sequence(x) for x in xs] + +// if len(seqs) == 0: +// return silence() + +// return stack(seqs) + +// # alias +// pr = polyrhythm + + +export {Fraction, TimeSpan, Hap, Pattern, + pure, stack, slowcat, fastcat, cat, sequence, polymeter} diff --git a/test/pattern.test.mjs b/test/pattern.test.mjs index f746784d..dbf08722 100644 --- a/test/pattern.test.mjs +++ b/test/pattern.test.mjs @@ -2,7 +2,7 @@ import Fraction from 'fraction.js' import { strict as assert } from 'assert'; -import {TimeSpan, Hap, Pattern, pure, stack, fastcat, slowcat, cat} from "../js/strudel.mjs"; +import {TimeSpan, Hap, Pattern, pure, stack, fastcat, slowcat, cat, sequence} from "../js/strudel.mjs"; describe('TimeSpan', function() { describe('equals()', function() { @@ -120,4 +120,9 @@ describe('Pattern', function() { assert.deepStrictEqual(fastcat([pure("a"), pure("b"), pure("c")]).rev().firstCycle.sort((a,b) => a.part.begin.sub(b.part.begin)).map(a => a.value), ["c", "b","a"]) }) }) + describe('sequence()', function () { + it('Can work like fastcat', function () { + assert.deepStrictEqual(sequence(1,2,3).firstCycle, fastcat([pure(1), pure(2), pure(3)]).firstCycle) + }) + }) }) \ No newline at end of file