mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-11 05:38:34 +00:00
Tidying up core (#256)
* remove _ prefixes except for functions to be patternified * categorise pattern methods * experimental support for `.add.squeeze` and friends as alternative to `.addSqueeze` * `every` is now an alias for `firstOf` with additional `lastOf` (which every will become an alias for next)
This commit is contained in:
parent
4cf412b93d
commit
e1a532500e
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@ export const signal = (func) => {
|
||||
};
|
||||
|
||||
export const isaw = signal((t) => 1 - (t % 1));
|
||||
export const isaw2 = isaw._toBipolar();
|
||||
export const isaw2 = isaw.toBipolar();
|
||||
|
||||
/**
|
||||
* A sawtooth signal between 0 and 1.
|
||||
@ -33,7 +33,7 @@ export const isaw2 = isaw._toBipolar();
|
||||
*
|
||||
*/
|
||||
export const saw = signal((t) => t % 1);
|
||||
export const saw2 = saw._toBipolar();
|
||||
export const saw2 = saw.toBipolar();
|
||||
|
||||
export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
||||
|
||||
@ -45,7 +45,7 @@ export const sine2 = signal((t) => Math.sin(Math.PI * 2 * t));
|
||||
* sine.segment(16).range(0,15).slow(2).scale('C minor').note()
|
||||
*
|
||||
*/
|
||||
export const sine = sine2._fromBipolar();
|
||||
export const sine = sine2.fromBipolar();
|
||||
|
||||
/**
|
||||
* A cosine signal between 0 and 1.
|
||||
@ -67,7 +67,7 @@ export const cosine2 = sine2._early(Fraction(1).div(4));
|
||||
*
|
||||
*/
|
||||
export const square = signal((t) => Math.floor((t * 2) % 2));
|
||||
export const square2 = square._toBipolar();
|
||||
export const square2 = square.toBipolar();
|
||||
|
||||
/**
|
||||
* A triangle signal between 0 and 1.
|
||||
@ -127,7 +127,7 @@ export const rand = signal(timeToRand);
|
||||
/**
|
||||
* A continuous pattern of random numbers, between -1 and 1
|
||||
*/
|
||||
export const rand2 = rand._toBipolar();
|
||||
export const rand2 = rand.toBipolar();
|
||||
|
||||
export const _brandBy = (p) => rand.fmap((x) => x < p);
|
||||
export const brandBy = (pPat) => reify(pPat).fmap(_brandBy).innerJoin();
|
||||
@ -201,7 +201,7 @@ Pattern.prototype.choose = function (...xs) {
|
||||
* @returns {Pattern}
|
||||
*/
|
||||
Pattern.prototype.choose2 = function (...xs) {
|
||||
return chooseWith(this._fromBipolar(), xs);
|
||||
return chooseWith(this.fromBipolar(), xs);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -259,7 +259,7 @@ export const perlinWith = (pat) => {
|
||||
export const perlin = perlinWith(time.fmap((v) => Number(v)));
|
||||
|
||||
Pattern.prototype._degradeByWith = function (withPat, x) {
|
||||
return this.fmap((a) => (_) => a).appLeft(withPat._filterValues((v) => v > x));
|
||||
return this.fmap((a) => (_) => a).appLeft(withPat.filterValues((v) => v > x));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -49,7 +49,7 @@ import { steady } from '../signal.mjs';
|
||||
|
||||
import controls from '../controls.mjs';
|
||||
|
||||
const { n } = controls;
|
||||
const { n, s } = controls;
|
||||
const st = (begin, end) => new State(ts(begin, end));
|
||||
const ts = (begin, end) => new TimeSpan(Fraction(begin), Fraction(end));
|
||||
const hap = (whole, part, value, context = {}) => new Hap(whole, part, value, context);
|
||||
@ -58,7 +58,7 @@ const third = Fraction(1, 3);
|
||||
const twothirds = Fraction(2, 3);
|
||||
|
||||
const sameFirst = (a, b) => {
|
||||
return expect(a._sortHapsByPart().firstCycle()).toStrictEqual(b._sortHapsByPart().firstCycle());
|
||||
return expect(a.sortHapsByPart().firstCycle()).toStrictEqual(b.sortHapsByPart().firstCycle());
|
||||
};
|
||||
|
||||
describe('TimeSpan', () => {
|
||||
@ -382,7 +382,7 @@ describe('Pattern', () => {
|
||||
);
|
||||
});
|
||||
it('copes with breaking up events across cycles', () => {
|
||||
expect(pure('a').slow(2)._fastGap(2)._setContext({}).query(st(0, 2))).toStrictEqual([
|
||||
expect(pure('a').slow(2)._fastGap(2).setContext({}).query(st(0, 2))).toStrictEqual([
|
||||
hap(ts(0, 1), ts(0, 0.5), 'a'),
|
||||
hap(ts(0.5, 1.5), ts(1, 1.5), 'a'),
|
||||
]);
|
||||
@ -446,8 +446,8 @@ describe('Pattern', () => {
|
||||
});
|
||||
describe('slow()', () => {
|
||||
it('Supports zero-length queries', () => {
|
||||
expect(steady('a').slow(1)._setContext({}).queryArc(0, 0)).toStrictEqual(
|
||||
steady('a')._setContext({}).queryArc(0, 0),
|
||||
expect(steady('a').slow(1).setContext({}).queryArc(0, 0)).toStrictEqual(
|
||||
steady('a').setContext({}).queryArc(0, 0),
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -465,7 +465,7 @@ describe('Pattern', () => {
|
||||
it('Filters true', () => {
|
||||
expect(
|
||||
pure(true)
|
||||
._filterValues((x) => x)
|
||||
.filterValues((x) => x)
|
||||
.firstCycle().length,
|
||||
).toBe(1);
|
||||
});
|
||||
@ -490,7 +490,7 @@ describe('Pattern', () => {
|
||||
pure(10)
|
||||
.when(slowcat(true, false), (x) => x.add(3))
|
||||
.fast(4)
|
||||
._sortHapsByPart()
|
||||
.sortHapsByPart()
|
||||
.firstCycle(),
|
||||
).toStrictEqual(fastcat(13, 10, 13, 10).firstCycle());
|
||||
});
|
||||
@ -577,26 +577,26 @@ describe('Pattern', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('every()', () => {
|
||||
describe('firstOf()', () => {
|
||||
it('Can apply a function every 3rd time', () => {
|
||||
expect(
|
||||
pure('a')
|
||||
.every(3, (x) => x._fast(2))
|
||||
.firstOf(3, (x) => x._fast(2))
|
||||
._fast(3)
|
||||
.firstCycle(),
|
||||
).toStrictEqual(sequence(sequence('a', 'a'), 'a', 'a').firstCycle());
|
||||
});
|
||||
it('works with currying', () => {
|
||||
expect(pure('a').every(3, fast(2))._fast(3).firstCycle()).toStrictEqual(
|
||||
expect(pure('a').firstOf(3, fast(2))._fast(3).firstCycle()).toStrictEqual(
|
||||
sequence(sequence('a', 'a'), 'a', 'a').firstCycle(),
|
||||
);
|
||||
expect(sequence(3, 4, 5).every(3, add(3)).fast(5).firstCycle()).toStrictEqual(
|
||||
expect(sequence(3, 4, 5).firstOf(3, add(3)).fast(5).firstCycle()).toStrictEqual(
|
||||
sequence(6, 7, 8, 3, 4, 5, 3, 4, 5, 6, 7, 8, 3, 4, 5).firstCycle(),
|
||||
);
|
||||
expect(sequence(3, 4, 5).every(2, sub(1)).fast(5).firstCycle()).toStrictEqual(
|
||||
expect(sequence(3, 4, 5).firstOf(2, sub(1)).fast(5).firstCycle()).toStrictEqual(
|
||||
sequence(2, 3, 4, 3, 4, 5, 2, 3, 4, 3, 4, 5, 2, 3, 4).firstCycle(),
|
||||
);
|
||||
expect(sequence(3, 4, 5).every(3, add(3)).every(2, sub(1)).fast(2).firstCycle()).toStrictEqual(
|
||||
expect(sequence(3, 4, 5).firstOf(3, add(3)).firstOf(2, sub(1)).fast(2).firstCycle()).toStrictEqual(
|
||||
sequence(5, 6, 7, 3, 4, 5).firstCycle(),
|
||||
);
|
||||
});
|
||||
@ -692,7 +692,7 @@ describe('Pattern', () => {
|
||||
it('Can set the hap context', () => {
|
||||
expect(
|
||||
pure('a')
|
||||
._setContext([
|
||||
.setContext([
|
||||
[
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
@ -713,13 +713,13 @@ describe('Pattern', () => {
|
||||
it('Can update the hap context', () => {
|
||||
expect(
|
||||
pure('a')
|
||||
._setContext([
|
||||
.setContext([
|
||||
[
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
],
|
||||
])
|
||||
._withContext((c) => [
|
||||
.withContext((c) => [
|
||||
...c,
|
||||
[
|
||||
[3, 4],
|
||||
@ -743,7 +743,7 @@ describe('Pattern', () => {
|
||||
});
|
||||
describe('apply', () => {
|
||||
it('Can apply a function', () => {
|
||||
expect(sequence('a', 'b')._apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
||||
expect(sequence('a', 'b').apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
||||
}),
|
||||
it('Can apply a pattern of functions', () => {
|
||||
expect(sequence('a', 'b').apply(fast(2)).firstCycle()).toStrictEqual(sequence('a', 'b').fast(2).firstCycle());
|
||||
@ -784,18 +784,18 @@ describe('Pattern', () => {
|
||||
});
|
||||
describe('jux', () => {
|
||||
it('Can juxtapose', () => {
|
||||
expect(pure({ a: 1 }).jux(fast(2))._sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
expect(pure({ a: 1 }).jux(fast(2)).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
stack(pure({ a: 1, pan: 0 }), pure({ a: 1, pan: 1 }).fast(2))
|
||||
._sortHapsByPart()
|
||||
.sortHapsByPart()
|
||||
.firstCycle(),
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('juxBy', () => {
|
||||
it('Can juxtapose by half', () => {
|
||||
expect(pure({ a: 1 }).juxBy(0.5, fast(2))._sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
expect(pure({ a: 1 }).juxBy(0.5, fast(2)).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
stack(pure({ a: 1, pan: 0.25 }), pure({ a: 1, pan: 0.75 }).fast(2))
|
||||
._sortHapsByPart()
|
||||
.sortHapsByPart()
|
||||
.firstCycle(),
|
||||
);
|
||||
});
|
||||
@ -805,7 +805,7 @@ describe('Pattern', () => {
|
||||
expect(
|
||||
sequence('a', ['a', 'a'])
|
||||
.fmap((a) => fastcat('b', 'c'))
|
||||
._squeezeJoin()
|
||||
.squeezeJoin()
|
||||
.firstCycle(),
|
||||
).toStrictEqual(
|
||||
sequence(
|
||||
@ -820,7 +820,7 @@ describe('Pattern', () => {
|
||||
it('Squeezes to the correct cycle', () => {
|
||||
expect(
|
||||
pure(time.struct(true))
|
||||
._squeezeJoin()
|
||||
.squeezeJoin()
|
||||
.queryArc(3, 4)
|
||||
.map((x) => x.value),
|
||||
).toStrictEqual([Fraction(3.5)]);
|
||||
@ -857,7 +857,7 @@ describe('Pattern', () => {
|
||||
);
|
||||
});
|
||||
it('Can chop(2,3)', () => {
|
||||
expect(pure({ sound: 'a' }).fast(2).chop(2, 3)._sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
expect(pure({ sound: 'a' }).fast(2).chop(2, 3).sortHapsByPart().firstCycle()).toStrictEqual(
|
||||
sequence(
|
||||
[
|
||||
{ sound: 'a', begin: 0, end: 0.5 },
|
||||
@ -869,7 +869,7 @@ describe('Pattern', () => {
|
||||
{ sound: 'a', begin: 2 / 3, end: 1 },
|
||||
],
|
||||
)
|
||||
._sortHapsByPart()
|
||||
.sortHapsByPart()
|
||||
.firstCycle(),
|
||||
);
|
||||
});
|
||||
@ -893,4 +893,11 @@ describe('Pattern', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('alignments', () => {
|
||||
it('Can squeeze arguments', () => {
|
||||
expect(sequence(1, 2).add.squeeze(4, 5).firstCycle()).toStrictEqual(
|
||||
sequence(5, 6, 6, 7).firstCycle()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,7 +13,7 @@ const { fastcat, evalScope } = strudel;
|
||||
|
||||
describe('evaluate', async () => {
|
||||
await evalScope({ mini }, strudel);
|
||||
const ev = async (code) => (await evaluate(code)).pattern._firstCycleValues;
|
||||
const ev = async (code) => (await evaluate(code)).pattern.firstCycleValues;
|
||||
it('Should evaluate strudel functions', async () => {
|
||||
expect(await ev('pure("c3")')).toEqual(['c3']);
|
||||
expect(await ev('cat("c3")')).toEqual(['c3']);
|
||||
|
||||
@ -9,8 +9,8 @@ import '@strudel.cycles/core/euclid.mjs';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe('mini', () => {
|
||||
const minV = (v) => mini(v)._firstCycleValues;
|
||||
const minS = (v) => mini(v)._showFirstCycle;
|
||||
const minV = (v) => mini(v).firstCycleValues;
|
||||
const minS = (v) => mini(v).showFirstCycle;
|
||||
it('supports single elements', () => {
|
||||
expect(minV('a')).toEqual(['a']);
|
||||
});
|
||||
|
||||
@ -12,6 +12,6 @@ import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('tonal', () => {
|
||||
it('Should run tonal functions ', () => {
|
||||
expect(pure('c3').scale('C major').scaleTranspose(1)._firstCycleValues).toEqual(['D3']);
|
||||
expect(pure('c3').scale('C major').scaleTranspose(1).firstCycleValues).toEqual(['D3']);
|
||||
});
|
||||
});
|
||||
|
||||
@ -75,7 +75,7 @@ function scaleOffset(scale, offset, note) {
|
||||
*/
|
||||
|
||||
Pattern.prototype._transpose = function (intervalOrSemitones) {
|
||||
return this._withHap((hap) => {
|
||||
return this.withHap((hap) => {
|
||||
const interval = !isNaN(Number(intervalOrSemitones))
|
||||
? Interval.fromSemitones(intervalOrSemitones /* as number */)
|
||||
: String(intervalOrSemitones);
|
||||
@ -111,7 +111,7 @@ Pattern.prototype._transpose = function (intervalOrSemitones) {
|
||||
*/
|
||||
|
||||
Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
|
||||
return this._withHap((hap) => {
|
||||
return this.withHap((hap) => {
|
||||
if (!hap.context.scale) {
|
||||
throw new Error('can only use scaleTranspose after .scale');
|
||||
}
|
||||
@ -142,7 +142,7 @@ Pattern.prototype._scaleTranspose = function (offset /* : number | string */) {
|
||||
*/
|
||||
|
||||
Pattern.prototype._scale = function (scale /* : string */) {
|
||||
return this._withHap((hap) => {
|
||||
return this.withHap((hap) => {
|
||||
let note = hap.value;
|
||||
const asNumber = Number(note);
|
||||
if (!isNaN(asNumber)) {
|
||||
|
||||
@ -51,7 +51,7 @@ Pattern.prototype.voicings = function (range) {
|
||||
}
|
||||
return this.fmapNested((event) => {
|
||||
lastVoicing = getVoicing(event.value, lastVoicing, range);
|
||||
return stack(...lastVoicing)._withContext(() => ({
|
||||
return stack(...lastVoicing).withContext(() => ({
|
||||
locations: event.context.locations || [],
|
||||
}));
|
||||
});
|
||||
|
||||
@ -13,6 +13,6 @@ describe('tone', () => {
|
||||
// const s = synth().chain(out()); // TODO: mock audio context?
|
||||
// assert.deepStrictEqual(s, new Tone.Synth().chain(out()));
|
||||
const s = {};
|
||||
expect(pure('c3').tone(s)._firstCycleValues).toEqual(['c3']);
|
||||
expect(pure('c3').tone(s).firstCycleValues).toEqual(['c3']);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,5 +1,22 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`runs examples > example "_apply" example index 0 1`] = `
|
||||
[
|
||||
"0/1 -> 1/1: {\\"note\\":\\"C3\\"}",
|
||||
"0/1 -> 1/1: {\\"note\\":\\"Eb3\\"}",
|
||||
"0/1 -> 1/1: {\\"note\\":\\"G3\\"}",
|
||||
"1/1 -> 2/1: {\\"note\\":\\"Eb3\\"}",
|
||||
"1/1 -> 2/1: {\\"note\\":\\"G3\\"}",
|
||||
"1/1 -> 2/1: {\\"note\\":\\"Bb3\\"}",
|
||||
"2/1 -> 3/1: {\\"note\\":\\"G3\\"}",
|
||||
"2/1 -> 3/1: {\\"note\\":\\"Bb3\\"}",
|
||||
"2/1 -> 3/1: {\\"note\\":\\"D4\\"}",
|
||||
"3/1 -> 4/1: {\\"note\\":\\"C3\\"}",
|
||||
"3/1 -> 4/1: {\\"note\\":\\"Eb3\\"}",
|
||||
"3/1 -> 4/1: {\\"note\\":\\"G3\\"}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "accelerate" example index 0 1`] = `
|
||||
[
|
||||
"0/1 -> 2/1: {\\"s\\":\\"sax\\",\\"accelerate\\":0}",
|
||||
@ -1593,6 +1610,27 @@ exports[`runs examples > example "fastcat" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "firstOf" example index 0 1`] = `
|
||||
[
|
||||
"3/4 -> 1/1: {\\"note\\":\\"c3\\"}",
|
||||
"1/2 -> 3/4: {\\"note\\":\\"d3\\"}",
|
||||
"1/4 -> 1/2: {\\"note\\":\\"e3\\"}",
|
||||
"0/1 -> 1/4: {\\"note\\":\\"g3\\"}",
|
||||
"1/1 -> 5/4: {\\"note\\":\\"c3\\"}",
|
||||
"5/4 -> 3/2: {\\"note\\":\\"d3\\"}",
|
||||
"3/2 -> 7/4: {\\"note\\":\\"e3\\"}",
|
||||
"7/4 -> 2/1: {\\"note\\":\\"g3\\"}",
|
||||
"2/1 -> 9/4: {\\"note\\":\\"c3\\"}",
|
||||
"9/4 -> 5/2: {\\"note\\":\\"d3\\"}",
|
||||
"5/2 -> 11/4: {\\"note\\":\\"e3\\"}",
|
||||
"11/4 -> 3/1: {\\"note\\":\\"g3\\"}",
|
||||
"3/1 -> 13/4: {\\"note\\":\\"c3\\"}",
|
||||
"13/4 -> 7/2: {\\"note\\":\\"d3\\"}",
|
||||
"7/2 -> 15/4: {\\"note\\":\\"e3\\"}",
|
||||
"15/4 -> 4/1: {\\"note\\":\\"g3\\"}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "freq" example index 0 1`] = `
|
||||
[
|
||||
"0/1 -> 1/4: {\\"freq\\":220,\\"s\\":\\"superzow\\"}",
|
||||
@ -1793,6 +1831,27 @@ exports[`runs examples > example "iterBack" example index 0 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "lastOf" example index 0 1`] = `
|
||||
[
|
||||
"0/1 -> 1/4: {\\"note\\":\\"c3\\"}",
|
||||
"1/4 -> 1/2: {\\"note\\":\\"d3\\"}",
|
||||
"1/2 -> 3/4: {\\"note\\":\\"e3\\"}",
|
||||
"3/4 -> 1/1: {\\"note\\":\\"g3\\"}",
|
||||
"1/1 -> 5/4: {\\"note\\":\\"c3\\"}",
|
||||
"5/4 -> 3/2: {\\"note\\":\\"d3\\"}",
|
||||
"3/2 -> 7/4: {\\"note\\":\\"e3\\"}",
|
||||
"7/4 -> 2/1: {\\"note\\":\\"g3\\"}",
|
||||
"2/1 -> 9/4: {\\"note\\":\\"c3\\"}",
|
||||
"9/4 -> 5/2: {\\"note\\":\\"d3\\"}",
|
||||
"5/2 -> 11/4: {\\"note\\":\\"e3\\"}",
|
||||
"11/4 -> 3/1: {\\"note\\":\\"g3\\"}",
|
||||
"15/4 -> 4/1: {\\"note\\":\\"c3\\"}",
|
||||
"7/2 -> 15/4: {\\"note\\":\\"d3\\"}",
|
||||
"13/4 -> 7/2: {\\"note\\":\\"e3\\"}",
|
||||
"3/1 -> 13/4: {\\"note\\":\\"g3\\"}",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`runs examples > example "late" example index 0 1`] = `
|
||||
[
|
||||
"0/1 -> 1/2: {\\"s\\":\\"bd\\"}",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user