Compare commits

..

1 Commits

Author SHA1 Message Date
Alex McLean a481a86c3b not quite.. 2025-07-15 17:38:50 +01:00
27 changed files with 119 additions and 1027 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
jsdoc-synonyms.js - Add support for @synonyms tag jsdoc-synonyms.js - Add support for @synonym tag
Copyright (C) 2023 Strudel contributors - see <https://codeberg.org/uzu/strudel/activity/contributors> Copyright (C) 2023 Strudel contributors - see <https://codeberg.org/uzu/strudel/activity/contributors>
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/>. 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/>.
*/ */
+13 -111
View File
@@ -252,20 +252,6 @@ export const { fmenv } = registerControl('fmenv');
* *
*/ */
export const { fmattack } = registerControl('fmattack'); export const { fmattack } = registerControl('fmattack');
/**
* waveform of the fm modulator
*
* @name fmwave
* @param {number | Pattern} wave waveform
* @example
* n("0 1 2 3".fast(4)).scale("d:minor").s("sine").fmwave("<sine square sawtooth crackle>").fm(4).fmh(2.01)
* @example
* n("0 1 2 3".fast(4)).chord("<Dm Am F G>").voicing().s("sawtooth").fmwave("brown").fm(.6)
*
*/
export const { fmwave } = registerControl('fmwave');
/** /**
* Decay time for the FM envelope: seconds until the sustain level is reached after the attack phase. * Decay time for the FM envelope: seconds until the sustain level is reached after the attack phase.
* *
@@ -320,7 +306,6 @@ export const { fft } = registerControl('fft');
* *
* @name decay * @name decay
* @param {number | Pattern} time decay time in seconds * @param {number | Pattern} time decay time in seconds
* @synonyms dec
* @example * @example
* note("c3 e3 f3 g3").decay("<.1 .2 .3 .4>").sustain(0) * note("c3 e3 f3 g3").decay("<.1 .2 .3 .4>").sustain(0)
* *
@@ -459,78 +444,6 @@ export const { crush } = registerControl('crush');
*/ */
export const { coarse } = registerControl('coarse'); export const { coarse } = registerControl('coarse');
/**
* modulate the amplitude of a sound with a continuous waveform
*
* @name tremolo
* @synonyms trem
* @param {number | Pattern} speed modulation speed in HZ
* @example
* note("d d d# d".fast(4)).s("supersaw").tremolo("<3 2 100> ").tremoloskew("<.5>")
*
*/
export const { tremolo } = registerControl(['tremolo', 'tremolodepth', 'tremoloskew', 'tremolophase'], 'trem');
/**
* modulate the amplitude of a sound with a continuous waveform
*
* @name tremolosync
* @synonyms tremsync
* @param {number | Pattern} cycles modulation speed in cycles
* @example
* note("d d d# d".fast(4)).s("supersaw").tremolosync("4").tremoloskew("<1 .5 0>")
*
*/
export const { tremolosync } = registerControl(
['tremolosync', 'tremolodepth', 'tremoloskew', 'tremolophase'],
'tremsync',
);
/**
* depth of amplitude modulation
*
* @name tremolodepth
* @synonyms tremdepth
* @param {number | Pattern} depth
* @example
* note("a1 a1 a#1 a1".fast(4)).s("pulse").tremsync(4).tremolodepth("<1 2 .7>")
*
*/
export const { tremolodepth } = registerControl('tremolodepth', 'tremdepth');
/**
* alter the shape of the modulation waveform
*
* @name tremoloskew
* @synonyms tremskew
* @param {number | Pattern} amount between 0 & 1, the shape of the waveform
* @example
* note("{f a c e}%16").s("sawtooth").tremsync(4).tremoloskew("<.5 0 1>")
*
*/
export const { tremoloskew } = registerControl('tremoloskew', 'tremskew');
/**
* alter the phase of the modulation waveform
*
* @name tremolophase
* @synonyms tremphase
* @param {number | Pattern} offset the offset in cycles of the modulation
* @example
* note("{f a c e}%16").s("sawtooth").tremsync(4).tremolophase("<0 .25 .66>")
*
*/
export const { tremolophase } = registerControl('tremolophase', 'tremphase');
/**
* shape of amplitude modulation
*
* @name tremoloshape
* @param {number | Pattern} shape tri | square | sine | saw | ramp
* @example
* note("{f g c d}%16").tremsync(4).tremoloshape("<sine tri square>").s("sawtooth")
*
*/
export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
/** /**
* filter overdrive for supported filter types * filter overdrive for supported filter types
* *
@@ -540,30 +453,6 @@ export const { tremoloshape } = registerControl('tremoloshape', 'tremshape');
* note("{f g g c d a a#}%16".sub(17)).s("supersaw").lpenv(8).lpf(150).lpq(.8).ftype('ladder').drive("<.5 4>") * note("{f g g c d a a#}%16".sub(17)).s("supersaw").lpenv(8).lpf(150).lpq(.8).ftype('ladder').drive("<.5 4>")
* *
*/ */
// TODO: SUPRADOUGH implement post orbit "pump" sidechain effect
// /**
// * modulate the amplitude of an orbit to create a "sidechain" like effect
// *
// * @name pump
// * @param {number | Pattern} speed modulation speed in cycles
// * @example
// * note("{f g c d}%16").s("sawtooth").pump(".25:.75")
// *
// */
// export const { pump } = registerControl(['pump', 'pumpdepth']);
// /**
// * modulate the amplitude of an orbit to create a "sidechain" like effect
// *
// * @name pumpdepth
// * @param {number | Pattern} depth depth of modulation from 0 to 1
// * @example
// * note("{f g c d}%16").s("sawtooth").pump(".25").depth("<.25 .5 .75 1>")
// *
// */
// export const { pumpdepth } = registerControl('pumpdepth');
export const { drive } = registerControl('drive'); export const { drive } = registerControl('drive');
/** /**
@@ -1672,6 +1561,18 @@ export const { density } = registerControl('density');
// ['modwheel'], // ['modwheel'],
export const { expression } = registerControl('expression'); export const { expression } = registerControl('expression');
export const { sustainpedal } = registerControl('sustainpedal'); export const { sustainpedal } = registerControl('sustainpedal');
/* // TODO: doesn't seem to do anything
*
* Tremolo Audio DSP effect
*
* @name tremolodepth
* @param {number | Pattern} depth between 0 and 1
* @example
* n("0,4,7").tremolodepth("<0 .3 .6 .9>").osc()
*
*/
export const { tremolodepth, tremdp } = registerControl('tremolodepth', 'tremdp');
export const { tremolorate, tremr } = registerControl('tremolorate', 'tremr');
export const { fshift } = registerControl('fshift'); export const { fshift } = registerControl('fshift');
export const { fshiftnote } = registerControl('fshiftnote'); export const { fshiftnote } = registerControl('fshiftnote');
@@ -1748,6 +1649,7 @@ export const { zmod } = registerControl('zmod');
// like crush but scaled differently // like crush but scaled differently
export const { zcrush } = registerControl('zcrush'); export const { zcrush } = registerControl('zcrush');
export const { zdelay } = registerControl('zdelay'); export const { zdelay } = registerControl('zdelay');
export const { tremolo } = registerControl('tremolo');
export const { zzfx } = registerControl('zzfx'); export const { zzfx } = registerControl('zzfx');
/** /**
+2 -2
View File
@@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th
*/ */
import createClock from './zyklus.mjs'; import createClock from './zyklus.mjs';
import { errorLogger, logger } from './logger.mjs'; import { logger } from './logger.mjs';
export class Cyclist { export class Cyclist {
constructor({ constructor({
@@ -76,7 +76,7 @@ export class Cyclist {
} }
}); });
} catch (e) { } catch (e) {
errorLogger(e); logger(`[cyclist] error: ${e.message}`);
onError?.(e); onError?.(e);
} }
}, },
-6
View File
@@ -4,12 +4,6 @@ let debounce = 1000,
lastMessage, lastMessage,
lastTime; lastTime;
export function errorLogger(e, origin = 'cyclist') {
//TODO: add some kind of debug flag that enables this while in dev mode
// console.error(e)
logger(`[${origin}] error: ${e.message}`);
}
export function logger(message, type, data = {}) { export function logger(message, type, data = {}) {
let t = performance.now(); let t = performance.now();
if (lastMessage === message && t - lastTime < debounce) { if (lastMessage === message && t - lastTime < debounce) {
+3 -2
View File
@@ -8,9 +8,10 @@ import { logger } from './logger.mjs';
import { ClockCollator, cycleToSeconds } from './util.mjs'; import { ClockCollator, cycleToSeconds } from './util.mjs';
export class NeoCyclist { export class NeoCyclist {
constructor({ onTrigger, onToggle, getTime }) { constructor({ onTrigger, onToggle, getTime, latency = 0.1 }) {
this.started = false; this.started = false;
this.cps = 0.5; this.cps = 0.5;
this.lastTick = 0; // absolute time when last tick (clock callback) happened
this.getTime = getTime; // get absolute time this.getTime = getTime; // get absolute time
this.time_at_last_tick_message = 0; this.time_at_last_tick_message = 0;
// the clock of the worker and the audio context clock can drift apart over time // the clock of the worker and the audio context clock can drift apart over time
@@ -19,7 +20,7 @@ export class NeoCyclist {
// in order to schedule events consistently. // in order to schedule events consistently.
this.collator = new ClockCollator({ getTargetClockTime: getTime }); this.collator = new ClockCollator({ getTargetClockTime: getTime });
this.onToggle = onToggle; this.onToggle = onToggle;
this.latency = 0.1; // fixed trigger time offset this.latency = latency; // fixed trigger time offset
this.cycle = 0; this.cycle = 0;
this.id = Math.round(Date.now() * Math.random()); this.id = Math.round(Date.now() * Math.random());
this.worker = new SharedWorker(new URL('./clockworker.js', import.meta.url)); this.worker = new SharedWorker(new URL('./clockworker.js', import.meta.url));
+4 -4
View File
@@ -1569,7 +1569,7 @@ export const func = curry((a, b) => reify(b).func(a));
/** /**
* Registers a new pattern method. The method is added to the Pattern class + the standalone function is returned from register. * Registers a new pattern method. The method is added to the Pattern class + the standalone function is returned from register.
* *
* @param {string | string[]} name name of the function, or an array of names to be used as synonyms * @param {string} name name of the function
* @param {function} func function with 1 or more params, where last is the current pattern * @param {function} func function with 1 or more params, where last is the current pattern
* @noAutocomplete * @noAutocomplete
* *
@@ -2522,7 +2522,7 @@ export const { fastchunk, fastChunk } = register(
/** /**
* Like `chunk`, but the function is applied to a looped subcycle of the source pattern. * Like `chunk`, but the function is applied to a looped subcycle of the source pattern.
* @name chunkInto * @name chunkInto
* @synonyms chunkinto * @synonym chunkinto
* @memberof Pattern * @memberof Pattern
* @example * @example
* sound("bd sd ht lt bd - cp lt").chunkInto(4, hurry(2)) * sound("bd sd ht lt bd - cp lt").chunkInto(4, hurry(2))
@@ -2535,7 +2535,7 @@ export const { chunkinto, chunkInto } = register(['chunkinto', 'chunkInto'], fun
/** /**
* Like `chunkInto`, but moves backwards through the chunks. * Like `chunkInto`, but moves backwards through the chunks.
* @name chunkBackInto * @name chunkBackInto
* @synonyms chunkbackinto * @synonym chunkbackinto
* @memberof Pattern * @memberof Pattern
* @example * @example
* sound("bd sd ht lt bd - cp lt").chunkInto(4, hurry(2)) * sound("bd sd ht lt bd - cp lt").chunkInto(4, hurry(2))
@@ -2565,7 +2565,7 @@ export const bypass = register(
* Loops the pattern inside an `offset` for `cycles`. * Loops the pattern inside an `offset` for `cycles`.
* If you think of the entire span of time in cycles as a ribbon, you can cut a single piece and loop it. * If you think of the entire span of time in cycles as a ribbon, you can cut a single piece and loop it.
* @name ribbon * @name ribbon
* @synonyms rib * @synonym rib
* @param {number} offset start point of loop in cycles * @param {number} offset start point of loop in cycles
* @param {number} cycles loop length in cycles * @param {number} cycles loop length in cycles
* @example * @example
+4 -2
View File
@@ -1,7 +1,7 @@
import { NeoCyclist } from './neocyclist.mjs'; import { NeoCyclist } from './neocyclist.mjs';
import { Cyclist } from './cyclist.mjs'; import { Cyclist } from './cyclist.mjs';
import { evaluate as _evaluate } from './evaluate.mjs'; import { evaluate as _evaluate } from './evaluate.mjs';
import { errorLogger, logger } from './logger.mjs'; import { logger } from './logger.mjs';
import { setTime } from './time.mjs'; import { setTime } from './time.mjs';
import { evalScope } from './evaluate.mjs'; import { evalScope } from './evaluate.mjs';
import { register, Pattern, isPattern, silence, stack } from './pattern.mjs'; import { register, Pattern, isPattern, silence, stack } from './pattern.mjs';
@@ -18,6 +18,7 @@ export function repl({
editPattern, editPattern,
onUpdateState, onUpdateState,
sync = false, sync = false,
latency = 0.1,
setInterval, setInterval,
clearInterval, clearInterval,
id, id,
@@ -56,6 +57,7 @@ export function repl({
setInterval, setInterval,
clearInterval, clearInterval,
beforeStart, beforeStart,
latency,
}; };
// NeoCyclist uses a shared worker to communicate between instances, which is not supported on mobile chrome // NeoCyclist uses a shared worker to communicate between instances, which is not supported on mobile chrome
@@ -256,6 +258,6 @@ export const getTrigger =
await hap.context.onTrigger(hap, getTime(), cps, t); await hap.context.onTrigger(hap, getTime(), cps, t);
} }
} catch (err) { } catch (err) {
errorLogger(err, 'getTrigger'); logger(`[cyclist] error: ${err.message}`, 'error');
} }
}; };
-1
View File
@@ -42,7 +42,6 @@ lib['%'] = pace;
lib['?'] = degradeBy; // todo: default 0.5 not working.. lib['?'] = degradeBy; // todo: default 0.5 not working..
lib[':'] = tail; lib[':'] = tail;
lib['..'] = range; lib['..'] = range;
lib['def'] = () => silence;
lib['or'] = (...children) => chooseIn(...children); // always has structure but is cyclewise.. e.g. "s oh*8.dec[.04 | .5]" lib['or'] = (...children) => chooseIn(...children); // always has structure but is cyclewise.. e.g. "s oh*8.dec[.04 | .5]"
//lib['or'] = (...children) => chooseOut(...children); // "s oh*8.dec[.04 | .5]" is better but "dec[.04 | .5].s oh*8" has no struct //lib['or'] = (...children) => chooseOut(...children); // "s oh*8.dec[.04 | .5]" is better but "dec[.04 | .5].s oh*8" has no struct
+1 -1
View File
@@ -36,7 +36,7 @@ export async function prebake() {
samples(`${ds}/tidal-drum-machines.json`), samples(`${ds}/tidal-drum-machines.json`),
samples(`${ds}/piano.json`), samples(`${ds}/piano.json`),
samples(`${ds}/Dirt-Samples.json`), samples(`${ds}/Dirt-Samples.json`),
samples(`${ds}/uzu-drumkit.json`), samples(`${ds}/EmuSP12.json`),
samples(`${ds}/vcsl.json`), samples(`${ds}/vcsl.json`),
samples(`${ds}/mridangam.json`), samples(`${ds}/mridangam.json`),
]); ]);
+3 -14
View File
@@ -1,8 +1,5 @@
import { getAudioContext } from './superdough.mjs'; import { getAudioContext } from './superdough.mjs';
import { clamp, nanFallback } from './util.mjs'; import { clamp, nanFallback } from './util.mjs';
import { getNoiseBuffer } from './noise.mjs';
export const noises = ['pink', 'white', 'brown', 'crackle'];
export function gainNode(value) { export function gainNode(value) {
const node = getAudioContext().createGain(); const node = getAudioContext().createGain();
@@ -219,17 +216,9 @@ export function webAudioTimeout(audioContext, onComplete, startTime, stopTime) {
} }
const mod = (freq, range = 1, type = 'sine') => { const mod = (freq, range = 1, type = 'sine') => {
const ctx = getAudioContext(); const ctx = getAudioContext();
let osc; const osc = ctx.createOscillator();
if (noises.includes(type)) { osc.type = type;
osc = ctx.createBufferSource(); osc.frequency.value = freq;
osc.buffer = getNoiseBuffer(type, 2);
osc.loop = true;
} else {
osc = ctx.createOscillator();
osc.type = type;
osc.frequency.value = freq;
}
osc.start(); osc.start();
const g = new GainNode(ctx, { gain: range }); const g = new GainNode(ctx, { gain: range });
osc.connect(g); // -range, range osc.connect(g); // -range, range
+1 -1
View File
@@ -4,7 +4,7 @@ import { getAudioContext } from './superdough.mjs';
let noiseCache = {}; let noiseCache = {};
// lazy generates noise buffers and keeps them forever // lazy generates noise buffers and keeps them forever
export function getNoiseBuffer(type, density) { function getNoiseBuffer(type, density) {
const ac = getAudioContext(); const ac = getAudioContext();
if (noiseCache[type]) { if (noiseCache[type]) {
return noiseCache[type]; return noiseCache[type];
+21 -78
View File
@@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
import './feedbackdelay.mjs'; import './feedbackdelay.mjs';
import './reverb.mjs'; import './reverb.mjs';
import './vowel.mjs'; import './vowel.mjs';
import { clamp, nanFallback, _mod, cycleToSeconds, secondsToCycle } from './util.mjs'; import { clamp, nanFallback, _mod, cycleToSeconds } from './util.mjs';
import workletsUrl from './worklets.mjs?audioworklet'; import workletsUrl from './worklets.mjs?audioworklet';
import { createFilter, gainNode, getCompressor, getWorklet } from './helpers.mjs'; import { createFilter, gainNode, getCompressor, getWorklet } from './helpers.mjs';
import { map } from 'nanostores'; import { map } from 'nanostores';
@@ -28,13 +28,6 @@ export function setMultiChannelOrbits(bool) {
multiChannelOrbits = bool == true; multiChannelOrbits = bool == true;
} }
function getModulationShapeInput(val) {
if (typeof val === 'number') {
return val % 5;
}
return { tri: 0, triangle: 0, sine: 1, ramp: 2, saw: 3, square: 4 }[val] ?? 0;
}
export const soundMap = map(); export const soundMap = map();
export function registerSound(key, onTrigger, data = {}) { export function registerSound(key, onTrigger, data = {}) {
@@ -343,33 +336,9 @@ function getDelay(orbit, delaytime, delayfeedback, t, channels) {
return delays[orbit]; return delays[orbit];
} }
export function getLfo(audioContext, begin, end, properties = {}) { export function getLfo(audioContext, time, end, properties = {}) {
const { shape = 0, ...props } = properties;
const { dcoffset = -0.5, depth = 1 } = properties;
const lfoprops = {
frequency: 1,
depth,
skew: 0.5,
phaseoffset: 0,
time: begin,
begin,
end,
shape: getModulationShapeInput(shape),
dcoffset,
min: dcoffset * depth,
max: dcoffset * depth + depth,
curve: 1,
...props,
};
return getWorklet(audioContext, 'lfo-processor', lfoprops);
}
export function getSyncedLfo(audioContext, time, end, cps, cycle, properties = {}) {
const frequency = cycle / cps;
return getWorklet(audioContext, 'lfo-processor', { return getWorklet(audioContext, 'lfo-processor', {
frequency, frequency: 1,
depth: 1, depth: 1,
skew: 0, skew: 0,
phaseoffset: 0, phaseoffset: 0,
@@ -492,10 +461,9 @@ function mapChannelNumbers(channels) {
return (Array.isArray(channels) ? channels : [channels]).map((ch) => ch - 1); return (Array.isArray(channels) ? channels : [channels]).map((ch) => ch - 1);
} }
export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) => { export const superdough = async (value, t, hapDuration, cps = 0.5) => {
// new: t is always expected to be the absolute target onset time // new: t is always expected to be the absolute target onset time
const ac = getAudioContext(); const ac = getAudioContext();
let { stretch } = value; let { stretch } = value;
if (stretch != null) { if (stretch != null) {
//account for phase vocoder latency //account for phase vocoder latency
@@ -521,12 +489,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
} }
// destructure // destructure
let { let {
tremolo,
tremolosync,
tremolodepth = 1,
tremoloskew,
tremolophase = 0,
tremoloshape,
s = getDefaultValue('s'), s = getDefaultValue('s'),
bank, bank,
source, source,
@@ -536,7 +498,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// filters // filters
fanchor = getDefaultValue('fanchor'), fanchor = getDefaultValue('fanchor'),
drive = 0.69, drive = 0.69,
release = 0,
// low pass // low pass
cutoff, cutoff,
lpenv, lpenv,
@@ -569,7 +530,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
phasercenter, phasercenter,
// //
coarse, coarse,
crush, crush,
shape, shape,
shapevol = getDefaultValue('shapevol'), shapevol = getDefaultValue('shapevol'),
@@ -612,11 +572,8 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
distortvol = applyGainCurve(distortvol); distortvol = applyGainCurve(distortvol);
delay = applyGainCurve(delay); delay = applyGainCurve(delay);
velocity = applyGainCurve(velocity); velocity = applyGainCurve(velocity);
tremolodepth = applyGainCurve(tremolodepth);
gain *= velocity; // velocity currently only multiplies with gain. it might do other things in the future gain *= velocity; // velocity currently only multiplies with gain. it might do other things in the future
const end = t + hapDuration;
const endWithRelease = end + release;
const chainID = Math.round(Math.random() * 1000000); const chainID = Math.round(Math.random() * 1000000);
// oldest audio nodes will be destroyed if maximum polyphony is exceeded // oldest audio nodes will be destroyed if maximum polyphony is exceeded
@@ -691,7 +648,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
lprelease, lprelease,
lpenv, lpenv,
t, t,
end, t + hapDuration,
fanchor, fanchor,
ftype, ftype,
drive, drive,
@@ -715,7 +672,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
hprelease, hprelease,
hpenv, hpenv,
t, t,
end, t + hapDuration,
fanchor, fanchor,
); );
chain.push(hp()); chain.push(hp());
@@ -726,7 +683,20 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
if (bandf !== undefined) { if (bandf !== undefined) {
let bp = () => let bp = () =>
createFilter(ac, 'bandpass', bandf, bandq, bpattack, bpdecay, bpsustain, bprelease, bpenv, t, end, fanchor); createFilter(
ac,
'bandpass',
bandf,
bandq,
bpattack,
bpdecay,
bpsustain,
bprelease,
bpenv,
t,
t + hapDuration,
fanchor,
);
chain.push(bp()); chain.push(bp());
if (ftype === '24db') { if (ftype === '24db') {
chain.push(bp()); chain.push(bp());
@@ -744,33 +714,6 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol })); shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol })); distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
if (tremolosync != null) {
tremolo = cps * tremolosync;
}
if (tremolo !== undefined) {
// Allow clipping of modulator for more dynamic possiblities, and to prevent speaker overload
// EX: a triangle waveform will clip like this /-\ when the depth is above 1
const gain = Math.max(1 - tremolodepth, 0);
const amGain = new GainNode(ac, { gain });
const time = cycle / cps;
const lfo = getLfo(ac, t, endWithRelease, {
skew: tremoloskew ?? (tremoloshape != null ? 0.5 : 1),
frequency: tremolo,
depth: tremolodepth,
time,
dcoffset: 0,
shape: tremoloshape,
phaseoffset: tremolophase,
min: 0,
max: 1,
curve: 1.5,
});
lfo.connect(amGain.gain);
chain.push(amGain);
}
compressorThreshold !== undefined && compressorThreshold !== undefined &&
chain.push( chain.push(
getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease), getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease),
@@ -784,7 +727,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
} }
// phaser // phaser
if (phaser !== undefined && phaserdepth > 0) { if (phaser !== undefined && phaserdepth > 0) {
const phaserFX = getPhaser(t, endWithRelease, phaser, phaserdepth, phasercenter, phasersweep); const phaserFX = getPhaser(t, t + hapDuration, phaser, phaserdepth, phasercenter, phasersweep);
chain.push(phaserFX); chain.push(phaserFX);
} }
+3 -83
View File
@@ -9,13 +9,12 @@ import {
getVibratoOscillator, getVibratoOscillator,
webAudioTimeout, webAudioTimeout,
getWorklet, getWorklet,
noises,
} from './helpers.mjs'; } from './helpers.mjs';
import { getNoiseMix, getNoiseOscillator } from './noise.mjs'; import { getNoiseMix, getNoiseOscillator } from './noise.mjs';
const getFrequencyFromValue = (value, defaultNote = 36) => { const getFrequencyFromValue = (value) => {
let { note, freq } = value; let { note, freq } = value;
note = note || defaultNote; note = note || 36;
if (typeof note === 'string') { if (typeof note === 'string') {
note = noteToMidi(note); // e.g. c3 => 48 note = noteToMidi(note); // e.g. c3 => 48
} }
@@ -41,17 +40,7 @@ const waveformAliases = [
['saw', 'sawtooth'], ['saw', 'sawtooth'],
['sin', 'sine'], ['sin', 'sine'],
]; ];
const noises = ['pink', 'white', 'brown', 'crackle'];
function makeSaturationCurve(amount, n_samples) {
const k = typeof amount === 'number' ? amount : 50;
const curve = new Float32Array(n_samples);
for (let i = 0; i < n_samples; i++) {
const x = (i * 2) / n_samples - 1;
curve[i] = Math.tanh(x * k);
}
return curve;
}
export function registerSynthSounds() { export function registerSynthSounds() {
[...waveforms].forEach((s) => { [...waveforms].forEach((s) => {
@@ -95,75 +84,6 @@ export function registerSynthSounds() {
{ type: 'synth', prebake: true }, { type: 'synth', prebake: true },
); );
}); });
registerSound(
'sbd',
(t, value, onended) => {
const { duration, decay = 0.5, pdecay = 0.5, penv = 36, clip } = value;
const ctx = getAudioContext();
const attackhold = 0.02;
const noiselvl = 1.2;
const noisedecay = 0.025;
const mixGain = 1;
const o = ctx.createOscillator();
o.type = 'triangle';
o.frequency.value = getFrequencyFromValue(value, 29);
o.detune.setValueAtTime(penv * 100, 0);
o.detune.setValueAtTime(penv * 100, t);
o.detune.exponentialRampToValueAtTime(0.001, t + pdecay);
const g = gainNode(1);
g.gain.setValueAtTime(1, t + attackhold);
g.gain.exponentialRampToValueAtTime(0.001, t + attackhold + decay);
o.start(t);
const noise = getNoiseOscillator('brown', t, 2);
const noiseGain = gainNode(1);
noiseGain.gain.setValueAtTime(noiselvl, t);
noiseGain.gain.exponentialRampToValueAtTime(0.001, t + noisedecay);
const sat = new WaveShaperNode(ctx);
// tri to sine diode shaper emulation
sat.curve = makeSaturationCurve(2, ctx.sampleRate);
const mix = gainNode(mixGain);
o.onended = () => {
o.disconnect();
g.disconnect();
sat.disconnect();
noise.node.disconnect();
noiseGain.disconnect();
mix.disconnect();
onended();
};
const node = o.connect(sat).connect(g).connect(mix);
noise.node.connect(noiseGain).connect(mix);
const holdEnd = t + decay;
let end = holdEnd + 0.01;
if (clip != null) {
end = Math.min(t + clip * duration, end);
}
// prevent clicking
mix.gain.setValueAtTime(mixGain, end - 0.01);
mix.gain.linearRampToValueAtTime(0, end);
o.stop(end);
noise.stop(end);
return {
node,
stop: (endTime) => {
o.stop(endTime);
},
};
},
{ type: 'synth', prebake: true },
);
registerSound( registerSound(
'supersaw', 'supersaw',
(begin, value, onended) => { (begin, value, onended) => {
-4
View File
@@ -72,7 +72,3 @@ export const getSoundIndex = (n, numSounds) => {
export function cycleToSeconds(cycle, cps) { export function cycleToSeconds(cycle, cps) {
return cycle / cps; return cycle / cps;
} }
export function secondsToCycle(t, cps) {
return t * cps;
}
+3 -17
View File
@@ -31,7 +31,7 @@ function polyBlep(phase, dt) {
return 0; return 0;
} }
} }
// The order is important for dough integration
const waveshapes = { const waveshapes = {
tri(phase, skew = 0.5) { tri(phase, skew = 0.5) {
const x = 1 - skew; const x = 1 - skew;
@@ -81,12 +81,10 @@ function getParamValue(block, param) {
} }
return param[0]; return param[0];
} }
const waveShapeNames = Object.keys(waveshapes); const waveShapeNames = Object.keys(waveshapes);
class LFOProcessor extends AudioWorkletProcessor { class LFOProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() { static get parameterDescriptors() {
return [ return [
{ name: 'begin', defaultValue: 0 },
{ name: 'time', defaultValue: 0 }, { name: 'time', defaultValue: 0 },
{ name: 'end', defaultValue: 0 }, { name: 'end', defaultValue: 0 },
{ name: 'frequency', defaultValue: 0.5 }, { name: 'frequency', defaultValue: 0.5 },
@@ -94,10 +92,7 @@ class LFOProcessor extends AudioWorkletProcessor {
{ name: 'depth', defaultValue: 1 }, { name: 'depth', defaultValue: 1 },
{ name: 'phaseoffset', defaultValue: 0 }, { name: 'phaseoffset', defaultValue: 0 },
{ name: 'shape', defaultValue: 0 }, { name: 'shape', defaultValue: 0 },
{ name: 'curve', defaultValue: 1 },
{ name: 'dcoffset', defaultValue: 0 }, { name: 'dcoffset', defaultValue: 0 },
{ name: 'min', defaultValue: 0 },
{ name: 'max', defaultValue: 1 },
]; ];
} }
@@ -114,14 +109,10 @@ class LFOProcessor extends AudioWorkletProcessor {
} }
process(inputs, outputs, parameters) { process(inputs, outputs, parameters) {
const begin = parameters['begin'][0];
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
if (currentTime >= parameters.end[0]) { if (currentTime >= parameters.end[0]) {
return false; return false;
} }
if (currentTime <= begin) {
return true;
}
const output = outputs[0]; const output = outputs[0];
const frequency = parameters['frequency'][0]; const frequency = parameters['frequency'][0];
@@ -131,11 +122,7 @@ class LFOProcessor extends AudioWorkletProcessor {
const skew = parameters['skew'][0]; const skew = parameters['skew'][0];
const phaseoffset = parameters['phaseoffset'][0]; const phaseoffset = parameters['phaseoffset'][0];
const curve = parameters['curve'][0];
const dcoffset = parameters['dcoffset'][0]; const dcoffset = parameters['dcoffset'][0];
const min = parameters['min'][0];
const max = parameters['max'][0];
const shape = waveShapeNames[parameters['shape'][0]]; const shape = waveShapeNames[parameters['shape'][0]];
const blockSize = output[0].length ?? 0; const blockSize = output[0].length ?? 0;
@@ -147,9 +134,8 @@ class LFOProcessor extends AudioWorkletProcessor {
const dt = frequency / sampleRate; const dt = frequency / sampleRate;
for (let n = 0; n < blockSize; n++) { for (let n = 0; n < blockSize; n++) {
for (let i = 0; i < output.length; i++) { for (let i = 0; i < output.length; i++) {
let modval = (waveshapes[shape](this.phase, skew) + dcoffset) * depth; const modval = (waveshapes[shape](this.phase, skew) + dcoffset) * depth;
modval = Math.pow(modval, curve); output[i][n] = modval;
output[i][n] = clamp(modval, min, max);
} }
this.incrementPhase(dt); this.incrementPhase(dt);
} }
+17 -22
View File
@@ -88,14 +88,13 @@ function scaleOffset(scale, offset, note) {
* @returns Pattern * @returns Pattern
* @memberof Pattern * @memberof Pattern
* @name transpose * @name transpose
* @synonyms trans
* @example * @example
* "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note() * "c2 c3".fast(2).transpose("<0 -2 5 3>".slow(2)).note()
* @example * @example
* "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note() * "c2 c3".fast(2).transpose("<1P -2M 4P 3m>".slow(2)).note()
*/ */
export const { transpose, trans } = register(['transpose', 'trans'], function transposeFn(intervalOrSemitones, pat) { export const transpose = register('transpose', function (intervalOrSemitones, pat) {
return pat.withHap((hap) => { return pat.withHap((hap) => {
const note = hap.value.note ?? hap.value; const note = hap.value.note ?? hap.value;
if (typeof note === 'number') { if (typeof note === 'number') {
@@ -143,7 +142,6 @@ export const { transpose, trans } = register(['transpose', 'trans'], function tr
* @name scaleTranspose * @name scaleTranspose
* @param {offset} offset number of steps inside the scale * @param {offset} offset number of steps inside the scale
* @returns Pattern * @returns Pattern
* @synonyms scaleTrans, strans
* @example * @example
* "-8 [2,4,6]" * "-8 [2,4,6]"
* .scale('C4 bebop major') * .scale('C4 bebop major')
@@ -151,25 +149,22 @@ export const { transpose, trans } = register(['transpose', 'trans'], function tr
* .note() * .note()
*/ */
export const { scaleTranspose, scaleTrans, strans } = register( export const scaleTranspose = register('scaleTranspose', function (offset /* : number | string */, pat) {
['scaleTranspose', 'scaleTrans', 'strans'], return pat.withHap((hap) => {
function (offset /* : number | string */, pat) { if (!hap.context.scale) {
return pat.withHap((hap) => { throw new Error('can only use scaleTranspose after .scale');
if (!hap.context.scale) { }
throw new Error('can only use scaleTranspose after .scale'); if (typeof hap.value === 'object')
} return hap.withValue(() => ({
if (typeof hap.value === 'object') ...hap.value,
return hap.withValue(() => ({ note: scaleOffset(hap.context.scale, Number(offset), hap.value.note),
...hap.value, }));
note: scaleOffset(hap.context.scale, Number(offset), hap.value.note), if (typeof hap.value !== 'string') {
})); throw new Error('can only use scaleTranspose with notes');
if (typeof hap.value !== 'string') { }
throw new Error('can only use scaleTranspose with notes'); return hap.withValue(() => scaleOffset(hap.context.scale, Number(offset), hap.value));
} });
return hap.withValue(() => scaleOffset(hap.context.scale, Number(offset), hap.value)); });
});
},
);
/** /**
* Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}. * Turns numbers into notes in the scale (zero indexed). Also sets scale for other scale operations, like {@link Pattern#scaleTranspose}.
+2 -2
View File
@@ -17,8 +17,8 @@ const hap2value = (hap) => {
// uses more precise, absolute t if available, see https://github.com/tidalcycles/strudel/pull/1004 // uses more precise, absolute t if available, see https://github.com/tidalcycles/strudel/pull/1004
// TODO: refactor output callbacks to eliminate deadline // TODO: refactor output callbacks to eliminate deadline
export const webaudioOutput = (hap, _deadline, hapDuration, cps, t) => { export const webaudioOutput = (hap, deadline, hapDuration, cps, t) => {
return superdough(hap2value(hap), t, hapDuration, cps, hap.whole?.begin.valueOf()); return superdough(hap2value(hap), t, hapDuration, cps);
}; };
export function webaudioRepl(options = {}) { export function webaudioRepl(options = {}) {
-552
View File
@@ -3706,144 +3706,6 @@ exports[`runs examples > example "fmsustain" example index 0 1`] = `
] ]
`; `;
exports[`runs examples > example "fmwave" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:D3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 1/16 → 1/8 | note:E3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 1/8 → 3/16 | note:F3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 3/16 → 1/4 | note:G3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 1/4 → 5/16 | note:D3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 5/16 → 3/8 | note:E3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 3/8 → 7/16 | note:F3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 7/16 → 1/2 | note:G3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 1/2 → 9/16 | note:D3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 9/16 → 5/8 | note:E3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 5/8 → 11/16 | note:F3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 11/16 → 3/4 | note:G3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 3/4 → 13/16 | note:D3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 13/16 → 7/8 | note:E3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 7/8 → 15/16 | note:F3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 15/16 → 1/1 | note:G3 s:sine fmwave:sine fmi:4 fmh:2.01 ]",
"[ 1/1 → 17/16 | note:D3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 17/16 → 9/8 | note:E3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 9/8 → 19/16 | note:F3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 19/16 → 5/4 | note:G3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 5/4 → 21/16 | note:D3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 21/16 → 11/8 | note:E3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 11/8 → 23/16 | note:F3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 23/16 → 3/2 | note:G3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 3/2 → 25/16 | note:D3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 25/16 → 13/8 | note:E3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 13/8 → 27/16 | note:F3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 27/16 → 7/4 | note:G3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 7/4 → 29/16 | note:D3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 29/16 → 15/8 | note:E3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 15/8 → 31/16 | note:F3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 31/16 → 2/1 | note:G3 s:sine fmwave:square fmi:4 fmh:2.01 ]",
"[ 2/1 → 33/16 | note:D3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 33/16 → 17/8 | note:E3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 17/8 → 35/16 | note:F3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 35/16 → 9/4 | note:G3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 9/4 → 37/16 | note:D3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 37/16 → 19/8 | note:E3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 19/8 → 39/16 | note:F3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 39/16 → 5/2 | note:G3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 5/2 → 41/16 | note:D3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 41/16 → 21/8 | note:E3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 21/8 → 43/16 | note:F3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 43/16 → 11/4 | note:G3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 11/4 → 45/16 | note:D3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 45/16 → 23/8 | note:E3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 23/8 → 47/16 | note:F3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 47/16 → 3/1 | note:G3 s:sine fmwave:sawtooth fmi:4 fmh:2.01 ]",
"[ 3/1 → 49/16 | note:D3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 49/16 → 25/8 | note:E3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 25/8 → 51/16 | note:F3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 51/16 → 13/4 | note:G3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 13/4 → 53/16 | note:D3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 53/16 → 27/8 | note:E3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 27/8 → 55/16 | note:F3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 55/16 → 7/2 | note:G3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 7/2 → 57/16 | note:D3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 57/16 → 29/8 | note:E3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 29/8 → 59/16 | note:F3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 59/16 → 15/4 | note:G3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 15/4 → 61/16 | note:D3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 61/16 → 31/8 | note:E3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 31/8 → 63/16 | note:F3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
"[ 63/16 → 4/1 | note:G3 s:sine fmwave:crackle fmi:4 fmh:2.01 ]",
]
`;
exports[`runs examples > example "fmwave" example index 1 1`] = `
[
"[ 0/1 → 1/16 | note:50 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 1/16 → 1/8 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 1/8 → 3/16 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 3/16 → 1/4 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 1/4 → 5/16 | note:50 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 5/16 → 3/8 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 3/8 → 7/16 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 7/16 → 1/2 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 1/2 → 9/16 | note:50 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 9/16 → 5/8 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 5/8 → 11/16 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 11/16 → 3/4 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 3/4 → 13/16 | note:50 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 13/16 → 7/8 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 7/8 → 15/16 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 15/16 → 1/1 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 1/1 → 17/16 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 17/16 → 9/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 9/8 → 19/16 | note:64 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 19/16 → 5/4 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 5/4 → 21/16 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 21/16 → 11/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 11/8 → 23/16 | note:64 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 23/16 → 3/2 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 3/2 → 25/16 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 25/16 → 13/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 13/8 → 27/16 | note:64 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 27/16 → 7/4 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 7/4 → 29/16 | note:57 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 29/16 → 15/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 15/8 → 31/16 | note:64 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 31/16 → 2/1 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 2/1 → 33/16 | note:53 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 33/16 → 17/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 17/8 → 35/16 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 35/16 → 9/4 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 9/4 → 37/16 | note:53 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 37/16 → 19/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 19/8 → 39/16 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 39/16 → 5/2 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 5/2 → 41/16 | note:53 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 41/16 → 21/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 21/8 → 43/16 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 43/16 → 11/4 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 11/4 → 45/16 | note:53 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 45/16 → 23/8 | note:60 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 23/8 → 47/16 | note:65 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 47/16 → 3/1 | note:69 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 3/1 → 49/16 | note:55 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 49/16 → 25/8 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 25/8 → 51/16 | note:67 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 51/16 → 13/4 | note:71 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 13/4 → 53/16 | note:55 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 53/16 → 27/8 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 27/8 → 55/16 | note:67 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 55/16 → 7/2 | note:71 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 7/2 → 57/16 | note:55 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 57/16 → 29/8 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 29/8 → 59/16 | note:67 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 59/16 → 15/4 | note:71 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 15/4 → 61/16 | note:55 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 61/16 → 31/8 | note:62 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 31/8 → 63/16 | note:67 s:sawtooth fmwave:brown fmi:0.6 ]",
"[ 63/16 → 4/1 | note:71 s:sawtooth fmwave:brown fmi:0.6 ]",
]
`;
exports[`runs examples > example "focus" example index 0 1`] = ` exports[`runs examples > example "focus" example index 0 1`] = `
[ [
"[ 0/1 → 1/8 | s:sd ]", "[ 0/1 → 1/8 | s:sd ]",
@@ -10248,420 +10110,6 @@ exports[`runs examples > example "transpose" example index 1 1`] = `
] ]
`; `;
exports[`runs examples > example "tremolo" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 1/16 → 1/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 1/8 → 3/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 3/16 → 1/4 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 1/4 → 5/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 5/16 → 3/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 3/8 → 7/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 7/16 → 1/2 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 1/2 → 9/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 9/16 → 5/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 5/8 → 11/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 11/16 → 3/4 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 3/4 → 13/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 13/16 → 7/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 7/8 → 15/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 15/16 → 1/1 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 1/1 → 17/16 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 17/16 → 9/8 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 9/8 → 19/16 | note:d# s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 19/16 → 5/4 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 5/4 → 21/16 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 21/16 → 11/8 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 11/8 → 23/16 | note:d# s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 23/16 → 3/2 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 3/2 → 25/16 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 25/16 → 13/8 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 13/8 → 27/16 | note:d# s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 27/16 → 7/4 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 7/4 → 29/16 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 29/16 → 15/8 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 15/8 → 31/16 | note:d# s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 31/16 → 2/1 | note:d s:supersaw tremolo:2 tremoloskew:0.5 ]",
"[ 2/1 → 33/16 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 33/16 → 17/8 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 17/8 → 35/16 | note:d# s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 35/16 → 9/4 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 9/4 → 37/16 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 37/16 → 19/8 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 19/8 → 39/16 | note:d# s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 39/16 → 5/2 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 5/2 → 41/16 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 41/16 → 21/8 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 21/8 → 43/16 | note:d# s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 43/16 → 11/4 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 11/4 → 45/16 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 45/16 → 23/8 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 23/8 → 47/16 | note:d# s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 47/16 → 3/1 | note:d s:supersaw tremolo:100 tremoloskew:0.5 ]",
"[ 3/1 → 49/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 49/16 → 25/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 25/8 → 51/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 51/16 → 13/4 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 13/4 → 53/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 53/16 → 27/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 27/8 → 55/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 55/16 → 7/2 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 7/2 → 57/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 57/16 → 29/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 29/8 → 59/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 59/16 → 15/4 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 15/4 → 61/16 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 61/16 → 31/8 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 31/8 → 63/16 | note:d# s:supersaw tremolo:3 tremoloskew:0.5 ]",
"[ 63/16 → 4/1 | note:d s:supersaw tremolo:3 tremoloskew:0.5 ]",
]
`;
exports[`runs examples > example "tremolodepth" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 1/16 → 1/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 1/8 → 3/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 3/16 → 1/4 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 1/4 → 5/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 5/16 → 3/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 3/8 → 7/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 7/16 → 1/2 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 1/2 → 9/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 9/16 → 5/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 5/8 → 11/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 11/16 → 3/4 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 3/4 → 13/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 13/16 → 7/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 7/8 → 15/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 15/16 → 1/1 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 1/1 → 17/16 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 17/16 → 9/8 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 9/8 → 19/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 19/16 → 5/4 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 5/4 → 21/16 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 21/16 → 11/8 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 11/8 → 23/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 23/16 → 3/2 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 3/2 → 25/16 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 25/16 → 13/8 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 13/8 → 27/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 27/16 → 7/4 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 7/4 → 29/16 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 29/16 → 15/8 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 15/8 → 31/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 31/16 → 2/1 | note:a1 s:pulse tremolosync:4 tremolodepth:2 ]",
"[ 2/1 → 33/16 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 33/16 → 17/8 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 17/8 → 35/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 35/16 → 9/4 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 9/4 → 37/16 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 37/16 → 19/8 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 19/8 → 39/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 39/16 → 5/2 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 5/2 → 41/16 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 41/16 → 21/8 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 21/8 → 43/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 43/16 → 11/4 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 11/4 → 45/16 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 45/16 → 23/8 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 23/8 → 47/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 47/16 → 3/1 | note:a1 s:pulse tremolosync:4 tremolodepth:0.7 ]",
"[ 3/1 → 49/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 49/16 → 25/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 25/8 → 51/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 51/16 → 13/4 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 13/4 → 53/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 53/16 → 27/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 27/8 → 55/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 55/16 → 7/2 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 7/2 → 57/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 57/16 → 29/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 29/8 → 59/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 59/16 → 15/4 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 15/4 → 61/16 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 61/16 → 31/8 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 31/8 → 63/16 | note:a#1 s:pulse tremolosync:4 tremolodepth:1 ]",
"[ 63/16 → 4/1 | note:a1 s:pulse tremolosync:4 tremolodepth:1 ]",
]
`;
exports[`runs examples > example "tremolophase" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 1/16 → 1/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 1/8 → 3/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 3/16 → 1/4 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 1/4 → 5/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 5/16 → 3/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 3/8 → 7/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 7/16 → 1/2 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 1/2 → 9/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 9/16 → 5/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 5/8 → 11/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 11/16 → 3/4 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 3/4 → 13/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 13/16 → 7/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 7/8 → 15/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 15/16 → 1/1 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 1/1 → 17/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 17/16 → 9/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 9/8 → 19/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 19/16 → 5/4 | note:e s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 5/4 → 21/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 21/16 → 11/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 11/8 → 23/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 23/16 → 3/2 | note:e s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 3/2 → 25/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 25/16 → 13/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 13/8 → 27/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 27/16 → 7/4 | note:e s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 7/4 → 29/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 29/16 → 15/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 15/8 → 31/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 31/16 → 2/1 | note:e s:sawtooth tremolosync:4 tremolophase:0.25 ]",
"[ 2/1 → 33/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 33/16 → 17/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 17/8 → 35/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 35/16 → 9/4 | note:e s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 9/4 → 37/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 37/16 → 19/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 19/8 → 39/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 39/16 → 5/2 | note:e s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 5/2 → 41/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 41/16 → 21/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 21/8 → 43/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 43/16 → 11/4 | note:e s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 11/4 → 45/16 | note:f s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 45/16 → 23/8 | note:a s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 23/8 → 47/16 | note:c s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 47/16 → 3/1 | note:e s:sawtooth tremolosync:4 tremolophase:0.66 ]",
"[ 3/1 → 49/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 49/16 → 25/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 25/8 → 51/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 51/16 → 13/4 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 13/4 → 53/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 53/16 → 27/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 27/8 → 55/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 55/16 → 7/2 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 7/2 → 57/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 57/16 → 29/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 29/8 → 59/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 59/16 → 15/4 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 15/4 → 61/16 | note:f s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 61/16 → 31/8 | note:a s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 31/8 → 63/16 | note:c s:sawtooth tremolosync:4 tremolophase:0 ]",
"[ 63/16 → 4/1 | note:e s:sawtooth tremolosync:4 tremolophase:0 ]",
]
`;
exports[`runs examples > example "tremoloshape" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 1/16 → 1/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 1/8 → 3/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 3/16 → 1/4 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 1/4 → 5/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 5/16 → 3/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 3/8 → 7/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 7/16 → 1/2 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 1/2 → 9/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 9/16 → 5/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 5/8 → 11/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 11/16 → 3/4 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 3/4 → 13/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 13/16 → 7/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 7/8 → 15/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 15/16 → 1/1 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 1/1 → 17/16 | note:f tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 17/16 → 9/8 | note:g tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 9/8 → 19/16 | note:c tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 19/16 → 5/4 | note:d tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 5/4 → 21/16 | note:f tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 21/16 → 11/8 | note:g tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 11/8 → 23/16 | note:c tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 23/16 → 3/2 | note:d tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 3/2 → 25/16 | note:f tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 25/16 → 13/8 | note:g tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 13/8 → 27/16 | note:c tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 27/16 → 7/4 | note:d tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 7/4 → 29/16 | note:f tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 29/16 → 15/8 | note:g tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 15/8 → 31/16 | note:c tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 31/16 → 2/1 | note:d tremolosync:4 tremoloshape:tri s:sawtooth ]",
"[ 2/1 → 33/16 | note:f tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 33/16 → 17/8 | note:g tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 17/8 → 35/16 | note:c tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 35/16 → 9/4 | note:d tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 9/4 → 37/16 | note:f tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 37/16 → 19/8 | note:g tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 19/8 → 39/16 | note:c tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 39/16 → 5/2 | note:d tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 5/2 → 41/16 | note:f tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 41/16 → 21/8 | note:g tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 21/8 → 43/16 | note:c tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 43/16 → 11/4 | note:d tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 11/4 → 45/16 | note:f tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 45/16 → 23/8 | note:g tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 23/8 → 47/16 | note:c tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 47/16 → 3/1 | note:d tremolosync:4 tremoloshape:square s:sawtooth ]",
"[ 3/1 → 49/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 49/16 → 25/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 25/8 → 51/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 51/16 → 13/4 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 13/4 → 53/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 53/16 → 27/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 27/8 → 55/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 55/16 → 7/2 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 7/2 → 57/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 57/16 → 29/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 29/8 → 59/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 59/16 → 15/4 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 15/4 → 61/16 | note:f tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 61/16 → 31/8 | note:g tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 31/8 → 63/16 | note:c tremolosync:4 tremoloshape:sine s:sawtooth ]",
"[ 63/16 → 4/1 | note:d tremolosync:4 tremoloshape:sine s:sawtooth ]",
]
`;
exports[`runs examples > example "tremoloskew" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 1/16 → 1/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 1/8 → 3/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 3/16 → 1/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 1/4 → 5/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 5/16 → 3/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 3/8 → 7/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 7/16 → 1/2 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 1/2 → 9/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 9/16 → 5/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 5/8 → 11/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 11/16 → 3/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 3/4 → 13/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 13/16 → 7/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 7/8 → 15/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 15/16 → 1/1 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 1/1 → 17/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 17/16 → 9/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 9/8 → 19/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 19/16 → 5/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 5/4 → 21/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 21/16 → 11/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 11/8 → 23/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 23/16 → 3/2 | note:e s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 3/2 → 25/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 25/16 → 13/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 13/8 → 27/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 27/16 → 7/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 7/4 → 29/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 29/16 → 15/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 15/8 → 31/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 31/16 → 2/1 | note:e s:sawtooth tremolosync:4 tremoloskew:0 ]",
"[ 2/1 → 33/16 | note:f s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 33/16 → 17/8 | note:a s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 17/8 → 35/16 | note:c s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 35/16 → 9/4 | note:e s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 9/4 → 37/16 | note:f s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 37/16 → 19/8 | note:a s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 19/8 → 39/16 | note:c s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 39/16 → 5/2 | note:e s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 5/2 → 41/16 | note:f s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 41/16 → 21/8 | note:a s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 21/8 → 43/16 | note:c s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 43/16 → 11/4 | note:e s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 11/4 → 45/16 | note:f s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 45/16 → 23/8 | note:a s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 23/8 → 47/16 | note:c s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 47/16 → 3/1 | note:e s:sawtooth tremolosync:4 tremoloskew:1 ]",
"[ 3/1 → 49/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 49/16 → 25/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 25/8 → 51/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 51/16 → 13/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 13/4 → 53/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 53/16 → 27/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 27/8 → 55/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 55/16 → 7/2 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 7/2 → 57/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 57/16 → 29/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 29/8 → 59/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 59/16 → 15/4 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 15/4 → 61/16 | note:f s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 61/16 → 31/8 | note:a s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 31/8 → 63/16 | note:c s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
"[ 63/16 → 4/1 | note:e s:sawtooth tremolosync:4 tremoloskew:0.5 ]",
]
`;
exports[`runs examples > example "tremolosync" example index 0 1`] = `
[
"[ 0/1 → 1/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 1/16 → 1/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 1/8 → 3/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 3/16 → 1/4 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 1/4 → 5/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 5/16 → 3/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 3/8 → 7/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 7/16 → 1/2 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 1/2 → 9/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 9/16 → 5/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 5/8 → 11/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 11/16 → 3/4 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 3/4 → 13/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 13/16 → 7/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 7/8 → 15/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 15/16 → 1/1 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 1/1 → 17/16 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 17/16 → 9/8 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 9/8 → 19/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 19/16 → 5/4 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 5/4 → 21/16 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 21/16 → 11/8 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 11/8 → 23/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 23/16 → 3/2 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 3/2 → 25/16 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 25/16 → 13/8 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 13/8 → 27/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 27/16 → 7/4 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 7/4 → 29/16 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 29/16 → 15/8 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 15/8 → 31/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 31/16 → 2/1 | note:d s:supersaw tremolosync:4 tremoloskew:0.5 ]",
"[ 2/1 → 33/16 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 33/16 → 17/8 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 17/8 → 35/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 35/16 → 9/4 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 9/4 → 37/16 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 37/16 → 19/8 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 19/8 → 39/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 39/16 → 5/2 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 5/2 → 41/16 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 41/16 → 21/8 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 21/8 → 43/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 43/16 → 11/4 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 11/4 → 45/16 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 45/16 → 23/8 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 23/8 → 47/16 | note:d# s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 47/16 → 3/1 | note:d s:supersaw tremolosync:4 tremoloskew:0 ]",
"[ 3/1 → 49/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 49/16 → 25/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 25/8 → 51/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 51/16 → 13/4 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 13/4 → 53/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 53/16 → 27/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 27/8 → 55/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 55/16 → 7/2 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 7/2 → 57/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 57/16 → 29/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 29/8 → 59/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 59/16 → 15/4 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 15/4 → 61/16 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 61/16 → 31/8 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 31/8 → 63/16 | note:d# s:supersaw tremolosync:4 tremoloskew:1 ]",
"[ 63/16 → 4/1 | note:d s:supersaw tremolosync:4 tremoloskew:1 ]",
]
`;
exports[`runs examples > example "tri" example index 0 1`] = ` exports[`runs examples > example "tri" example index 0 1`] = `
[ [
"[ 0/1 → 1/8 | note:C3 ]", "[ 0/1 → 1/8 | note:C3 ]",
+17
View File
@@ -0,0 +1,17 @@
{
"_base": "https://raw.githubusercontent.com/ritchse/tidal-drum-machines/main/machines/EmuSP12/",
"bd": ["emusp12-bd/Bassdrum-01.wav","emusp12-bd/Bassdrum-02.wav","emusp12-bd/Bassdrum-03.wav","emusp12-bd/Bassdrum-04.wav","emusp12-bd/Bassdrum-05.wav","emusp12-bd/Bassdrum-06.wav","emusp12-bd/Bassdrum-07.wav","emusp12-bd/Bassdrum-08.wav","emusp12-bd/Bassdrum-09.wav","emusp12-bd/Bassdrum-10.wav","emusp12-bd/Bassdrum-11.wav","emusp12-bd/Bassdrum-12.wav","emusp12-bd/Bassdrum-13.wav","emusp12-bd/Bassdrum-14.wav"],
"cb": ["emusp12-cb/Cowbell.wav"],
"cp": ["emusp12-cp/Clap.wav"],
"cr": ["emusp12-cr/Crash.wav"],
"hh": ["emusp12-hh/Hat Closed-01.wav","emusp12-hh/Hat Closed-02.wav"],
"ht": ["emusp12-ht/Tom H-01.wav","emusp12-ht/Tom H-02.wav","emusp12-ht/Tom H-03.wav","emusp12-ht/Tom H-04.wav","emusp12-ht/Tom H-05.wav","emusp12-ht/Tom H-06.wav"],
"lt": ["emusp12-lt/Tom L-01.wav","emusp12-lt/Tom L-02.wav","emusp12-lt/Tom L-03.wav","emusp12-lt/Tom L-04.wav","emusp12-lt/Tom L-05.wav","emusp12-lt/Tom L-06.wav"],
"misc": ["emusp12-misc/Metal-01.wav","emusp12-misc/Metal-02.wav","emusp12-misc/Metal-03.wav","emusp12-misc/Scratch.wav","emusp12-misc/Shot-01.wav","emusp12-misc/Shot-02.wav","emusp12-misc/Shot-03.wav"],
"mt": ["emusp12-mt/Tom M-01.wav","emusp12-mt/Tom M-02.wav","emusp12-mt/Tom M-03.wav","emusp12-mt/Tom M-05.wav"],
"oh": ["emusp12-oh/Hhopen1.wav"],
"perc": ["emusp12-perc/Blow1.wav"],
"rd": ["emusp12-rd/Ride.wav"],
"rim": ["emusp12-rim/zRim Shot-01.wav","emusp12-rim/zRim Shot-02.wav"],
"sd": ["emusp12-sd/Snaredrum-01.wav","emusp12-sd/Snaredrum-02.wav","emusp12-sd/Snaredrum-03.wav","emusp12-sd/Snaredrum-04.wav","emusp12-sd/Snaredrum-05.wav","emusp12-sd/Snaredrum-06.wav","emusp12-sd/Snaredrum-07.wav","emusp12-sd/Snaredrum-08.wav","emusp12-sd/Snaredrum-09.wav","emusp12-sd/Snaredrum-10.wav","emusp12-sd/Snaredrum-11.wav","emusp12-sd/Snaredrum-12.wav","emusp12-sd/Snaredrum-13.wav","emusp12-sd/Snaredrum-14.wav","emusp12-sd/Snaredrum-15.wav","emusp12-sd/Snaredrum-16.wav","emusp12-sd/Snaredrum-17.wav","emusp12-sd/Snaredrum-18.wav","emusp12-sd/Snaredrum-19.wav","emusp12-sd/Snaredrum-20.wav","emusp12-sd/Snaredrum-21.wav"]
}
-76
View File
@@ -1,76 +0,0 @@
{
"_base": "https://raw.githubusercontent.com/tidalcycles/uzu-drumkit/main/",
"bd": [
"bd/10_bd_switchangel.wav",
"bd/11_bd_mot4i.wav",
"bd/12_bd_mot4i.wav",
"bd/13_bd_mot4i.wav",
"bd/14_bd_switchangel.wav",
"bd/15_bd_switchangel.wav",
"bd/16_bd_switchangel.wav",
"bd/17_bd_switchangel.wav"
],
"brk": [
"brk/10_break_amen_pprocessed.wav"
],
"cb": [
"cb/10_perc_switchangel.wav"
],
"cp": [
"cp/10_cp_switchangel.wav",
"cp/11_cp_mot4i.wav"
],
"cr": [
"cr/10_cr_switchangel.wav",
"cr/11_cr_mot4i.wav"
],
"hh": [
"hh/10_hh_switchangel.wav",
"hh/11_hh_mot4i.wav",
"hh/12_hh_switchangel.wav",
"hh/13_hh_switchangel.wav",
"hh/14_hh_mot4i.wav"
],
"ht": [
"ht/10_ht_mot4i.wav"
],
"lt": [
"lt/10_lt_mot4i.wav"
],
"misc": [
"misc/10_misc_switchangel_ludens.wav",
"misc/11_misc_switchangel_ludens.wav",
"misc/12_misc_switchangel_ludens.wav",
"misc/13_misc_switchangel_ludens.wav",
"misc/14_misc_switchangel_ludens.wav"
],
"mt": [
"mt/10_mt_mot4i.wav"
],
"oh": [
"oh/10_oh_switchangel.wav",
"oh/11_oh_switchangel.wav",
"oh/12_oh_switchangel.wav",
"oh/13_oh_switchangel.wav"
],
"rd": [
"rd/10_rd_switchangel.wav"
],
"rim": [
"rim/10_rim_switchangel.wav",
"rim/11_rim_switch_angel.wav"
],
"sd": [
"sd/10_sd_switchangel-bounce-2.wav",
"sd/11_sd_switchangel_3.wav",
"sd/12_sd_switchangel_2.wav",
"sd/13_sd_switchangel_2.wav",
"sd/14_sd.wav"
],
"sh": [
"sh/10_sh_switchangel.wav"
],
"tb": [
"tb/10_tb.wav"
]
}
-28
View File
@@ -57,34 +57,6 @@ Each filter has 2 parameters:
<JsDoc client:idle name="vowel" h={0} /> <JsDoc client:idle name="vowel" h={0} />
# Amplitude Modulation
Amplitude modulation changes the amplitude (gain) periodically over time.
## am
<JsDoc client:idle name="am" h={0} />
## tremolosync
<JsDoc client:idle name="tremolosync" h={0} />
## tremolodepth
<JsDoc client:idle name="tremolodepth" h={0} />
## tremoloskew
<JsDoc client:idle name="tremoloskew" h={0} />
## tremolophase
<JsDoc client:idle name="tremolophase" h={0} />
## tremoloshape
<JsDoc client:idle name="tremoloshape" h={0} />
# Amplitude Envelope # Amplitude Envelope
The amplitude [envelope](<https://en.wikipedia.org/wiki/Envelope_(music)>) controls the dynamic contour of a sound. The amplitude [envelope](<https://en.wikipedia.org/wiki/Envelope_(music)>) controls the dynamic contour of a sound.
@@ -176,16 +176,3 @@ $ chord <Dm9!3 Db7> # voicing
/> />
The `$` sign is an alias for `,` so it will create a stack behind the scenes. The `$` sign is an alias for `,` so it will create a stack behind the scenes.
## variables
using the `def` keyword, you can define variables:
<MiniRepl
client:idle
mondo
tune={`
$ def melody [0 1 2 3]
$ n melody # scale C:minor
`}
/>
@@ -125,7 +125,7 @@ function UserPatterns({ context }) {
style={{ display: 'none' }} style={{ display: 'none' }}
type="file" type="file"
multiple multiple
accept="text/plain,text/x-markdown,application/json" accept="text/plain,application/json"
onChange={(e) => importPatterns(e.target.files)} onChange={(e) => importPatterns(e.target.files)}
/> />
import import
@@ -108,6 +108,7 @@ export function SettingsTab({ started }) {
audioEngineTarget, audioEngineTarget,
togglePanelTrigger, togglePanelTrigger,
maxPolyphony, maxPolyphony,
latency,
multiChannelOrbits, multiChannelOrbits,
isTabIndentationEnabled, isTabIndentationEnabled,
isMultiCursorEnabled, isMultiCursorEnabled,
@@ -165,6 +166,24 @@ export function SettingsTab({ started }) {
value={maxPolyphony ?? ''} value={maxPolyphony ?? ''}
/> />
</FormItem> </FormItem>
<FormItem label="Latency">
<Textbox
min={0}
max={Infinity}
onBlur={(e) => {
let v = parseFloat(e.target.value);
v = isNaN(v) ? 0.1 : v;
settingsMap.setKey('latency', v);
}}
onChange={(v) => {
v = parseFloat(v);
settingsMap.setKey('latency', isNaN(v) ? undefined : v);
}}
type="number"
placeholder=""
value={latency ?? 0.1}
/>
</FormItem>
<FormItem> <FormItem>
<Checkbox <Checkbox
label="Multi Channel Orbits" label="Multi Channel Orbits"
+1 -4
View File
@@ -28,10 +28,7 @@ export async function prebake() {
prebake: true, prebake: true,
tag: 'drum-machines', tag: 'drum-machines',
}), }),
samples(`${baseNoTrailing}/uzu-drumkit.json`, undefined, { samples(`${baseNoTrailing}/EmuSP12.json`, undefined, { prebake: true, tag: 'drum-machines' }),
prebake: true,
tag: 'drum-machines',
}),
samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }), samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
samples( samples(
{ {
+2 -1
View File
@@ -37,7 +37,7 @@ import './Repl.css';
import { setInterval, clearInterval } from 'worker-timers'; import { setInterval, clearInterval } from 'worker-timers';
import { getMetadata } from '../metadata_parser'; import { getMetadata } from '../metadata_parser';
const { latestCode, maxPolyphony, audioDeviceName, multiChannelOrbits } = settingsMap.get(); const { latestCode, maxPolyphony, audioDeviceName, multiChannelOrbits, latency } = settingsMap.get();
let modulesLoading, presets, drawContext, clearCanvas, audioReady; let modulesLoading, presets, drawContext, clearCanvas, audioReady;
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
@@ -73,6 +73,7 @@ export function useReplContext() {
const drawContext = getDrawContext(); const drawContext = getDrawContext();
const editor = new StrudelMirror({ const editor = new StrudelMirror({
sync: isSyncEnabled, sync: isSyncEnabled,
latency,
defaultOutput, defaultOutput,
getTime, getTime,
setInterval, setInterval,
+1 -1
View File
@@ -197,7 +197,7 @@ export async function importPatterns(fileList) {
if (file.type === 'application/json') { if (file.type === 'application/json') {
const userPatterns = userPattern.getAll(); const userPatterns = userPattern.getAll();
setUserPatterns({ ...userPatterns, ...parseJSON(content) }); setUserPatterns({ ...userPatterns, ...parseJSON(content) });
} else if (['text/x-markdown', 'text/plain'].includes(file.type)) { } else if (file.type === 'text/plain') {
const id = file.name.replace(/\.[^/.]+$/, ''); const id = file.name.replace(/\.[^/.]+$/, '');
userPattern.update(id, { code: content }); userPattern.update(id, { code: content });
} }