mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-14 06:43:47 -04:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 97a38a6f59 | |||
| 986de6a73b | |||
| 1750db2f1c | |||
| eadcf25775 | |||
| 1d2c4fd771 | |||
| 92bf43e3a6 | |||
| 9dd4385bbf | |||
| 274378df42 | |||
| 5ec217ea21 | |||
| d2375f89ee |
@@ -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 = [
|
||||
@@ -400,7 +401,7 @@ const generic_params = [
|
||||
* @example
|
||||
* freq("220 110 440 110").s("superzow").osc()
|
||||
* @example
|
||||
* freq("110".mulOut(".5 1.5 .6 [2 3]")).s("superzow").osc()
|
||||
* freq("110".mul.out(".5 1.5 .6 [2 3]")).s("superzow").osc()
|
||||
*
|
||||
*/
|
||||
['f', 'freq', ''],
|
||||
|
||||
@@ -4,7 +4,11 @@ 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, State, TimeSpan } from './index.mjs';
|
||||
import pattern from './pattern.mjs';
|
||||
const Pattern = pattern.Pattern;
|
||||
import { getTime } from './time.mjs';
|
||||
import { State } from './state.mjs';
|
||||
import { TimeSpan } from './timespan.mjs';
|
||||
|
||||
export const getDrawContext = (id = 'test-canvas') => {
|
||||
let canvas = document.querySelector('#' + id);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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 './pattern.mjs';
|
||||
const { isPattern, Pattern } = pattern;
|
||||
|
||||
let scoped = false;
|
||||
export const evalScope = async (...args) => {
|
||||
|
||||
+28
-19
@@ -4,27 +4,36 @@ 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 controls from './controls.mjs';
|
||||
export * from './euclid.mjs';
|
||||
import Fraction from './fraction.mjs';
|
||||
|
||||
import drawLine from './drawLine.mjs';
|
||||
import gist from './gist.js';
|
||||
import { logger } from './logger.mjs';
|
||||
export { Fraction, controls };
|
||||
export * from './hap.mjs';
|
||||
export * from './pattern.mjs';
|
||||
export * from './signal.mjs';
|
||||
export * from './state.mjs';
|
||||
export * from './timespan.mjs';
|
||||
export * from './util.mjs';
|
||||
export * from './speak.mjs';
|
||||
export * from './evaluate.mjs';
|
||||
export * from './repl.mjs';
|
||||
export * from './logger.mjs';
|
||||
export * from './time.mjs';
|
||||
export * from './draw.mjs';
|
||||
export * from './pianoroll.mjs';
|
||||
export * from './ui.mjs';
|
||||
export { default as drawLine } from './drawLine.mjs';
|
||||
export { default as gist } from './gist.js';
|
||||
// Fraction: Fraction, drawLine: drawline, gist: gist, logger: logger,
|
||||
|
||||
import controls from './controls.mjs';
|
||||
import pattern from './pattern.mjs';
|
||||
|
||||
import * as draw from './draw.mjs';
|
||||
import * as euclid from './euclid.mjs';
|
||||
import * as evaluate from './evaluate.mjs';
|
||||
import * as hap from './hap.mjs';
|
||||
import * as repl from './repl.mjs';
|
||||
import * as pianoroll from './pianoroll.mjs';
|
||||
import * as signal from './signal.mjs';
|
||||
import * as speak from './speak.mjs';
|
||||
import * as state from './state.mjs';
|
||||
import * as time from './time.mjs';
|
||||
import * as timespan from './timespan.mjs';
|
||||
import * as ui from './ui.mjs';
|
||||
import * as util from './util.mjs';
|
||||
|
||||
const core = { drawLine, gist, logger, Fraction, ...controls, ...pattern, ...draw, ...euclid,
|
||||
...evaluate, ...hap, ...repl, ...pianoroll, ...signal, ...speak,
|
||||
...state, ...time, ...timespan, ...ui, ...util
|
||||
};
|
||||
export default core;
|
||||
|
||||
// below won't work with runtime.mjs (json import fails)
|
||||
/* import * as p from './package.json';
|
||||
export const version = p.version; */
|
||||
|
||||
+148
-118
@@ -14,15 +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.
|
||||
@@ -1026,6 +1029,7 @@ export class Pattern {
|
||||
* @example
|
||||
* note("c3 d3 e3 g3").rev()
|
||||
*/
|
||||
|
||||
rev() {
|
||||
const pat = this;
|
||||
const query = function (state) {
|
||||
@@ -1047,7 +1051,7 @@ export class Pattern {
|
||||
}
|
||||
|
||||
palindrome() {
|
||||
return this.every(2, rev);
|
||||
return this.every(2, pattern.rev);
|
||||
}
|
||||
|
||||
juxBy(by, func) {
|
||||
@@ -1378,6 +1382,8 @@ function groupHapsBy(eq, haps) {
|
||||
return groups;
|
||||
}
|
||||
|
||||
pattern['Pattern'] = Pattern;
|
||||
|
||||
// congruent haps = haps with equal spans
|
||||
const congruent = (a, b) => a.spanEquals(b);
|
||||
// Pattern<Hap<T>> -> Pattern<Hap<T[]>>
|
||||
@@ -1501,53 +1507,48 @@ function _composeOp(a, b, func) {
|
||||
|
||||
// generate methods to do what and how
|
||||
for (const [what, [op, preprocess]] of Object.entries(composers)) {
|
||||
for (const how of hows) {
|
||||
Pattern.prototype[what + how] = function (...other) {
|
||||
var pat = this;
|
||||
other = sequence(other);
|
||||
if (preprocess) {
|
||||
pat = preprocess(pat);
|
||||
other = preprocess(other);
|
||||
}
|
||||
var result;
|
||||
// hack to remove undefs when doing 'keepif'
|
||||
if (what === 'keepif') {
|
||||
// avoid union, as we want to throw away the value of 'b' completely
|
||||
result = pat['_op' + how](other, (a) => (b) => op(a, b));
|
||||
result = result.removeUndefineds();
|
||||
} else {
|
||||
result = pat['_op' + how](other, (a) => (b) => _composeOp(a, b, op));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (how === 'Squeeze') {
|
||||
// support 'squeezeIn' longhand
|
||||
Pattern.prototype[what + 'SqueezeIn'] = Pattern.prototype[what + how];
|
||||
}
|
||||
if (how === 'In') {
|
||||
// set 'in' to default, but with magic properties to pick a different 'how'
|
||||
Object.defineProperty(Pattern.prototype, what, {
|
||||
// a getter that returns a function, so 'pat' can be
|
||||
// accessed by closures that are methods of that function..
|
||||
get: function () {
|
||||
const pat = this;
|
||||
// wrap the 'in' function as default behaviour
|
||||
const wrapper = (...other) => pat[what + 'In'](...other);
|
||||
// add methods to that function to pick alternative behaviours
|
||||
for (const wraphow of hows) {
|
||||
wrapper[wraphow.toLowerCase()] = (...other) => pat[what + wraphow](...other);
|
||||
Object.defineProperty(Pattern.prototype, what, {
|
||||
// a getter that returns a function, so 'pat' can be
|
||||
// accessed by closures that are methods of that function..
|
||||
get: function() {
|
||||
const pat = this;
|
||||
|
||||
// wrap the 'in' function as default behaviour
|
||||
const wrapper = (...other) => pat[what]['in'](...other);
|
||||
|
||||
// add methods to that function for each behaviour
|
||||
for (const how of hows) {
|
||||
wrapper[how.toLowerCase()] = function (...other) {
|
||||
var howpat = pat;
|
||||
other = sequence(other);
|
||||
if (preprocess) {
|
||||
howpat = preprocess(howpat);
|
||||
other = preprocess(other);
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// default what to 'set', e.g. squeeze = setSqueeze
|
||||
if (what === 'set') {
|
||||
Pattern.prototype[how.toLowerCase()] = Pattern.prototype[what + how];
|
||||
var result;
|
||||
// hack to remove undefs when doing 'keepif'
|
||||
if (what === 'keepif') {
|
||||
// avoid union, as we want to throw away the value of 'b' completely
|
||||
result = howpat['_op' + how](other, (a) => (b) => op(a, b));
|
||||
result = result.removeUndefineds();
|
||||
} else {
|
||||
result = howpat['_op' + how](other, (a) => (b) => _composeOp(a, b, op));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
wrapper.squeezein = wrapper.squeeze
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
});
|
||||
|
||||
// Default op to 'set', e.g. pat.squeeze(pat2) = pat.set.squeeze(pat2)
|
||||
for (const how of hows) {
|
||||
Pattern.prototype[how.toLowerCase()] = function (...args) { return this.set[how.toLowerCase()](args) };
|
||||
curry_toplevel(how.toLowerCase(), 2);
|
||||
}
|
||||
curry_toplevel(what, 2);
|
||||
}
|
||||
|
||||
// binary composers
|
||||
@@ -1562,14 +1563,22 @@ function _composeOp(a, b, func) {
|
||||
* .struct("x ~ x ~ ~ x ~ x ~ ~ ~ x ~ x ~ ~")
|
||||
* .slow(4)
|
||||
*/
|
||||
Pattern.prototype.struct = Pattern.prototype.keepifOut;
|
||||
Pattern.prototype.structAll = Pattern.prototype.keepOut;
|
||||
Pattern.prototype.mask = Pattern.prototype.keepifIn;
|
||||
Pattern.prototype.maskAll = Pattern.prototype.keepIn;
|
||||
Pattern.prototype.reset = Pattern.prototype.keepifTrig;
|
||||
Pattern.prototype.resetAll = Pattern.prototype.keepTrig;
|
||||
Pattern.prototype.restart = Pattern.prototype.keepifTrigzero;
|
||||
Pattern.prototype.restartAll = Pattern.prototype.keepTrigzero;
|
||||
Pattern.prototype.struct = function(...args) { return this.keepif.out(...args) }
|
||||
curry_toplevel('struct', 2);
|
||||
Pattern.prototype.structAll = function(...args) { return this.keep.out(...args) }
|
||||
curry_toplevel('structAll', 2);
|
||||
Pattern.prototype.mask = function(...args) { return this.keepif.in(...args) }
|
||||
curry_toplevel('mask', 2);
|
||||
Pattern.prototype.maskAll = function(...args) { return this.keep.in(...args) }
|
||||
curry_toplevel('maskAll', 2);
|
||||
Pattern.prototype.reset = function(...args) { return this.keepif.trig(...args) }
|
||||
curry_toplevel('reset', 2);
|
||||
Pattern.prototype.resetAll = function(...args) { return this.keep.trig(...args) }
|
||||
curry_toplevel('resetAll', 2);
|
||||
Pattern.prototype.restart = function(...args) { return this.keepif.trigzero(...args) }
|
||||
curry_toplevel('restart', 2);
|
||||
Pattern.prototype.restartAll = function(...args) { return this.keep.trigzero(...args) }
|
||||
curry_toplevel('restartAll', 2);
|
||||
})();
|
||||
|
||||
// methods of Pattern that get callable factories
|
||||
@@ -1594,10 +1603,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,
|
||||
@@ -1615,10 +1620,39 @@ Pattern.prototype.factories = {
|
||||
};
|
||||
// the magic happens in Pattern constructor. Keeping this in prototype enables adding methods from the outside (e.g. see tonal.ts)
|
||||
|
||||
function curry_toplevel(name, arity=1) {
|
||||
//if (name in pattern) {
|
||||
// throw(`${name} already exists`);
|
||||
//}
|
||||
if (arity == 1) {
|
||||
pattern[name] = (pat) => pat[name]();
|
||||
}
|
||||
else if (arity == 2) {
|
||||
pattern[name] = curry((a, pat) => pat[name](a));
|
||||
}
|
||||
else if (arity == 3) {
|
||||
pattern[name] = curry((a, b, pat) => pat[name](a, b));
|
||||
}
|
||||
else if (arity == 4) {
|
||||
pattern[name] = curry((a, b, c, pat) => pat[name](a, b, c));
|
||||
}
|
||||
}
|
||||
|
||||
for (const x of [[1, ['inv', 'invert', 'rev']],
|
||||
[2, ['chop','chunk','chunkBack', 'mask','struct','superimpose'].concat(Pattern.prototype.patternified)],
|
||||
[3, ['every','juxBy','off','range','rangex','range2','when']],
|
||||
[4, ['echo']]
|
||||
]) {
|
||||
for (const name of x[1]) {
|
||||
curry_toplevel(name, x[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Elemental patterns
|
||||
|
||||
// Nothing
|
||||
export const silence = new Pattern(() => []);
|
||||
const silence = new Pattern(() => []);
|
||||
pattern['silence'] = silence;
|
||||
|
||||
/** A discrete value that repeats once per cycle.
|
||||
*
|
||||
@@ -1626,14 +1660,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;
|
||||
// TODO: find out how to check wrong core dependency. below will never work !thing === 'undefined'
|
||||
@@ -1648,8 +1683,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;
|
||||
@@ -1659,6 +1695,7 @@ export function reify(thing) {
|
||||
}
|
||||
return pure(thing);
|
||||
}
|
||||
pattern['reify'] = reify;
|
||||
|
||||
/** The given items are played at the same time at the same length.
|
||||
*
|
||||
@@ -1666,12 +1703,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:
|
||||
*
|
||||
@@ -1682,7 +1727,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)));
|
||||
|
||||
@@ -1702,12 +1747,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;
|
||||
@@ -1716,6 +1762,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
|
||||
*
|
||||
@@ -1728,9 +1775,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
|
||||
*
|
||||
@@ -1740,16 +1788,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 = [];
|
||||
@@ -1760,20 +1809,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)) {
|
||||
@@ -1788,7 +1840,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;
|
||||
@@ -1809,57 +1861,27 @@ 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);
|
||||
}
|
||||
|
||||
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));
|
||||
pattern['pm'] = polymeter;
|
||||
|
||||
// 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) => {
|
||||
@@ -1872,25 +1894,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);
|
||||
@@ -1942,6 +1970,7 @@ Pattern.prototype.range2 = function (...args) {
|
||||
};
|
||||
|
||||
// call this after all Pattern.prototype.define calls have been executed! (right before evaluate)
|
||||
// (but isn't this called for every define call anyway?)
|
||||
Pattern.prototype.bootstrap = function () {
|
||||
// makeComposable(Pattern.prototype);
|
||||
const bootstrapped = Object.fromEntries(
|
||||
@@ -1970,18 +1999,18 @@ Pattern.prototype.bootstrap = function () {
|
||||
// a getter that returns a function, so 'pat' can be
|
||||
// accessed by closures that are methods of that function..
|
||||
get: function() {
|
||||
const pat = this;
|
||||
// wrap the default behaviour
|
||||
const pat = this;
|
||||
// wrap the default behaviour
|
||||
const wrapper = pat.patternify(x => x.innerJoin(), func);
|
||||
|
||||
// add the variants
|
||||
// add the variants
|
||||
wrapper['in'] = pat.patternify(x => x.innerJoin(), func);
|
||||
wrapper['out'] = pat.patternify(x => x.outerJoin(), func);
|
||||
wrapper['trig'] = pat.patternify(x => x.trigJoin(), func);
|
||||
wrapper['trigzero'] = pat.patternify(x => x.trigzeroJoin(), func);
|
||||
wrapper['squeeze'] = pat.patternify(x => x.squeezeJoin(), func);
|
||||
|
||||
return wrapper;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
});
|
||||
*/
|
||||
@@ -2018,4 +2047,5 @@ 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(1), { patternified: true, composable: true });
|
||||
|
||||
export default pattern;
|
||||
|
||||
@@ -4,7 +4,11 @@ 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, toMidi, getDrawContext } from './index.mjs';
|
||||
import pattern from './pattern.mjs';
|
||||
const { Pattern } = pattern;
|
||||
|
||||
import { toMidi } from './util.mjs';
|
||||
import { getDrawContext } from './draw.mjs';
|
||||
|
||||
const scale = (normalized, min, max) => normalized * (max - min) + min;
|
||||
const getValue = (e) => {
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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, reify } from './index.mjs';
|
||||
import pattern from './pattern.mjs';
|
||||
const {Pattern, patternify2, reify} = pattern;
|
||||
|
||||
let synth;
|
||||
try {
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -8,10 +8,9 @@ import Fraction from 'fraction.js';
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import {
|
||||
TimeSpan,
|
||||
Hap,
|
||||
State,
|
||||
import core from '../index.mjs';
|
||||
|
||||
const {
|
||||
Pattern,
|
||||
pure,
|
||||
stack,
|
||||
@@ -29,6 +28,12 @@ import {
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
id,
|
||||
ply,
|
||||
rev,
|
||||
TimeSpan,
|
||||
Hap,
|
||||
State,
|
||||
saw,
|
||||
saw2,
|
||||
isaw,
|
||||
@@ -39,11 +44,7 @@ import {
|
||||
square2,
|
||||
tri,
|
||||
tri2,
|
||||
id,
|
||||
ply,
|
||||
rev,
|
||||
time,
|
||||
} from '../index.mjs';
|
||||
time} = core;
|
||||
|
||||
import { steady } from '../signal.mjs';
|
||||
|
||||
@@ -156,32 +157,32 @@ describe('Pattern', () => {
|
||||
describe('add()', () => {
|
||||
it('can structure In()', () => {
|
||||
expect(pure(3).add(pure(4)).query(st(0, 1))[0].value).toBe(7);
|
||||
expect(pure(3).addIn(pure(4)).query(st(0, 1))[0].value).toBe(7);
|
||||
expect(pure(3).add.in(pure(4)).query(st(0, 1))[0].value).toBe(7);
|
||||
});
|
||||
it('can structure Out()', () => {
|
||||
sameFirst(sequence(1, 2).addOut(4), sequence(5, 6).struct(true));
|
||||
sameFirst(sequence(1, 2).add.out(4), sequence(5, 6).struct(true));
|
||||
});
|
||||
it('can Mix() structure', () => {
|
||||
expect(sequence(1, 2).addMix(silence, 5, silence).firstCycle()).toStrictEqual([
|
||||
expect(sequence(1, 2).add.mix(silence, 5, silence).firstCycle()).toStrictEqual([
|
||||
new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 6),
|
||||
new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 7),
|
||||
]);
|
||||
});
|
||||
it('can Trig() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).addTrig(20, 30).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).add.trig(20, 30).early(2),
|
||||
sequence(26, 27, 36, 37),
|
||||
);
|
||||
});
|
||||
it('can Trigzero() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).addTrigzero(20, 30).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).add.trigzero(20, 30).early(2),
|
||||
sequence(21, 22, 31, 32),
|
||||
);
|
||||
});
|
||||
it('can Squeeze() structure', () => {
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).addSqueeze(sequence(10, 20, 30)),
|
||||
sequence(1, [2, 3]).add.squeeze(sequence(10, 20, 30)),
|
||||
sequence(
|
||||
[11, 21, 31],
|
||||
[
|
||||
@@ -193,7 +194,7 @@ describe('Pattern', () => {
|
||||
});
|
||||
it('can SqueezeOut() structure', () => {
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).addSqueezeOut(10, 20, 30),
|
||||
sequence(1, [2, 3]).add.squeezeout(10, 20, 30),
|
||||
sequence([11, [12, 13]], [21, [22, 23]], [31, [32, 33]]),
|
||||
);
|
||||
});
|
||||
@@ -204,32 +205,32 @@ describe('Pattern', () => {
|
||||
describe('keep()', () => {
|
||||
it('can structure In()', () => {
|
||||
expect(pure(3).keep(pure(4)).query(st(0, 1))[0].value).toBe(3);
|
||||
expect(pure(3).keepIn(pure(4)).query(st(0, 1))[0].value).toBe(3);
|
||||
expect(pure(3).keep.in(pure(4)).query(st(0, 1))[0].value).toBe(3);
|
||||
});
|
||||
it('can structure Out()', () => {
|
||||
sameFirst(sequence(1, 2).keepOut(4), sequence(1, 2).struct(true));
|
||||
sameFirst(sequence(1, 2).keep.out(4), sequence(1, 2).struct(true));
|
||||
});
|
||||
it('can Mix() structure', () => {
|
||||
expect(sequence(1, 2).keepMix(silence, 5, silence).firstCycle()).toStrictEqual([
|
||||
expect(sequence(1, 2).keep.mix(silence, 5, silence).firstCycle()).toStrictEqual([
|
||||
new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 1),
|
||||
new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 2),
|
||||
]);
|
||||
});
|
||||
it('can Trig() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepTrig(20, 30).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keep.trig(20, 30).early(2),
|
||||
sequence(6, 7, 6, 7),
|
||||
);
|
||||
});
|
||||
it('can Trigzero() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepTrigzero(20, 30).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keep.trigzero(20, 30).early(2),
|
||||
sequence(1, 2, 1, 2),
|
||||
);
|
||||
});
|
||||
it('can Squeeze() structure', () => {
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).keepSqueeze(sequence(10, 20, 30)),
|
||||
sequence(1, [2, 3]).keep.squeeze(sequence(10, 20, 30)),
|
||||
sequence(
|
||||
[1, 1, 1],
|
||||
[
|
||||
@@ -239,39 +240,39 @@ describe('Pattern', () => {
|
||||
),
|
||||
);
|
||||
});
|
||||
it('can SqueezeOut() structure', () => {
|
||||
sameFirst(sequence(1, [2, 3]).keepSqueezeOut(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]]));
|
||||
it('can squeezeOut() structure', () => {
|
||||
sameFirst(sequence(1, [2, 3]).keep.squeezeout(10, 20, 30), sequence([1, [2, 3]], [1, [2, 3]], [1, [2, 3]]));
|
||||
});
|
||||
});
|
||||
describe('keepif()', () => {
|
||||
it('can structure In()', () => {
|
||||
sameFirst(sequence(3, 4).keepif(true, false), sequence(3, silence));
|
||||
sameFirst(sequence(3, 4).keepifIn(true, false), sequence(3, silence));
|
||||
sameFirst(sequence(3, 4).keepif.in(true, false), sequence(3, silence));
|
||||
});
|
||||
it('can structure Out()', () => {
|
||||
sameFirst(pure(1).keepifOut(true, false), sequence(1, silence));
|
||||
sameFirst(pure(1).keepif.out(true, false), sequence(1, silence));
|
||||
});
|
||||
it('can Mix() structure', () => {
|
||||
expect(sequence(1, 2).keepifMix(false, true, false).firstCycle()).toStrictEqual([
|
||||
expect(sequence(1, 2).keepif.mix(false, true, false).firstCycle()).toStrictEqual([
|
||||
new Hap(ts(1 / 3, 1 / 2), ts(1 / 3, 1 / 2), 1),
|
||||
new Hap(ts(1 / 2, 2 / 3), ts(1 / 2, 2 / 3), 2),
|
||||
]);
|
||||
});
|
||||
it('can Trig() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepifTrig(false, true).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepif.trig(false, true).early(2),
|
||||
sequence(silence, silence, 6, 7),
|
||||
);
|
||||
});
|
||||
it('can Trigzero() structure', () => {
|
||||
sameFirst(
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepifTrigzero(false, true).early(2),
|
||||
slowcat(sequence(1, 2, 3, 4), 5, sequence(6, 7, 8, 9), 10).keepif.trigzero(false, true).early(2),
|
||||
sequence(silence, silence, 1, 2),
|
||||
);
|
||||
});
|
||||
it('can Squeeze() structure', () => {
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).keepifSqueeze(sequence(true, true, false)),
|
||||
sequence(1, [2, 3]).keepif.squeeze(sequence(true, true, false)),
|
||||
sequence(
|
||||
[1, 1, silence],
|
||||
[
|
||||
@@ -282,7 +283,7 @@ describe('Pattern', () => {
|
||||
);
|
||||
});
|
||||
it('can SqueezeOut() structure', () => {
|
||||
sameFirst(sequence(1, [2, 3]).keepifSqueezeOut(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence));
|
||||
sameFirst(sequence(1, [2, 3]).keepif.squeezeout(true, true, false), sequence([1, [2, 3]], [1, [2, 3]], silence));
|
||||
});
|
||||
});
|
||||
describe('sub()', () => {
|
||||
@@ -320,15 +321,15 @@ describe('Pattern', () => {
|
||||
it('Can set things with plain values', () => {
|
||||
sameFirst(sequence(1, 2, 3).set(4), sequence(4).fast(3));
|
||||
});
|
||||
describe('setOut()', () => {
|
||||
describe('set.out()', () => {
|
||||
it('Can set things with structure from second pattern', () => {
|
||||
sameFirst(sequence(1, 2).setOut(4), pure(4).mask(true, true));
|
||||
sameFirst(sequence(1, 2).set.out(4), pure(4).mask(true, true));
|
||||
});
|
||||
});
|
||||
describe('setSqueeze()', () => {
|
||||
describe('set.squeeze()', () => {
|
||||
it('Can squeeze one pattern inside the haps of another', () => {
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).setSqueeze(sequence('a', 'b', 'c')),
|
||||
sequence(1, [2, 3]).set.squeeze(sequence('a', 'b', 'c')),
|
||||
sequence(
|
||||
['a', 'b', 'c'],
|
||||
[
|
||||
@@ -338,7 +339,7 @@ describe('Pattern', () => {
|
||||
),
|
||||
);
|
||||
sameFirst(
|
||||
sequence(1, [2, 3]).setSqueeze('a', 'b', 'c'),
|
||||
sequence(1, [2, 3]).set.squeeze('a', 'b', 'c'),
|
||||
sequence(
|
||||
['a', 'b', 'c'],
|
||||
[
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
import { getFrequency, logger, Pattern } from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
const { getFrequency, logger, Pattern } = strudel;
|
||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||
import csd from './project.csd?raw';
|
||||
// import livecodeOrc from './livecode.orc?raw';
|
||||
|
||||
@@ -4,9 +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 { evaluate as _evaluate } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
import shapeshifter from './shapeshifter.mjs';
|
||||
|
||||
export const evaluate = async (code) => {
|
||||
return _evaluate(code, shapeshifter);
|
||||
return core.evaluate(code, shapeshifter);
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import shiftCodegen from 'shift-codegen';
|
||||
const codegen = shiftCodegen.default || shiftCodegen; // parcel module resolution fuckup
|
||||
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
|
||||
const { Pattern } = strudel;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { expect, describe, it } from 'vitest';
|
||||
|
||||
import { evaluate } from '../evaluate.mjs';
|
||||
import { mini } from '@strudel.cycles/mini';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
const { fastcat, evalScope } = strudel;
|
||||
|
||||
describe('evaluate', async () => {
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, isPattern, isNote, getPlayableNoteValue, logger } = core;
|
||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||
|
||||
// if you use WebMidi from outside of this package, make sure to import that instance:
|
||||
|
||||
@@ -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 core 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, rand, chooseInWith, Fraction } = core;
|
||||
|
||||
var _seedState = 0;
|
||||
const randOffset = 0.0002;
|
||||
@@ -31,7 +31,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': "%"
|
||||
@@ -96,7 +96,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') {
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, logger, parseNumeral } = core;
|
||||
|
||||
let connection; // Promise<OSC>
|
||||
function connect() {
|
||||
|
||||
@@ -13,12 +13,13 @@ npm i @strudel.cycles/react
|
||||
Here is a minimal example of how to set up a MiniRepl:
|
||||
|
||||
```jsx
|
||||
import { evalScope, controls } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const {evalScope} = core;
|
||||
import { MiniRepl } from '@strudel.cycles/react';
|
||||
import { prebake } from '../repl/src/prebake.mjs';
|
||||
|
||||
evalScope(
|
||||
controls,
|
||||
core,
|
||||
import('@strudel.cycles/core'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/mini'),
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+14
-13
@@ -7,7 +7,7 @@ import { tags as r } from "@lezer/highlight";
|
||||
import { createTheme as Z } from "@uiw/codemirror-themes";
|
||||
import { useInView as ee } from "react-hook-inview";
|
||||
import { webaudioOutput as te, getAudioContext as re } from "@strudel.cycles/webaudio";
|
||||
import { repl as oe } from "@strudel.cycles/core";
|
||||
import oe from "@strudel.cycles/core";
|
||||
import { transpiler as ne } from "@strudel.cycles/transpiler";
|
||||
const ae = Z({
|
||||
theme: "dark",
|
||||
@@ -177,7 +177,8 @@ function O({ type: e }) {
|
||||
function Ee(e) {
|
||||
return L(() => (window.addEventListener("message", e), () => window.removeEventListener("message", e)), [e]), _((t) => window.postMessage(t, "*"), []);
|
||||
}
|
||||
function we({
|
||||
const we = oe.repl;
|
||||
function ye({
|
||||
defaultOutput: e,
|
||||
interval: t,
|
||||
getTime: o,
|
||||
@@ -189,8 +190,8 @@ function we({
|
||||
onEvalError: c,
|
||||
onToggle: i
|
||||
}) {
|
||||
const m = V(() => ye(), []), [h, g] = w(), [C, N] = w(), [p, y] = w(s), [M, S] = w(), [k, D] = w(), [F, x] = w(!1), b = p !== M, { scheduler: A, evaluate: T, start: J, stop: q, pause: Q } = V(
|
||||
() => oe({
|
||||
const m = V(() => ke(), []), [h, g] = w(), [C, N] = w(), [p, y] = w(s), [M, S] = w(), [k, D] = w(), [F, x] = w(!1), b = p !== M, { scheduler: A, evaluate: T, start: J, stop: q, pause: Q } = V(
|
||||
() => we({
|
||||
interval: t,
|
||||
defaultOutput: e,
|
||||
onSchedulerError: g,
|
||||
@@ -243,11 +244,11 @@ function we({
|
||||
}
|
||||
};
|
||||
}
|
||||
function ye() {
|
||||
function ke() {
|
||||
return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
|
||||
}
|
||||
const ke = () => re().currentTime;
|
||||
function Se({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) {
|
||||
const _e = () => re().currentTime;
|
||||
function Te({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) {
|
||||
const {
|
||||
code: s,
|
||||
setCode: u,
|
||||
@@ -261,10 +262,10 @@ function Se({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) {
|
||||
scheduler: C,
|
||||
togglePlay: N,
|
||||
stop: p
|
||||
} = we({
|
||||
} = ye({
|
||||
initialCode: e,
|
||||
defaultOutput: te,
|
||||
getTime: ke
|
||||
getTime: _e
|
||||
}), [y, M] = w(), [S, k] = ee({
|
||||
threshold: 0.01
|
||||
}), D = H(), F = V(() => ((k || !t) && (D.current = !0), k || D.current), [k, t]);
|
||||
@@ -307,14 +308,14 @@ function Se({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) {
|
||||
onViewChanged: M
|
||||
})));
|
||||
}
|
||||
const Te = (e) => j(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]);
|
||||
const Ve = (e) => j(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]);
|
||||
export {
|
||||
de as CodeMirror,
|
||||
Se as MiniRepl,
|
||||
Te as MiniRepl,
|
||||
K as cx,
|
||||
ce as flash,
|
||||
ue as useHighlighting,
|
||||
Te as useKeydown,
|
||||
Ve as useKeydown,
|
||||
Ee as usePostMessage,
|
||||
we as useStrudel
|
||||
ye as useStrudel
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { evalScope, controls } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { evalScope } = core;
|
||||
import { getAudioContext, panic, webaudioOutput } from '@strudel.cycles/webaudio';
|
||||
import { useCallback, useState } from 'react';
|
||||
import CodeMirror, { flash } from '../../../src/components/CodeMirror6';
|
||||
@@ -10,8 +11,8 @@ import './style.css';
|
||||
|
||||
// TODO: only import stuff when play is pressed?
|
||||
evalScope(
|
||||
controls,
|
||||
import('@strudel.cycles/core'),
|
||||
core,
|
||||
// import('@strudel.cycles/core'),
|
||||
// import('@strudel.cycles/tone'),
|
||||
// import('@strudel.cycles/midi'), // TODO: find out why midi loads tone.js
|
||||
import('@strudel.cycles/tonal'),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import { MiniRepl } from './components/MiniRepl';
|
||||
import 'tailwindcss/tailwind.css';
|
||||
import { controls, evalScope } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const {controls, evalScope} = core;
|
||||
|
||||
evalScope(
|
||||
controls,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useRef, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { repl } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const repl = core.repl
|
||||
import { transpiler } from '@strudel.cycles/transpiler';
|
||||
import usePostMessage from './usePostMessage.mjs';
|
||||
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, isPattern } = core;
|
||||
|
||||
var writeMessage;
|
||||
var choosing = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { toMidi } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const toMidi = core.toMidi;
|
||||
|
||||
let loadCache = {};
|
||||
async function loadFont(name) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Pattern, getPlayableNoteValue, toMidi } from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
const { Pattern, getPlayableNoteValue, toMidi } = strudel;
|
||||
import { getAudioContext } from '@strudel.cycles/webaudio';
|
||||
import { loadSoundfont as _loadSoundfont, startPresetNote } from 'sfumato';
|
||||
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { pure } = core;
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('tonal', () => {
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, pattern, mod } = core;
|
||||
|
||||
// transpose note inside scale by offset steps
|
||||
// function scaleOffset(scale: string, offset: number, note: string) {
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, stack, reify, Hap } = core
|
||||
|
||||
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) =>
|
||||
|
||||
@@ -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 strudel from '@strudel.cycles/core';
|
||||
const { pure } = strudel;
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('tone', () => {
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern } = core;
|
||||
|
||||
import * as _Tone from 'tone';
|
||||
|
||||
// import Tone from here, to make sure to get the same AudioContext
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { evaluate as _evaluate } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
import { transpiler } from './transpiler.mjs';
|
||||
export * from './transpiler.mjs';
|
||||
|
||||
export const evaluate = (code) => _evaluate(code, transpiler);
|
||||
export const evaluate = (code) => core.evaluate(code, transpiler);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import escodegen from 'escodegen';
|
||||
import { parse } from 'acorn';
|
||||
import { walk } from 'estree-walker';
|
||||
import { isNote } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { isNote } = core;
|
||||
|
||||
export function transpiler(input, options = {}) {
|
||||
const { wrapAsync = false, addReturn = true, simpleLocs = false } = options;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { logger, toMidi } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { logger, toMidi } = core;
|
||||
import { getAudioContext } from './index.mjs';
|
||||
|
||||
const bufferCache = {}; // string: Promise<ArrayBuffer>
|
||||
|
||||
@@ -4,9 +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, getFrequency, patternify2 } from '@strudel.cycles/core';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import { fromMidi, logger, toMidi } from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
const { fromMidi, logger, toMidi } = strudel;
|
||||
import './feedbackdelay.mjs';
|
||||
import './reverb.mjs';
|
||||
import { getSampleBufferSource } from './sampler.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 core from '@strudel.cycles/core';
|
||||
const { Pattern } = core;
|
||||
|
||||
Pattern.prototype._tune = function (scale, tonic = 220) {
|
||||
const tune = new Tune();
|
||||
|
||||
@@ -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 core from '@strudel.cycles/core';
|
||||
const { Pattern, mod } = core;
|
||||
|
||||
export function edo(name) {
|
||||
if (!/^[1-9]+[0-9]*edo$/.test(name)) {
|
||||
|
||||
+3
-2
@@ -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 { cleanupDraw, cleanupUi, controls, evalScope, logger } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { cleanupDraw, cleanupUi, evalScope, logger } = core;
|
||||
import { CodeMirror, cx, flash, useHighlighting, useStrudel } from '@strudel.cycles/react';
|
||||
import {
|
||||
getAudioContext,
|
||||
@@ -47,7 +48,7 @@ const modules = [
|
||||
|
||||
evalScope(
|
||||
// Tone,
|
||||
controls, // sadly, this cannot be exported from core direclty
|
||||
core,
|
||||
{ WebDirt },
|
||||
...modules,
|
||||
);
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
import XMarkIcon from '@heroicons/react/20/solid/XMarkIcon';
|
||||
import { logger } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { logger } = core;
|
||||
import { cx } from '@strudel.cycles/react';
|
||||
import { nanoid } from 'nanoid';
|
||||
import React, { useContext, useCallback, useLayoutEffect, useRef, useState } from 'react';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Pattern, toMidi } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
const { Pattern, toMidi } = core;
|
||||
import { samples } from '@strudel.cycles/webaudio';
|
||||
|
||||
export async function prebake({ isMock = false, baseDir = '.' } = {}) {
|
||||
|
||||
+16
-16
@@ -5,8 +5,8 @@
|
||||
// import * as tunes from './tunes.mjs';
|
||||
// import { evaluate } from '@strudel.cycles/eval';
|
||||
import { evaluate } from '@strudel.cycles/transpiler';
|
||||
import { evalScope } from '@strudel.cycles/core';
|
||||
import * as strudel from '@strudel.cycles/core';
|
||||
import strudel from '@strudel.cycles/core';
|
||||
const { Pattern, evalScope } = strudel;
|
||||
import * as webaudio from '@strudel.cycles/webaudio';
|
||||
import controls from '@strudel.cycles/core/controls.mjs';
|
||||
// import gist from '@strudel.cycles/core/gist.js';
|
||||
@@ -85,51 +85,51 @@ const toneHelpersMocked = {
|
||||
highpass: mockNode,
|
||||
};
|
||||
|
||||
strudel.Pattern.prototype.osc = function () {
|
||||
Pattern.prototype.osc = function () {
|
||||
return this;
|
||||
};
|
||||
strudel.Pattern.prototype.csound = function () {
|
||||
Pattern.prototype.csound = 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;
|
||||
};
|
||||
|
||||
@@ -159,7 +159,7 @@ const loadSoundfont = () => {};
|
||||
evalScope(
|
||||
// Tone,
|
||||
strudel,
|
||||
strudel.Pattern.prototype.bootstrap(),
|
||||
Pattern.prototype.bootstrap(),
|
||||
toneHelpersMocked,
|
||||
uiHelpersMocked,
|
||||
controls,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { evalScope, controls } from '@strudel.cycles/core';
|
||||
import core from '@strudel.cycles/core';
|
||||
import { MiniRepl as _MiniRepl } from '@strudel.cycles/react';
|
||||
import { samples } from '@strudel.cycles/webaudio';
|
||||
import { prebake } from '../repl/src/prebake.mjs';
|
||||
@@ -7,9 +7,9 @@ fetch('https://strudel.tidalcycles.org/EmuSP12.json')
|
||||
.then((res) => res.json())
|
||||
.then((json) => samples(json, 'https://strudel.tidalcycles.org/EmuSP12/'));
|
||||
|
||||
evalScope(
|
||||
controls,
|
||||
import('@strudel.cycles/core'),
|
||||
core.evalScope(
|
||||
core,
|
||||
// import('@strudel.cycles/core'),
|
||||
// import('@strudel.cycles/tone'),
|
||||
import('@strudel.cycles/tonal'),
|
||||
import('@strudel.cycles/mini'),
|
||||
|
||||
Reference in New Issue
Block a user