Merge branch 'main' into glossing/wavetable-synth
This commit is contained in:
commit
5838ade740
11 changed files with 359 additions and 78 deletions
|
|
@ -192,7 +192,7 @@ export const { wtPosSkew } = registerControl('wtPosSkew');
|
||||||
* s("basique").bank("wt_digital").seg(8).note("F1").wtWarp("0 0.25 0.5 0.75 1")
|
* s("basique").bank("wt_digital").seg(8).note("F1").wtWarp("0 0.25 0.5 0.75 1")
|
||||||
* .wtWarpMode("spin")
|
* .wtWarpMode("spin")
|
||||||
*/
|
*/
|
||||||
export const { wtWarp, wavetableWarp } = registerControl('wtWarp', 'wavetableWarp')
|
export const { wtWarp, wavetableWarp } = registerControl('wtWarp', 'wavetableWarp');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attack time of the wavetable oscillator's warp envelope
|
* Attack time of the wavetable oscillator's warp envelope
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ function getModulationShapeInput(val) {
|
||||||
export function getLfo(audioContext, begin, end, properties = {}) {
|
export function getLfo(audioContext, begin, end, properties = {}) {
|
||||||
const { shape = 0, ...props } = properties;
|
const { shape = 0, ...props } = properties;
|
||||||
const { dcoffset = -0.5, depth = 1 } = properties;
|
const { dcoffset = -0.5, depth = 1 } = properties;
|
||||||
debugger;
|
|
||||||
const lfoprops = {
|
const lfoprops = {
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
depth,
|
depth,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { noteToMidi, valueToMidi, getSoundIndex } from './util.mjs';
|
import { noteToMidi, valueToMidi, getSoundIndex, getCommonSampleInfo } from './util.mjs';
|
||||||
import { getAudioContext, registerSound } from './index.mjs';
|
import { getAudioContext, registerSound, registerWaveTable } from './index.mjs';
|
||||||
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
||||||
import { logger } from './logger.mjs';
|
import { logger } from './logger.mjs';
|
||||||
|
|
||||||
|
|
@ -22,39 +22,16 @@ function humanFileSize(bytes, si) {
|
||||||
return bytes.toFixed(1) + ' ' + units[u];
|
return bytes.toFixed(1) + ' ' + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
// deduces relevant info for sample loading from hap.value and sample definition
|
|
||||||
// it encapsulates the core sampler logic into a pure and synchronous function
|
|
||||||
// hapValue: Hap.value, bank: sample bank definition for sound "s" (values in strudel.json format)
|
|
||||||
export function getSampleInfo(hapValue, bank) {
|
export function getSampleInfo(hapValue, bank) {
|
||||||
const { s, n = 0, speed = 1.0 } = hapValue;
|
const { speed = 1.0 } = hapValue;
|
||||||
let midi = valueToMidi(hapValue, 36);
|
const { transpose, url, index, midi, label } = getCommonSampleInfo(hapValue, bank);
|
||||||
let transpose = midi - 36; // C3 is middle C;
|
|
||||||
let sampleUrl;
|
|
||||||
let index = 0;
|
|
||||||
if (Array.isArray(bank)) {
|
|
||||||
index = getSoundIndex(n, bank.length);
|
|
||||||
sampleUrl = bank[index];
|
|
||||||
} else {
|
|
||||||
const midiDiff = (noteA) => noteToMidi(noteA) - midi;
|
|
||||||
// object format will expect keys as notes
|
|
||||||
const closest = Object.keys(bank)
|
|
||||||
.filter((k) => !k.startsWith('_'))
|
|
||||||
.reduce(
|
|
||||||
(closest, key, j) => (!closest || Math.abs(midiDiff(key)) < Math.abs(midiDiff(closest)) ? key : closest),
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
transpose = -midiDiff(closest); // semitones to repitch
|
|
||||||
index = getSoundIndex(n, bank[closest].length);
|
|
||||||
sampleUrl = bank[closest][index];
|
|
||||||
}
|
|
||||||
const label = `${s}:${index}`;
|
|
||||||
let playbackRate = Math.abs(speed) * Math.pow(2, transpose / 12);
|
let playbackRate = Math.abs(speed) * Math.pow(2, transpose / 12);
|
||||||
return { transpose, sampleUrl, index, midi, label, playbackRate };
|
return { transpose, url, index, midi, label, playbackRate };
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes hapValue and returns buffer + playbackRate.
|
// takes hapValue and returns buffer + playbackRate.
|
||||||
export const getSampleBuffer = async (hapValue, bank, resolveUrl) => {
|
export const getSampleBuffer = async (hapValue, bank, resolveUrl) => {
|
||||||
let { sampleUrl, label, playbackRate } = getSampleInfo(hapValue, bank);
|
let { url: sampleUrl, label, playbackRate } = getSampleInfo(hapValue, bank);
|
||||||
if (resolveUrl) {
|
if (resolveUrl) {
|
||||||
sampleUrl = await resolveUrl(sampleUrl);
|
sampleUrl = await resolveUrl(sampleUrl);
|
||||||
}
|
}
|
||||||
|
|
@ -79,14 +56,14 @@ export const getSampleBufferSource = async (hapValue, bank, resolveUrl) => {
|
||||||
bufferSource.buffer = buffer;
|
bufferSource.buffer = buffer;
|
||||||
bufferSource.playbackRate.value = playbackRate;
|
bufferSource.playbackRate.value = playbackRate;
|
||||||
|
|
||||||
const { s, loopBegin = 0, loopEnd = 1, begin = 0, end = 1 } = hapValue;
|
const { loopBegin = 0, loopEnd = 1, begin = 0, end = 1 } = hapValue;
|
||||||
|
|
||||||
// "The computation of the offset into the sound is performed using the sound buffer's natural sample rate,
|
// "The computation of the offset into the sound is performed using the sound buffer's natural sample rate,
|
||||||
// rather than the current playback rate, so even if the sound is playing at twice its normal speed,
|
// rather than the current playback rate, so even if the sound is playing at twice its normal speed,
|
||||||
// the midway point through a 10-second audio buffer is still 5."
|
// the midway point through a 10-second audio buffer is still 5."
|
||||||
const offset = begin * bufferSource.buffer.duration;
|
const offset = begin * bufferSource.buffer.duration;
|
||||||
|
|
||||||
const loop = s.startsWith('wt_') ? 1 : hapValue.loop;
|
const loop = hapValue.loop;
|
||||||
if (loop) {
|
if (loop) {
|
||||||
bufferSource.loop = true;
|
bufferSource.loop = true;
|
||||||
bufferSource.loopStart = loopBegin * bufferSource.buffer.duration - offset;
|
bufferSource.loopStart = loopBegin * bufferSource.buffer.duration - offset;
|
||||||
|
|
@ -267,16 +244,12 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
||||||
return samples(json, baseUrl || base, options);
|
return samples(json, baseUrl || base, options);
|
||||||
}
|
}
|
||||||
const { prebake, tag } = options;
|
const { prebake, tag } = options;
|
||||||
|
|
||||||
processSampleMap(
|
processSampleMap(
|
||||||
sampleMap,
|
sampleMap,
|
||||||
(key, bank) =>
|
(key, bank) => {
|
||||||
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, bank), {
|
registerSampleSource(key, bank, { baseUrl, prebake, tag });
|
||||||
type: 'sample',
|
},
|
||||||
samples: bank,
|
|
||||||
baseUrl,
|
|
||||||
prebake,
|
|
||||||
tag,
|
|
||||||
}),
|
|
||||||
baseUrl,
|
baseUrl,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -366,3 +339,20 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function registerSample(key, bank, params) {
|
||||||
|
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, bank), {
|
||||||
|
type: 'sample',
|
||||||
|
samples: bank,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerSampleSource(key, bank, params) {
|
||||||
|
const isWavetable = key.startsWith('wt_');
|
||||||
|
if (isWavetable) {
|
||||||
|
registerWaveTable(key, bank, params);
|
||||||
|
} else {
|
||||||
|
registerSample(key, bank, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,3 +76,32 @@ export function cycleToSeconds(cycle, cps) {
|
||||||
export function secondsToCycle(t, cps) {
|
export function secondsToCycle(t, cps) {
|
||||||
return t * cps;
|
return t * cps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deduces relevant info for sample loading from hap.value and sample definition
|
||||||
|
// it encapsulates the core sampler logic into a pure and synchronous function
|
||||||
|
// hapValue: Hap.value, bank: sample bank definition for sound "s" (values in strudel.json format)
|
||||||
|
export function getCommonSampleInfo(hapValue, bank) {
|
||||||
|
const { s, n = 0 } = hapValue;
|
||||||
|
let midi = valueToMidi(hapValue, 36);
|
||||||
|
let transpose = midi - 36; // C3 is middle C;
|
||||||
|
let url;
|
||||||
|
let index = 0;
|
||||||
|
if (Array.isArray(bank)) {
|
||||||
|
index = getSoundIndex(n, bank.length);
|
||||||
|
url = bank[index];
|
||||||
|
} else {
|
||||||
|
const midiDiff = (noteA) => noteToMidi(noteA) - midi;
|
||||||
|
// object format will expect keys as notes
|
||||||
|
const closest = Object.keys(bank)
|
||||||
|
.filter((k) => !k.startsWith('_'))
|
||||||
|
.reduce(
|
||||||
|
(closest, key, j) => (!closest || Math.abs(midiDiff(key)) < Math.abs(midiDiff(closest)) ? key : closest),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
transpose = -midiDiff(closest); // semitones to repitch
|
||||||
|
index = getSoundIndex(n, bank[closest].length);
|
||||||
|
url = bank[closest][index];
|
||||||
|
}
|
||||||
|
const label = `${s}:${index}`;
|
||||||
|
return { transpose, url, index, midi, label };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { getAudioContext, registerSound } from './index.mjs';
|
import { getAudioContext, registerSound } from './index.mjs';
|
||||||
import { getSoundIndex, valueToMidi } from './util.mjs';
|
import { getCommonSampleInfo } from './util.mjs';
|
||||||
import {
|
import {
|
||||||
destroyAudioWorkletNode,
|
destroyAudioWorkletNode,
|
||||||
getADSRValues,
|
getADSRValues,
|
||||||
|
|
@ -39,11 +39,11 @@ export const WarpMode = Object.freeze({
|
||||||
FLIP: 21,
|
FLIP: 21,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadWavetableFrames(url, label, frameLen = 256) {
|
async function loadWavetableFrames(url, label, frameLen = 2048) {
|
||||||
const buf = await loadBuffer(url, label);
|
const buf = await loadBuffer(url, label);
|
||||||
const ch0 = buf.getChannelData(0);
|
const ch0 = buf.getChannelData(0);
|
||||||
const total = ch0.length;
|
const total = ch0.length;
|
||||||
const numFrames = Math.floor(total / frameLen);
|
const numFrames = Math.max(1, Math.floor(total / frameLen));
|
||||||
const frames = new Array(numFrames);
|
const frames = new Array(numFrames);
|
||||||
for (let i = 0; i < numFrames; i++) {
|
for (let i = 0; i < numFrames; i++) {
|
||||||
const start = i * frameLen;
|
const start = i * frameLen;
|
||||||
|
|
@ -86,16 +86,6 @@ function humanFileSize(bytes, si) {
|
||||||
return bytes.toFixed(1) + ' ' + units[u];
|
return bytes.toFixed(1) + ' ' + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTableInfo(hapValue, tableUrls) {
|
|
||||||
const { s, n = 0 } = hapValue;
|
|
||||||
let midi = valueToMidi(hapValue, 36);
|
|
||||||
let transpose = midi - 36; // C3 is middle C;
|
|
||||||
const index = getSoundIndex(n, tableUrls.length);
|
|
||||||
const tableUrl = tableUrls[index];
|
|
||||||
const label = `${s}:${index}`;
|
|
||||||
return { transpose, tableUrl, index, midi, label };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the sample rate of a .wav file
|
// Extract the sample rate of a .wav file
|
||||||
function parseWavSampleRate(arrBuf) {
|
function parseWavSampleRate(arrBuf) {
|
||||||
const dv = new DataView(arrBuf);
|
const dv = new DataView(arrBuf);
|
||||||
|
|
@ -181,19 +171,19 @@ const _processTables = (json, baseUrl, frameLen, options = {}) => {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (tables.length) {
|
if (tables.length) {
|
||||||
const { prebake, tag } = options;
|
registerWaveTable(key, tables, { baseUrl, frameLen });
|
||||||
registerSound(key, (t, hapValue, onended) => onTriggerSynth(t, hapValue, onended, tables, frameLen), {
|
|
||||||
type: 'wavetable',
|
|
||||||
tables,
|
|
||||||
baseUrl,
|
|
||||||
frameLen,
|
|
||||||
prebake,
|
|
||||||
tag,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function registerWaveTable(key, tables, params) {
|
||||||
|
registerSound(key, (t, hapValue, onended) => onTriggerSynth(t, hapValue, onended, tables, params?.frameLen ?? 2048), {
|
||||||
|
type: 'wavetable',
|
||||||
|
tables,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a collection of wavetables to use with `s`
|
* Loads a collection of wavetables to use with `s`
|
||||||
*
|
*
|
||||||
|
|
@ -224,7 +214,7 @@ export const tables = async (url, frameLen, json, options = {}) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
export async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
||||||
const { s, n = 0, duration } = value;
|
const { s, n = 0, duration } = value;
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
const [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
||||||
|
|
@ -233,8 +223,8 @@ async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
||||||
wtWarpMode = WarpMode[wtWarpMode.toUpperCase()] ?? WarpMode.NONE;
|
wtWarpMode = WarpMode[wtWarpMode.toUpperCase()] ?? WarpMode.NONE;
|
||||||
}
|
}
|
||||||
const frequency = getFrequencyFromValue(value);
|
const frequency = getFrequencyFromValue(value);
|
||||||
const { tableUrl, label } = getTableInfo(value, tables);
|
const { url, label } = getCommonSampleInfo(value, tables);
|
||||||
const payload = await loadWavetableFrames(tableUrl, label, frameLen);
|
const payload = await loadWavetableFrames(url, label, frameLen);
|
||||||
const holdEnd = t + duration;
|
const holdEnd = t + duration;
|
||||||
const endWithRelease = holdEnd + release;
|
const endWithRelease = holdEnd + release;
|
||||||
const envEnd = endWithRelease + 0.01;
|
const envEnd = endWithRelease + 0.01;
|
||||||
|
|
@ -265,6 +255,7 @@ async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
||||||
const wtParams = source.parameters;
|
const wtParams = source.parameters;
|
||||||
const positionParam = wtParams.get('position');
|
const positionParam = wtParams.get('position');
|
||||||
const warpParam = wtParams.get('warp');
|
const warpParam = wtParams.get('warp');
|
||||||
|
let posLFO;
|
||||||
if (posADSRParams.some((p) => p !== undefined)) {
|
if (posADSRParams.some((p) => p !== undefined)) {
|
||||||
const [pAttack, pDecay, pSustain, pRelease] = getADSRValues(posADSRParams);
|
const [pAttack, pDecay, pSustain, pRelease] = getADSRValues(posADSRParams);
|
||||||
getParamADSR(positionParam, pAttack, pDecay, pSustain, pRelease, 0, 1, t, holdEnd, 'linear');
|
getParamADSR(positionParam, pAttack, pDecay, pSustain, pRelease, 0, 1, t, holdEnd, 'linear');
|
||||||
|
|
@ -278,6 +269,7 @@ async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
||||||
});
|
});
|
||||||
posLFO.connect(positionParam);
|
posLFO.connect(positionParam);
|
||||||
}
|
}
|
||||||
|
let warpLFO;
|
||||||
if (posADSRParams.some((p) => p !== undefined)) {
|
if (posADSRParams.some((p) => p !== undefined)) {
|
||||||
const [wAttack, wDecay, wSustain, wRelease] = getADSRValues(warpADSRParams);
|
const [wAttack, wDecay, wSustain, wRelease] = getADSRValues(warpADSRParams);
|
||||||
getParamADSR(warpParam, wAttack, wDecay, wSustain, wRelease, 0, 1, t, holdEnd, 'linear');
|
getParamADSR(warpParam, wAttack, wDecay, wSustain, wRelease, 0, 1, t, holdEnd, 'linear');
|
||||||
|
|
@ -304,8 +296,8 @@ async function onTriggerSynth(t, value, onended, tables, frameLen) {
|
||||||
destroyAudioWorkletNode(source);
|
destroyAudioWorkletNode(source);
|
||||||
vibratoOscillator?.stop();
|
vibratoOscillator?.stop();
|
||||||
node.disconnect();
|
node.disconnect();
|
||||||
warpLFO.disconnect();
|
posLFO?.disconnect();
|
||||||
posLFO.disconnect();
|
warpLFO?.disconnect();
|
||||||
onended();
|
onended();
|
||||||
},
|
},
|
||||||
t,
|
t,
|
||||||
|
|
|
||||||
|
|
@ -1049,7 +1049,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
{ name: 'begin', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
|
{ name: 'begin', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
|
||||||
{ name: 'end', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
|
{ name: 'end', defaultValue: 0, min: 0, max: Number.POSITIVE_INFINITY },
|
||||||
{ name: 'frequency', defaultValue: 220, minValue: 0.01, maxValue: 20000 },
|
{ name: 'frequency', defaultValue: 220, minValue: 0.01, maxValue: 20000 },
|
||||||
{ name: 'detune', defaultValue: 0 },
|
{ name: 'detune', defaultValue: 0.18 },
|
||||||
{ name: 'position', defaultValue: 0, minValue: 0, maxValue: 1 },
|
{ name: 'position', defaultValue: 0, minValue: 0, maxValue: 1 },
|
||||||
{ name: 'warp', defaultValue: 0, minValue: 0, maxValue: 1 },
|
{ name: 'warp', defaultValue: 0, minValue: 0, maxValue: 1 },
|
||||||
{ name: 'warpMode', defaultValue: 0 },
|
{ name: 'warpMode', defaultValue: 0 },
|
||||||
|
|
@ -1239,6 +1239,7 @@ class WavetableOscillatorProcessor extends AudioWorkletProcessor {
|
||||||
}
|
}
|
||||||
const outL = outputs[0][0];
|
const outL = outputs[0][0];
|
||||||
const outR = outputs[0][1] || outputs[0][0];
|
const outR = outputs[0][1] || outputs[0][0];
|
||||||
|
const gainAdjustment = 0.3;
|
||||||
|
|
||||||
if (!this.tables) {
|
if (!this.tables) {
|
||||||
outL.fill(0);
|
outL.fill(0);
|
||||||
|
|
|
||||||
|
|
@ -11993,6 +11993,234 @@ exports[`runs examples > example "withValue" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "wtPhaseRand" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 1/16 → 1/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 1/8 → 3/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 3/16 → 1/4 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 1/4 → 5/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 5/16 → 3/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 3/8 → 7/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 7/16 → 1/2 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 1/2 → 9/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 9/16 → 5/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 5/8 → 11/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 11/16 → 3/4 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 3/4 → 13/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 13/16 → 7/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 7/8 → 15/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 15/16 → 1/1 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 1/1 → 17/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 17/16 → 9/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 9/8 → 19/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 19/16 → 5/4 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 5/4 → 21/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 21/16 → 11/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 11/8 → 23/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 23/16 → 3/2 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 3/2 → 25/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 25/16 → 13/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 13/8 → 27/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 27/16 → 7/4 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 7/4 → 29/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 29/16 → 15/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 15/8 → 31/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 31/16 → 2/1 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 2/1 → 33/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 33/16 → 17/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 17/8 → 35/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 35/16 → 9/4 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 9/4 → 37/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 37/16 → 19/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 19/8 → 39/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 39/16 → 5/2 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 5/2 → 41/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 41/16 → 21/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 21/8 → 43/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 43/16 → 11/4 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 11/4 → 45/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 45/16 → 23/8 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 23/8 → 47/16 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 47/16 → 3/1 | s:basique bank:wt_digital wtPhaseRand:0 ]",
|
||||||
|
"[ 3/1 → 49/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 49/16 → 25/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 25/8 → 51/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 51/16 → 13/4 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 13/4 → 53/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 53/16 → 27/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 27/8 → 55/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 55/16 → 7/2 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 7/2 → 57/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 57/16 → 29/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 29/8 → 59/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 59/16 → 15/4 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 15/4 → 61/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 61/16 → 31/8 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 31/8 → 63/16 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
"[ 63/16 → 4/1 | s:basique bank:wt_digital wtPhaseRand:1 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "wtPos" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/8 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ (1/8 → 1/5) ⇝ 1/4 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ 1/8 ⇜ (1/5 → 1/4) | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 1/4 → 3/8 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ (3/8 → 2/5) ⇝ 1/2 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 3/8 ⇜ (2/5 → 1/2) | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ (1/2 → 3/5) ⇝ 5/8 | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ 1/2 ⇜ (3/5 → 5/8) | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 5/8 → 3/4 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ (3/4 → 4/5) ⇝ 7/8 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 3/4 ⇜ (4/5 → 7/8) | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 7/8 → 1/1 | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 1/1 → 9/8 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ (9/8 → 6/5) ⇝ 5/4 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ 9/8 ⇜ (6/5 → 5/4) | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 5/4 → 11/8 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ (11/8 → 7/5) ⇝ 3/2 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 11/8 ⇜ (7/5 → 3/2) | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ (3/2 → 8/5) ⇝ 13/8 | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ 3/2 ⇜ (8/5 → 13/8) | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 13/8 → 7/4 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ (7/4 → 9/5) ⇝ 15/8 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 7/4 ⇜ (9/5 → 15/8) | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 15/8 → 2/1 | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 2/1 → 17/8 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ (17/8 → 11/5) ⇝ 9/4 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ 17/8 ⇜ (11/5 → 9/4) | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 9/4 → 19/8 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ (19/8 → 12/5) ⇝ 5/2 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 19/8 ⇜ (12/5 → 5/2) | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ (5/2 → 13/5) ⇝ 21/8 | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ 5/2 ⇜ (13/5 → 21/8) | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 21/8 → 11/4 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ (11/4 → 14/5) ⇝ 23/8 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 11/4 ⇜ (14/5 → 23/8) | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 23/8 → 3/1 | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 3/1 → 25/8 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ (25/8 → 16/5) ⇝ 13/4 | s:squelch bank:wt_digital note:F1 wtPos:0 ]",
|
||||||
|
"[ 25/8 ⇜ (16/5 → 13/4) | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 13/4 → 27/8 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ (27/8 → 17/5) ⇝ 7/2 | s:squelch bank:wt_digital note:F1 wtPos:0.25 ]",
|
||||||
|
"[ 27/8 ⇜ (17/5 → 7/2) | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ (7/2 → 18/5) ⇝ 29/8 | s:squelch bank:wt_digital note:F1 wtPos:0.5 ]",
|
||||||
|
"[ 7/2 ⇜ (18/5 → 29/8) | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 29/8 → 15/4 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ (15/4 → 19/5) ⇝ 31/8 | s:squelch bank:wt_digital note:F1 wtPos:0.75 ]",
|
||||||
|
"[ 15/4 ⇜ (19/5 → 31/8) | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
"[ 31/8 → 4/1 | s:squelch bank:wt_digital note:F1 wtPos:1 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "wtWarp" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/8 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ (1/8 → 1/5) ⇝ 1/4 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ 1/8 ⇜ (1/5 → 1/4) | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 1/4 → 3/8 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ (3/8 → 2/5) ⇝ 1/2 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 3/8 ⇜ (2/5 → 1/2) | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ (1/2 → 3/5) ⇝ 5/8 | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ 1/2 ⇜ (3/5 → 5/8) | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 5/8 → 3/4 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ (3/4 → 4/5) ⇝ 7/8 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 3/4 ⇜ (4/5 → 7/8) | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 7/8 → 1/1 | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 1/1 → 9/8 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ (9/8 → 6/5) ⇝ 5/4 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ 9/8 ⇜ (6/5 → 5/4) | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 5/4 → 11/8 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ (11/8 → 7/5) ⇝ 3/2 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 11/8 ⇜ (7/5 → 3/2) | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ (3/2 → 8/5) ⇝ 13/8 | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ 3/2 ⇜ (8/5 → 13/8) | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 13/8 → 7/4 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ (7/4 → 9/5) ⇝ 15/8 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 7/4 ⇜ (9/5 → 15/8) | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 15/8 → 2/1 | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 2/1 → 17/8 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ (17/8 → 11/5) ⇝ 9/4 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ 17/8 ⇜ (11/5 → 9/4) | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 9/4 → 19/8 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ (19/8 → 12/5) ⇝ 5/2 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 19/8 ⇜ (12/5 → 5/2) | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ (5/2 → 13/5) ⇝ 21/8 | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ 5/2 ⇜ (13/5 → 21/8) | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 21/8 → 11/4 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ (11/4 → 14/5) ⇝ 23/8 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 11/4 ⇜ (14/5 → 23/8) | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 23/8 → 3/1 | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 3/1 → 25/8 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ (25/8 → 16/5) ⇝ 13/4 | s:basique bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ 25/8 ⇜ (16/5 → 13/4) | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 13/4 → 27/8 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ (27/8 → 17/5) ⇝ 7/2 | s:basique bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 27/8 ⇜ (17/5 → 7/2) | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ (7/2 → 18/5) ⇝ 29/8 | s:basique bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ 7/2 ⇜ (18/5 → 29/8) | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 29/8 → 15/4 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ (15/4 → 19/5) ⇝ 31/8 | s:basique bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:spin ]",
|
||||||
|
"[ 15/4 ⇜ (19/5 → 31/8) | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
"[ 31/8 → 4/1 | s:basique bank:wt_digital note:F1 wtWarp:1 wtWarpMode:spin ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "wtWarpMode" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/8 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:asym ]",
|
||||||
|
"[ (1/8 → 1/5) ⇝ 1/4 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:asym ]",
|
||||||
|
"[ 1/8 ⇜ (1/5 → 1/4) | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:asym ]",
|
||||||
|
"[ 1/4 → 3/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:asym ]",
|
||||||
|
"[ (3/8 → 2/5) ⇝ 1/2 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:asym ]",
|
||||||
|
"[ 3/8 ⇜ (2/5 → 1/2) | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:asym ]",
|
||||||
|
"[ (1/2 → 3/5) ⇝ 5/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:bendp ]",
|
||||||
|
"[ 1/2 ⇜ (3/5 → 5/8) | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:bendp ]",
|
||||||
|
"[ 5/8 → 3/4 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:bendp ]",
|
||||||
|
"[ (3/4 → 4/5) ⇝ 7/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:bendp ]",
|
||||||
|
"[ 3/4 ⇜ (4/5 → 7/8) | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:bendp ]",
|
||||||
|
"[ 7/8 → 1/1 | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:bendp ]",
|
||||||
|
"[ 1/1 → 9/8 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ (9/8 → 6/5) ⇝ 5/4 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:spin ]",
|
||||||
|
"[ 9/8 ⇜ (6/5 → 5/4) | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 5/4 → 11/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ (11/8 → 7/5) ⇝ 3/2 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:spin ]",
|
||||||
|
"[ 11/8 ⇜ (7/5 → 3/2) | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:spin ]",
|
||||||
|
"[ (3/2 → 8/5) ⇝ 13/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:logistic ]",
|
||||||
|
"[ 3/2 ⇜ (8/5 → 13/8) | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:logistic ]",
|
||||||
|
"[ 13/8 → 7/4 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:logistic ]",
|
||||||
|
"[ (7/4 → 9/5) ⇝ 15/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:logistic ]",
|
||||||
|
"[ 7/4 ⇜ (9/5 → 15/8) | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:logistic ]",
|
||||||
|
"[ 15/8 → 2/1 | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:logistic ]",
|
||||||
|
"[ 2/1 → 17/8 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:sync ]",
|
||||||
|
"[ (17/8 → 11/5) ⇝ 9/4 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:sync ]",
|
||||||
|
"[ 17/8 ⇜ (11/5 → 9/4) | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:sync ]",
|
||||||
|
"[ 9/4 → 19/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:sync ]",
|
||||||
|
"[ (19/8 → 12/5) ⇝ 5/2 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:sync ]",
|
||||||
|
"[ 19/8 ⇜ (12/5 → 5/2) | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:sync ]",
|
||||||
|
"[ (5/2 → 13/5) ⇝ 21/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:wormhole ]",
|
||||||
|
"[ 5/2 ⇜ (13/5 → 21/8) | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:wormhole ]",
|
||||||
|
"[ 21/8 → 11/4 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:wormhole ]",
|
||||||
|
"[ (11/4 → 14/5) ⇝ 23/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:wormhole ]",
|
||||||
|
"[ 11/4 ⇜ (14/5 → 23/8) | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:wormhole ]",
|
||||||
|
"[ 23/8 → 3/1 | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:wormhole ]",
|
||||||
|
"[ 3/1 → 25/8 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:brownian ]",
|
||||||
|
"[ (25/8 → 16/5) ⇝ 13/4 | s:morgana bank:wt_digital note:F1 wtWarp:0 wtWarpMode:brownian ]",
|
||||||
|
"[ 25/8 ⇜ (16/5 → 13/4) | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:brownian ]",
|
||||||
|
"[ 13/4 → 27/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:brownian ]",
|
||||||
|
"[ (27/8 → 17/5) ⇝ 7/2 | s:morgana bank:wt_digital note:F1 wtWarp:0.25 wtWarpMode:brownian ]",
|
||||||
|
"[ 27/8 ⇜ (17/5 → 7/2) | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:brownian ]",
|
||||||
|
"[ (7/2 → 18/5) ⇝ 29/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.5 wtWarpMode:asym ]",
|
||||||
|
"[ 7/2 ⇜ (18/5 → 29/8) | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:asym ]",
|
||||||
|
"[ 29/8 → 15/4 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:asym ]",
|
||||||
|
"[ (15/4 → 19/5) ⇝ 31/8 | s:morgana bank:wt_digital note:F1 wtWarp:0.75 wtWarpMode:asym ]",
|
||||||
|
"[ 15/4 ⇜ (19/5 → 31/8) | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:asym ]",
|
||||||
|
"[ 31/8 → 4/1 | s:morgana bank:wt_digital note:F1 wtWarp:1 wtWarpMode:asym ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "xfade" example index 0 1`] = `
|
exports[`runs examples > example "xfade" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/8 | s:hh gain:0 ]",
|
"[ 0/1 → 1/8 | s:hh gain:0 ]",
|
||||||
|
|
|
||||||
39
website/public/uzu-wavetables.json
Normal file
39
website/public/uzu-wavetables.json
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"_base": "https://raw.githubusercontent.com/tidalcycles/uzu-wavetables/main/",
|
||||||
|
"wt_digital": [
|
||||||
|
"wt_digital/wt_bad_day.wav",
|
||||||
|
"wt_digital/wt_basique.wav",
|
||||||
|
"wt_digital/wt_crickets.wav",
|
||||||
|
"wt_digital/wt_curses.wav",
|
||||||
|
"wt_digital/wt_earl_grey.wav",
|
||||||
|
"wt_digital/wt_echoes.wav",
|
||||||
|
"wt_digital/wt_glimmer.wav",
|
||||||
|
"wt_digital/wt_majick.wav",
|
||||||
|
"wt_digital/wt_meditation.wav",
|
||||||
|
"wt_digital/wt_morgana.wav",
|
||||||
|
"wt_digital/wt_red_alert.wav",
|
||||||
|
"wt_digital/wt_sad_piano.wav",
|
||||||
|
"wt_digital/wt_shook.wav",
|
||||||
|
"wt_digital/wt_sludge.wav",
|
||||||
|
"wt_digital/wt_squelch.wav",
|
||||||
|
"wt_digital/wt_summer.wav",
|
||||||
|
"wt_digital/wt_wasp.wav"
|
||||||
|
],
|
||||||
|
"wt_digital_bad_day": ["wt_digital/wt_bad_day.wav"],
|
||||||
|
"wt_digital_basique": ["wt_digital/wt_basique.wav"],
|
||||||
|
"wt_digital_crickets": ["wt_digital/wt_crickets.wav"],
|
||||||
|
"wt_digital_curses": ["wt_digital/wt_curses.wav"],
|
||||||
|
"wt_digital_earl_grey": ["wt_digital/wt_earl_grey.wav"],
|
||||||
|
"wt_digital_echoes": ["wt_digital/wt_echoes.wav"],
|
||||||
|
"wt_digital_glimmer": ["wt_digital/wt_glimmer.wav"],
|
||||||
|
"wt_digital_majick": ["wt_digital/wt_majick.wav"],
|
||||||
|
"wt_digital_meditation": ["wt_digital/wt_meditation.wav"],
|
||||||
|
"wt_digital_morgana": ["wt_digital/wt_morgana.wav"],
|
||||||
|
"wt_digital_red_alert": ["wt_digital/wt_red_alert.wav"],
|
||||||
|
"wt_digital_sad_piano": ["wt_digital/wt_sad_piano.wav"],
|
||||||
|
"wt_digital_shook": ["wt_digital/wt_shook.wav"],
|
||||||
|
"wt_digital_sludge": ["wt_digital/wt_sludge.wav"],
|
||||||
|
"wt_digital_squelch": ["wt_digital/wt_squelch.wav"],
|
||||||
|
"wt_digital_summer": ["wt_digital/wt_summer.wav"],
|
||||||
|
"wt_digital_wasp": ["wt_digital/wt_wasp.wav"]
|
||||||
|
}
|
||||||
|
|
@ -57,6 +57,9 @@ export function SoundsTab() {
|
||||||
// holds mutable ref to current triggered sound
|
// holds mutable ref to current triggered sound
|
||||||
const trigRef = useRef();
|
const trigRef = useRef();
|
||||||
|
|
||||||
|
// Used to cycle through sound previews on banks with multiple sounds
|
||||||
|
let soundPreviewIdx = 0;
|
||||||
|
|
||||||
// stop current sound on mouseup
|
// stop current sound on mouseup
|
||||||
useEvent('mouseup', () => {
|
useEvent('mouseup', () => {
|
||||||
const t = trigRef.current;
|
const t = trigRef.current;
|
||||||
|
|
@ -114,11 +117,13 @@ export function SoundsTab() {
|
||||||
const params = {
|
const params = {
|
||||||
note: ['synth', 'soundfont'].includes(data.type) ? 'a3' : undefined,
|
note: ['synth', 'soundfont'].includes(data.type) ? 'a3' : undefined,
|
||||||
s: name,
|
s: name,
|
||||||
|
n: soundPreviewIdx,
|
||||||
clip: 1,
|
clip: 1,
|
||||||
release: 0.5,
|
release: 0.5,
|
||||||
sustain: 1,
|
sustain: 1,
|
||||||
duration: 0.5,
|
duration: 0.5,
|
||||||
};
|
};
|
||||||
|
soundPreviewIdx++;
|
||||||
const time = ctx.currentTime + 0.05;
|
const time = ctx.currentTime + 0.05;
|
||||||
const onended = () => trigRef.current?.node?.disconnect();
|
const onended = () => trigRef.current?.node?.disconnect();
|
||||||
trigRef.current = Promise.resolve(onTrigger(time, params, onended));
|
trigRef.current = Promise.resolve(onTrigger(time, params, onended));
|
||||||
|
|
@ -129,7 +134,8 @@ export function SoundsTab() {
|
||||||
>
|
>
|
||||||
{' '}
|
{' '}
|
||||||
{name}
|
{name}
|
||||||
{data?.type === 'sample' || data?.type === 'wavetable' ? `(${getSamples(data.samples)})` : ''}
|
{data?.type === 'sample' ? `(${getSamples(data.samples)})` : ''}
|
||||||
|
{data?.type === 'wavetable' ? `(${getSamples(data.tables)})` : ''}
|
||||||
{data?.type === 'soundfont' ? `(${data.fonts.length})` : ''}
|
{data?.type === 'soundfont' ? `(${data.fonts.length})` : ''}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { registerSound, onTriggerSample } from '@strudel/webaudio';
|
import { registerSampleSource } from '@strudel/webaudio';
|
||||||
import { isAudioFile } from './files.mjs';
|
import { isAudioFile } from './files.mjs';
|
||||||
import { logger } from '@strudel/core';
|
import { logger } from '@strudel/core';
|
||||||
|
|
||||||
|
|
@ -76,13 +76,7 @@ export function registerSamplesFromDB(config = userSamplesDBConfig, onComplete =
|
||||||
})
|
})
|
||||||
.map((title) => titlePathMap.get(title));
|
.map((title) => titlePathMap.get(title));
|
||||||
|
|
||||||
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, value), {
|
registerSampleSource(key, value, { prebake: false });
|
||||||
type: 'sample',
|
|
||||||
samples: value,
|
|
||||||
baseUrl: undefined,
|
|
||||||
prebake: false,
|
|
||||||
tag: undefined,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
logger('imported sounds registered!', 'success');
|
logger('imported sounds registered!', 'success');
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ export async function prebake() {
|
||||||
prebake: true,
|
prebake: true,
|
||||||
tag: 'drum-machines',
|
tag: 'drum-machines',
|
||||||
}),
|
}),
|
||||||
|
samples(`${baseNoTrailing}/uzu-wavetables.json`, undefined, {
|
||||||
|
prebake: true,
|
||||||
|
}),
|
||||||
samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
|
samples(`${baseNoTrailing}/mridangam.json`, undefined, { prebake: true, tag: 'drum-machines' }),
|
||||||
samples(
|
samples(
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue