diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 0edc4dfcf..aff33a5f6 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, sequence } from './pattern.mjs';
+import pattern from './pattern.mjs';
+const { Pattern, sequence } = pattern;
const controls = {};
const generic_params = [
diff --git a/packages/core/draw.mjs b/packages/core/draw.mjs
index 9ef34e3ab..f63acdf3f 100644
--- a/packages/core/draw.mjs
+++ b/packages/core/draw.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, getTime } from './index.mjs';
+import { pattern, getTime } from './index.mjs';
+const { Pattern } = pattern;
export const getDrawContext = (id = 'test-canvas') => {
let canvas = document.querySelector('#' + id);
diff --git a/packages/core/euclid.mjs b/packages/core/euclid.mjs
index 45a59783e..5d7d6789f 100644
--- a/packages/core/euclid.mjs
+++ b/packages/core/euclid.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, timeCat } from './pattern.mjs';
+import pattern from './pattern.mjs';
+const { Pattern, timeCat } = pattern;
import bjork from 'bjork';
import { rotate } from './util.mjs';
import Fraction from './fraction.mjs';
diff --git a/packages/core/evaluate.mjs b/packages/core/evaluate.mjs
index 35c47e422..f2879a55d 100644
--- a/packages/core/evaluate.mjs
+++ b/packages/core/evaluate.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { isPattern, Pattern } from './index.mjs';
+import { pattern } from './index.mjs';
+const { isPattern, Pattern } = pattern;
let scoped = false;
export const evalScope = async (...args) => {
diff --git a/packages/core/index.mjs b/packages/core/index.mjs
index b9fd70618..0a6c32a82 100644
--- a/packages/core/index.mjs
+++ b/packages/core/index.mjs
@@ -4,13 +4,13 @@ Copyright (C) 2022 Strudel contributors - see .
*/
+import pattern from './pattern.mjs';
import controls from './controls.mjs';
export * from './euclid.mjs';
import Fraction from './fraction.mjs';
import { logger } from './logger.mjs';
-export { Fraction, controls };
+export { Fraction, controls, pattern };
export * from './hap.mjs';
-export * from './pattern.mjs';
export * from './signal.mjs';
export * from './state.mjs';
export * from './timespan.mjs';
diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs
index c7a80b59b..abd89fd56 100644
--- a/packages/core/pattern.mjs
+++ b/packages/core/pattern.mjs
@@ -14,14 +14,18 @@ import { compose, removeUndefineds, flatten, id, listRange, curry, mod, numeralA
import drawLine from './drawLine.mjs';
import { logger } from './logger.mjs';
+// monster object collecting everything to be exported
+const pattern = {};
+
let stringParser;
+
// parser is expected to turn a string into a pattern
// if set, the reify function will parse all strings with it
// intended to use with mini to automatically interpret all strings as mini notation
-export const setStringParser = (parser) => (stringParser = parser);
+pattern['setStringParser'] = (parser) => (stringParser = parser);
/** @class Class representing a pattern. */
-export class Pattern {
+class Pattern {
_Pattern = true; // this property is used to detect if a pattern that fails instanceof Pattern is an instance of another Pattern
/**
* Create a pattern. As an end user, you will most likely not create a Pattern directly.
@@ -1366,6 +1370,8 @@ export class Pattern {
}
+pattern['Pattern'] = Pattern;
+
// TODO - adopt value.mjs fully..
function _composeOp(a, b, func) {
function _nonFunctionObject(x) {
@@ -1550,10 +1556,6 @@ Pattern.prototype.patternified = [
'velocity',
];
-// aliases
-export const polyrhythm = stack;
-export const pr = stack;
-
// methods that create patterns, which are added to patternified Pattern methods
Pattern.prototype.factories = {
pure,
@@ -1574,7 +1576,8 @@ Pattern.prototype.factories = {
// Elemental patterns
// Nothing
-export const silence = new Pattern((_) => []);
+const silence = new Pattern((_) => []);
+pattern['silence'] = silence;
/** A discrete value that repeats once per cycle.
*
@@ -1582,14 +1585,15 @@ export const silence = new Pattern((_) => []);
* @example
* pure('e4') // "e4"
*/
-export function pure(value) {
+function pure(value) {
function query(state) {
return state.span.spanCycles.map((subspan) => new Hap(Fraction(subspan.begin).wholeCycle(), subspan, value));
}
return new Pattern(query);
}
+pattern['pure'] = pure;
-export function isPattern(thing) {
+function isPattern(thing) {
// thing?.constructor?.name !== 'Pattern' // <- this will fail when code is mangled
const is = thing instanceof Pattern || thing?._Pattern;
if (!thing instanceof Pattern) {
@@ -1601,8 +1605,9 @@ export function isPattern(thing) {
}
return is;
}
+pattern['isPattern'] = isPattern;
-export function reify(thing) {
+function reify(thing) {
// Turns something into a pattern, unless it's already a pattern
if (isPattern(thing)) {
return thing;
@@ -1612,6 +1617,7 @@ export function reify(thing) {
}
return pure(thing);
}
+pattern['reify'] = reify;
/** The given items are played at the same time at the same length.
*
@@ -1619,12 +1625,20 @@ export function reify(thing) {
* @example
* stack(g3, b3, [e4, d4]).note() // "g3,b3,[e4,d4]".note()
*/
-export function stack(...pats) {
+function stack(...pats) {
// Array test here is to avoid infinite recursions..
pats = pats.map((pat) => (Array.isArray(pat) ? sequence(...pat) : reify(pat)));
const query = (state) => flatten(pats.map((pat) => pat.query(state)));
return new Pattern(query);
}
+pattern['stack'] = stack;
+function polyrhythm(...pats) {
+ return stack(...pats);
+}
+function pr(...pats) {
+ return stack(...pats);
+}
+pattern['pr'] = pattern['polyrhythm'] = pattern['stack'];
/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:
*
@@ -1635,7 +1649,7 @@ export function stack(...pats) {
* slowcat(e5, b4, [d5, c5])
*
*/
-export function slowcat(...pats) {
+function slowcat(...pats) {
// Array test here is to avoid infinite recursions..
pats = pats.map((pat) => (Array.isArray(pat) ? sequence(...pat) : reify(pat)));
@@ -1655,12 +1669,13 @@ export function slowcat(...pats) {
};
return new Pattern(query).splitQueries();
}
+pattern['slowcat'] = slowcat;
/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.
* @param {...any} items - The items to concatenate
* @return {Pattern}
*/
-export function slowcatPrime(...pats) {
+function slowcatPrime(...pats) {
pats = pats.map(reify);
const query = function (state) {
const pat_n = Math.floor(state.span.begin) % pats.length;
@@ -1669,6 +1684,7 @@ export function slowcatPrime(...pats) {
};
return new Pattern(query).splitQueries();
}
+pattern['slowcatPrime'] = slowcatPrime;
/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle
*
@@ -1681,9 +1697,10 @@ export function slowcatPrime(...pats) {
* // sequence(e5, b4, [d5, c5])
* // seq(e5, b4, [d5, c5])
*/
-export function fastcat(...pats) {
+function fastcat(...pats) {
return slowcat(...pats)._fast(pats.length);
}
+pattern['fastcat'] = fastcat;
/** The given items are con**cat**enated, where each one takes one cycle. Synonym: slowcat
*
@@ -1693,16 +1710,17 @@ export function fastcat(...pats) {
* cat(e5, b4, [d5, c5]).note() // "".note()
*
*/
-export function cat(...pats) {
+function cat(...pats) {
return slowcat(...pats);
}
+pattern['cat'] = cat;
/** Like {@link seq}, but each step has a length, relative to the whole.
* @return {Pattern}
* @example
* timeCat([3,e3],[1, g3]).note() // "e3@3 g3".note()
*/
-export function timeCat(...timepats) {
+function timeCat(...timepats) {
const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0));
let begin = Fraction(0);
const pats = [];
@@ -1713,20 +1731,23 @@ export function timeCat(...timepats) {
}
return stack(...pats);
}
+pattern['timeCat'] = timeCat;
/** See {@link fastcat} */
-export function sequence(...pats) {
+function sequence(...pats) {
return fastcat(...pats);
}
+pattern['sequence'] = sequence;
/** Like **cat**, but the items are crammed into one cycle. Synonyms: fastcat, sequence
* @example
* seq(e5, b4, [d5, c5]).note() // "e5 b4 [d5 c5]".note()
*
*/
-export function seq(...pats) {
+function seq(...pats) {
return fastcat(...pats);
}
+pattern['seq'] = seq;
function _sequenceCount(x) {
if (Array.isArray(x)) {
@@ -1741,7 +1762,7 @@ function _sequenceCount(x) {
return [reify(x), 1];
}
-export function polymeterSteps(steps, ...args) {
+function polymeterSteps(steps, ...args) {
const seqs = args.map((a) => _sequenceCount(a));
if (seqs.length == 0) {
return silence;
@@ -1762,57 +1783,49 @@ export function polymeterSteps(steps, ...args) {
}
return stack(...pats);
}
+pattern['polymeterSteps'] = polymeterSteps;
-export function polymeter(...args) {
+function polymeter(...args) {
return polymeterSteps(0, ...args);
}
+pattern['polymeter'] = polymeter;
-// alias
-export function pm(...args) {
- polymeter(...args);
+function pm(...args) {
+ return polymeter(...args);
+}
+pattern['pm'] = polymeter;
+
+// arity 1
+for (const func of ['inv', 'invert', 'rev']) {
+ pattern[func] = (pat) => pat[func]();
}
-export const add = curry((a, pat) => pat.add(a));
-export const chop = curry((a, pat) => pat.chop(a));
-export const chunk = curry((a, pat) => pat.chunk(a));
-export const chunkBack = curry((a, pat) => pat.chunkBack(a));
-export const div = curry((a, pat) => pat.div(a));
-export const early = curry((a, pat) => pat.early(a));
-export const echo = curry((a, b, c, pat) => pat.echo(a, b, c));
-export const every = curry((i, f, pat) => pat.every(i, f));
-export const fast = curry((a, pat) => pat.fast(a));
-export const inv = (pat) => pat.inv();
-export const invert = (pat) => pat.invert();
-export const iter = curry((a, pat) => pat.iter(a));
-export const iterBack = curry((a, pat) => pat.iterBack(a));
-export const jux = curry((f, pat) => pat.jux(f));
-export const juxBy = curry((by, f, pat) => pat.juxBy(by, f));
-export const late = curry((a, pat) => pat.late(a));
-export const linger = curry((a, pat) => pat.linger(a));
-export const mask = curry((a, pat) => pat.mask(a));
-export const mul = curry((a, pat) => pat.mul(a));
-export const off = curry((t, f, pat) => pat.off(t, f));
-export const ply = curry((a, pat) => pat.ply(a));
-export const range = curry((a, b, pat) => pat.range(a, b));
-export const rangex = curry((a, b, pat) => pat.rangex(a, b));
-export const range2 = curry((a, b, pat) => pat.range2(a, b));
-export const rev = (pat) => pat.rev();
-export const slow = curry((a, pat) => pat.slow(a));
-export const struct = curry((a, pat) => pat.struct(a));
-export const sub = curry((a, pat) => pat.sub(a));
-export const superimpose = curry((array, pat) => pat.superimpose(...array));
-export const set = curry((a, pat) => pat.set(a));
-export const when = curry((binary, f, pat) => pat.when(binary, f));
+// arity 2
+for (const func of ['add','chop','chunk','chunkBack','div','early','fast','iter','iterBack','jux','late','linger',
+ 'mask','mul','ply','slow','struct','sub','superimpose','set']
+ ) {
+ pattern[func] = curry((a, pat) => pat[func](a));
+}
+// arity 3
+for (const func of ['every','juxBy','off','range','rangex','range2','when']) {
+ pattern[func] = curry((a, b, pat) => pat[func](a,b));
+}
+
+// arity 4
+for (const func of ['echo']) {
+ pattern[func] = curry((a, b, c, pat) => pat[func](a,b,c));
+}
+
// problem: curried functions with spread arguments must have pat at the beginning
// with this, we cannot keep the pattern open at the end.. solution for now: use array to keep using pat as last arg
// these are the core composable functions. they are extended with Pattern.prototype.define below
-Pattern.prototype.composable = { fast, slow, early, late, superimpose };
+Pattern.prototype.composable = {fast: pattern.fast, slow: pattern.slow, early: pattern.early, late: pattern.late, superimpose: pattern.superimpose };
// adds Pattern.prototype.composable to given function as child functions
// then you can do transpose(2).late(0.2) instead of x => x.transpose(2).late(0.2)
-export function makeComposable(func) {
+function makeComposable(func) {
Object.entries(Pattern.prototype.composable).forEach(([functionName, composable]) => {
// compose with dot
func[functionName] = (...args) => {
@@ -1825,25 +1838,31 @@ export function makeComposable(func) {
});
return func;
}
+pattern['makeComposable'] = makeComposable;
-export const patternify2 = (f) => (pata, patb, pat) =>
+const patternify2 = (f) => (pata, patb, pat) =>
pata
.fmap((a) => (b) => f.call(pat, a, b))
.appLeft(patb)
.innerJoin();
-export const patternify3 = (f) => (pata, patb, patc, pat) =>
+pattern['patternify2'] = patternify2;
+
+const patternify3 = (f) => (pata, patb, patc, pat) =>
pata
.fmap((a) => (b) => (c) => f.call(pat, a, b, c))
.appLeft(patb)
.appLeft(patc)
.innerJoin();
-export const patternify4 = (f) => (pata, patb, patc, patd, pat) =>
+pattern['patternify3'] = patternify3;
+
+const patternify4 = (f) => (pata, patb, patc, patd, pat) =>
pata
.fmap((a) => (b) => (c) => (d) => f.call(pat, a, b, c, d))
.appLeft(patb)
.appLeft(patc)
.appLeft(patd)
.innerJoin();
+pattern['patternify4'] = patternify4;
Pattern.prototype.echo = function (...args) {
args = args.map(reify);
@@ -1974,3 +1993,7 @@ Pattern.prototype.define = (name, func, options = {}) => {
// Pattern.prototype.define('early', (a, pat) => pat.early(a), { patternified: true, composable: true });
Pattern.prototype.define('hush', (pat) => pat.hush(), { patternified: false, composable: true });
Pattern.prototype.define('bypass', (pat) => pat.bypass(on), { patternified: true, composable: true });
+
+
+export default pattern;
+
diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs
index f9c198e94..c383dfe2c 100644
--- a/packages/core/pianoroll.mjs
+++ b/packages/core/pianoroll.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern } from './index.mjs';
+import { pattern } from './index.mjs';
+const { Pattern } = pattern;
const scale = (normalized, min, max) => normalized * (max - min) + min;
const getValue = (e) => {
diff --git a/packages/core/signal.mjs b/packages/core/signal.mjs
index d92d51fe8..3f2da134d 100644
--- a/packages/core/signal.mjs
+++ b/packages/core/signal.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import { Hap } from './hap.mjs';
-import { Pattern, fastcat, reify, silence, stack, isPattern } from './pattern.mjs';
+import pattern from './pattern.mjs';
+const { Pattern, fastcat, reify, silence, stack, isPattern } = pattern;
import Fraction from './fraction.mjs';
import { id } from './util.mjs';
diff --git a/packages/core/speak.mjs b/packages/core/speak.mjs
index 2e9ba80ac..96c8f8a78 100644
--- a/packages/core/speak.mjs
+++ b/packages/core/speak.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, patternify2 } from './index.mjs';
+import { pattern } from './index.mjs';
+const {Pattern, patternify2} = pattern;
let synth;
try {
diff --git a/packages/core/test/drawLine.test.mjs b/packages/core/test/drawLine.test.mjs
index 84359a7cf..5f2a968dc 100644
--- a/packages/core/test/drawLine.test.mjs
+++ b/packages/core/test/drawLine.test.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { fastcat, stack, slowcat, silence, pure } from '../pattern.mjs';
+import pattern from '../pattern.mjs';
+const { fastcat, stack, slowcat, silence, pure } = pattern;
import { describe, it, expect } from 'vitest';
import drawLine from '../drawLine.mjs';
diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs
index 72365d131..036053bc2 100644
--- a/packages/core/test/pattern.test.mjs
+++ b/packages/core/test/pattern.test.mjs
@@ -8,10 +8,24 @@ import Fraction from 'fraction.js';
import { describe, it, expect } from 'vitest';
-import {
- TimeSpan,
- Hap,
- State,
+import { pattern,
+ TimeSpan,
+ Hap,
+ State,
+ saw,
+ saw2,
+ isaw,
+ isaw2,
+ sine,
+ sine2,
+ square,
+ square2,
+ tri,
+ tri2,
+ time,
+ } from '../index.mjs';
+
+const {
Pattern,
pure,
stack,
@@ -29,21 +43,10 @@ import {
sub,
mul,
div,
- saw,
- saw2,
- isaw,
- isaw2,
- sine,
- sine2,
- square,
- square2,
- tri,
- tri2,
id,
ply,
rev,
- time,
-} from '../index.mjs';
+} = pattern;
import { steady } from '../signal.mjs';
diff --git a/packages/core/test/util.test.mjs b/packages/core/test/util.test.mjs
index 303a3645a..4cef2d4b8 100644
--- a/packages/core/test/util.test.mjs
+++ b/packages/core/test/util.test.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { pure } from '../pattern.mjs';
+import pattern from '../pattern.mjs';
+const { pure } = pattern;
import {
isNote,
tokenizeNote,
diff --git a/packages/eval/shapeshifter.mjs b/packages/eval/shapeshifter.mjs
index b8ffffd3f..b26841def 100644
--- a/packages/eval/shapeshifter.mjs
+++ b/packages/eval/shapeshifter.mjs
@@ -23,7 +23,7 @@ const codegen = shiftCodegen.default || shiftCodegen; // parcel module resolutio
import * as strudel from '@strudel.cycles/core';
-const { Pattern } = strudel;
+const { Pattern } = strudel.pattern;
const isNote = (name) => /^[a-gC-G][bs]?[0-9]$/.test(name);
diff --git a/packages/eval/test/evaluate.test.mjs b/packages/eval/test/evaluate.test.mjs
index 674c581bd..b85bbd0cc 100644
--- a/packages/eval/test/evaluate.test.mjs
+++ b/packages/eval/test/evaluate.test.mjs
@@ -9,10 +9,11 @@ import { expect, describe, it } from 'vitest';
import { evaluate } from '../evaluate.mjs';
import { mini } from '@strudel.cycles/mini';
import * as strudel from '@strudel.cycles/core';
-const { fastcat, evalScope } = strudel;
+const { pattern, evalScope } = strudel;
+const { fastcat } = pattern;
describe('evaluate', async () => {
- await evalScope({ mini }, strudel);
+ await evalScope({ mini }, strudel, pattern);
const ev = async (code) => (await evaluate(code)).pattern.firstCycleValues;
it('Should evaluate strudel functions', async () => {
expect(await ev('pure("c3")')).toEqual(['c3']);
diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs
index c59757fb8..10ece6416 100644
--- a/packages/midi/midi.mjs
+++ b/packages/midi/midi.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import * as _WebMidi from 'webmidi';
-import { Pattern, isPattern, isNote, getPlayableNoteValue, logger } from '@strudel.cycles/core';
+import { pattern, logger } from '@strudel.cycles/core';
+const { Pattern, isPattern, isNote, getPlayableNoteValue } = pattern;
import { getAudioContext } from '@strudel.cycles/webaudio';
// if you use WebMidi from outside of this package, make sure to import that instance:
diff --git a/packages/mini/mini.mjs b/packages/mini/mini.mjs
index 82ed4b86a..90a1cec1c 100644
--- a/packages/mini/mini.mjs
+++ b/packages/mini/mini.mjs
@@ -5,10 +5,10 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import * as krill from './krill-parser.js';
-import * as strudel from '@strudel.cycles/core';
+import {pattern, rand, chooseInWith, Fraction} from '@strudel.cycles/core';
// import { addMiniLocations } from '@strudel.cycles/eval/shapeshifter.mjs';
-const { pure, Pattern, Fraction, stack, slowcat, sequence, timeCat, silence, reify } = strudel;
+const { pure, Pattern, stack, slowcat, sequence, timeCat, silence, reify } = pattern;
var _seedState = 0;
const randOffset = 0.0002;
@@ -30,7 +30,7 @@ const applyOptions = (parent) => (pat, i) => {
return pat.euclid(operator.arguments_.pulse, operator.arguments_.step, operator.arguments_.rotation);
case 'degradeBy':
return reify(pat)._degradeByWith(
- strudel.rand.early(randOffset * _nextSeed()).segment(1),
+ rand.early(randOffset * _nextSeed()).segment(1),
operator.arguments_.amount,
);
// TODO: case 'fixed-step': "%"
@@ -95,7 +95,7 @@ export function patternifyAST(ast) {
return stack(...children);
}
if (alignment === 'r') {
- return strudel.chooseInWith(strudel.rand.early(randOffset * _nextSeed()).segment(1), children);
+ return chooseInWith(rand.early(randOffset * _nextSeed()).segment(1), children);
}
const weightedChildren = ast.source_.some((child) => !!child.options_?.weight);
if (!weightedChildren && alignment === 't') {
diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs
index 15909203e..a9a28e52b 100644
--- a/packages/osc/osc.mjs
+++ b/packages/osc/osc.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import OSC from 'osc-js';
-import { logger, parseNumeral, Pattern } from '@strudel.cycles/core';
+import { logger, parseNumeral, pattern } from '@strudel.cycles/core';
+const { Pattern } = pattern;
let connection; // Promise
function connect() {
diff --git a/packages/serial/serial.mjs b/packages/serial/serial.mjs
index 4452195dd..8d7785bcd 100644
--- a/packages/serial/serial.mjs
+++ b/packages/serial/serial.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, isPattern } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { Pattern, isPattern } = pattern;
var serialWriter;
var choosing = false;
diff --git a/packages/soundfonts/sfumato.mjs b/packages/soundfonts/sfumato.mjs
index 1cca2ffe5..d9770b1e8 100644
--- a/packages/soundfonts/sfumato.mjs
+++ b/packages/soundfonts/sfumato.mjs
@@ -1,4 +1,6 @@
-import { Pattern } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { Pattern } = pattern;
+
import { loadSoundfont as _loadSoundfont, startPresetNote } from 'sfumato';
Pattern.prototype.soundfont = function (sf, n = 0) {
diff --git a/packages/tonal/test/tonal.test.mjs b/packages/tonal/test/tonal.test.mjs
index f8a999571..cb293cf39 100644
--- a/packages/tonal/test/tonal.test.mjs
+++ b/packages/tonal/test/tonal.test.mjs
@@ -7,7 +7,8 @@ This program is free software: you can redistribute it and/or modify it under th
// import { strict as assert } from 'assert';
import '../tonal.mjs'; // need to import this to add prototypes
-import { pure } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { pure } = pattern;
import { describe, it, expect } from 'vitest';
describe('tonal', () => {
diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs
index 4d8e0d821..973eeb437 100644
--- a/packages/tonal/tonal.mjs
+++ b/packages/tonal/tonal.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import { Note, Interval, Scale } from '@tonaljs/tonal';
-import { Pattern, mod } from '@strudel.cycles/core';
+import { pattern, mod } from '@strudel.cycles/core';
+const { Pattern } = pattern;
// transpose note inside scale by offset steps
// function scaleOffset(scale: string, offset: number, note: string) {
diff --git a/packages/tonal/voicings.mjs b/packages/tonal/voicings.mjs
index 70a2f0e13..62d83457f 100644
--- a/packages/tonal/voicings.mjs
+++ b/packages/tonal/voicings.mjs
@@ -4,7 +4,9 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern as _Pattern, stack, Hap, reify } from '@strudel.cycles/core';
+import { pattern, Hap } from '@strudel.cycles/core';
+const { Pattern, stack, reify } = pattern
+
import _voicings from 'chord-voicings';
const { dictionaryVoicing, minTopNoteDiff, lefthand } = _voicings.default || _voicings; // parcel module resolution fuckup
@@ -17,7 +19,7 @@ const getVoicing = (chord, lastVoicing, range = ['F3', 'A4']) =>
lastVoicing,
});
-const Pattern = _Pattern;
+// const Pattern = _Pattern;
Pattern.prototype.fmapNested = function (func) {
return new Pattern((span) =>
diff --git a/packages/tone/test/tone.test.mjs b/packages/tone/test/tone.test.mjs
index 42feb676b..586b11931 100644
--- a/packages/tone/test/tone.test.mjs
+++ b/packages/tone/test/tone.test.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import '../tone.mjs';
-import { pure } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { pure } = pattern;
import { describe, it, expect } from 'vitest';
describe('tone', () => {
diff --git a/packages/tone/tone.mjs b/packages/tone/tone.mjs
index b5ea4b9ef..17f029fb6 100644
--- a/packages/tone/tone.mjs
+++ b/packages/tone/tone.mjs
@@ -4,7 +4,9 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { Pattern } = pattern;
+
import * as _Tone from 'tone';
// import Tone from here, to make sure to get the same AudioContext
diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs
index 52650d650..561ee9980 100644
--- a/packages/webaudio/webaudio.mjs
+++ b/packages/webaudio/webaudio.mjs
@@ -10,7 +10,7 @@ import { fromMidi, logger, toMidi } from '@strudel.cycles/core';
import './feedbackdelay.mjs';
import './reverb.mjs';
import { getSampleBufferSource } from './sampler.mjs';
-const { Pattern } = strudel;
+const { Pattern } = strudel.pattern;
import './vowel.mjs';
import workletsUrl from './worklets.mjs?url';
diff --git a/packages/xen/tune.mjs b/packages/xen/tune.mjs
index 5685e1a70..1429edfcc 100644
--- a/packages/xen/tune.mjs
+++ b/packages/xen/tune.mjs
@@ -5,7 +5,8 @@ This program is free software: you can redistribute it and/or modify it under th
*/
import Tune from './tunejs.js';
-import { Pattern } from '@strudel.cycles/core';
+import { pattern } from '@strudel.cycles/core';
+const { Pattern } = pattern;
Pattern.prototype._tune = function (scale, tonic = 220) {
const tune = new Tune();
diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs
index ff5a13ebc..63e1ee44f 100644
--- a/packages/xen/xen.mjs
+++ b/packages/xen/xen.mjs
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { Pattern, mod } from '@strudel.cycles/core';
+import { pattern, mod } from '@strudel.cycles/core';
+const { Pattern } = pattern;
export function edo(name) {
if (!/^[1-9]+[0-9]*edo$/.test(name)) {
diff --git a/repl/src/App.jsx b/repl/src/App.jsx
index ef2346c2e..0886bd115 100644
--- a/repl/src/App.jsx
+++ b/repl/src/App.jsx
@@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { cleanupDraw, cleanupUi, controls, evalScope, logger } from '@strudel.cycles/core';
+import { cleanupDraw, cleanupUi, controls, evalScope, logger, pattern } from '@strudel.cycles/core';
import { CodeMirror, cx, flash, useHighlighting, useStrudel } from '@strudel.cycles/react';
import {
getAudioContext,
@@ -47,6 +47,7 @@ const modules = [
evalScope(
// Tone,
controls, // sadly, this cannot be exported from core direclty
+ pattern,
{ WebDirt },
...modules,
);
diff --git a/repl/src/prebake.mjs b/repl/src/prebake.mjs
index 97443dcf2..75b490a33 100644
--- a/repl/src/prebake.mjs
+++ b/repl/src/prebake.mjs
@@ -1,4 +1,5 @@
-import { Pattern, toMidi } from '@strudel.cycles/core';
+import { pattern, toMidi } from '@strudel.cycles/core';
+const { Pattern } = pattern;
import { samples } from '@strudel.cycles/webaudio';
export async function prebake({ isMock = false, baseDir = '.' } = {}) {
diff --git a/repl/src/runtime.mjs b/repl/src/runtime.mjs
index 8945f1a81..d95c8f995 100644
--- a/repl/src/runtime.mjs
+++ b/repl/src/runtime.mjs
@@ -7,6 +7,7 @@
import { evaluate } from '@strudel.cycles/transpiler';
import { evalScope } from '@strudel.cycles/core';
import * as strudel from '@strudel.cycles/core';
+const { Pattern } = strudel.pattern;
import * as webaudio from '@strudel.cycles/webaudio';
import controls from '@strudel.cycles/core/controls.mjs';
// import gist from '@strudel.cycles/core/gist.js';
@@ -85,48 +86,48 @@ const toneHelpersMocked = {
highpass: mockNode,
};
-strudel.Pattern.prototype.osc = function () {
+Pattern.prototype.osc = function () {
return this;
};
-strudel.Pattern.prototype.tone = function () {
+Pattern.prototype.tone = function () {
return this;
};
-strudel.Pattern.prototype.webdirt = function () {
+Pattern.prototype.webdirt = function () {
return this;
};
// draw mock
-strudel.Pattern.prototype.pianoroll = function () {
+Pattern.prototype.pianoroll = function () {
return this;
};
// speak mock
-strudel.Pattern.prototype.speak = function () {
+Pattern.prototype.speak = function () {
return this;
};
// webaudio mock
-strudel.Pattern.prototype.wave = function () {
+Pattern.prototype.wave = function () {
return this;
};
-strudel.Pattern.prototype.filter = function () {
+Pattern.prototype.filter = function () {
return this;
};
-strudel.Pattern.prototype.adsr = function () {
+Pattern.prototype.adsr = function () {
return this;
};
-strudel.Pattern.prototype.out = function () {
+Pattern.prototype.out = function () {
return this;
};
-strudel.Pattern.prototype.soundfont = function () {
+Pattern.prototype.soundfont = function () {
return this;
};
// tune mock
-strudel.Pattern.prototype.tune = function () {
+Pattern.prototype.tune = function () {
return this;
};
-strudel.Pattern.prototype.midi = function () {
+Pattern.prototype.midi = function () {
return this;
};
@@ -156,7 +157,8 @@ const loadSoundfont = () => {};
evalScope(
// Tone,
strudel,
- strudel.Pattern.prototype.bootstrap(),
+ strudel.pattern,
+ Pattern.prototype.bootstrap(),
toneHelpersMocked,
uiHelpersMocked,
controls,