export pattern.mjs as single object

This commit is contained in:
alex
2022-12-05 11:33:40 +00:00
parent 5ec217ea21
commit 274378df42
30 changed files with 175 additions and 121 deletions
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Pattern, sequence } from './pattern.mjs';
import pattern from './pattern.mjs';
const { Pattern, sequence } = pattern;
const controls = {};
const generic_params = [
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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);
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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';
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { isPattern, Pattern } from './index.mjs';
import { pattern } from './index.mjs';
const { isPattern, Pattern } = pattern;
let scoped = false;
export const evalScope = async (...args) => {
+2 -2
View File
@@ -4,13 +4,13 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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';
+82 -59
View File
@@ -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() // "<e5 b4 [d5 c5]>".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;
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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) => {
+2 -1
View File
@@ -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';
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Pattern, patternify2 } from './index.mjs';
import { pattern } from './index.mjs';
const {Pattern, patternify2} = pattern;
let synth;
try {
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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';
+19 -16
View File
@@ -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';
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { pure } from '../pattern.mjs';
import pattern from '../pattern.mjs';
const { pure } = pattern;
import {
isNote,
tokenizeNote,
+1 -1
View File
@@ -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);
+3 -2
View File
@@ -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']);
+2 -1
View File
@@ -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:
+4 -4
View File
@@ -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') {
+2 -1
View File
@@ -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<OSC>
function connect() {
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Pattern, isPattern } from '@strudel.cycles/core';
import { pattern } from '@strudel.cycles/core';
const { Pattern, isPattern } = pattern;
var serialWriter;
var choosing = false;
+3 -1
View File
@@ -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) {
+2 -1
View File
@@ -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', () => {
+2 -1
View File
@@ -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) {
+4 -2
View File
@@ -4,7 +4,9 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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) =>
+2 -1
View File
@@ -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', () => {
+3 -1
View File
@@ -4,7 +4,9 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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
+1 -1
View File
@@ -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';
+2 -1
View File
@@ -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();
+2 -1
View File
@@ -4,7 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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)) {
+2 -1
View File
@@ -4,7 +4,7 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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,
);
+2 -1
View File
@@ -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 = '.' } = {}) {
+15 -13
View File
@@ -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,