Merge pull request 'feat: delaytime in cycles' (#1341) from daslyfe/jade/delaycycle into main
Reviewed-on: https://codeberg.org/uzu/strudel/pulls/1341
This commit is contained in:
commit
db413881db
6 changed files with 61 additions and 12 deletions
|
|
@ -985,15 +985,31 @@ export const { delayfeedback, delayfb, dfb } = registerControl('delayfeedback',
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const { delaytime, delayt, dt } = registerControl('delaytime', 'delayt', 'dt');
|
export const { delaytime, delayt, dt } = registerControl('delaytime', 'delayt', 'dt');
|
||||||
/* // TODO: test
|
|
||||||
|
/**
|
||||||
|
* Sets the time of the delay effect in cycles.
|
||||||
|
*
|
||||||
|
* @name delaysync
|
||||||
|
* @param {number | Pattern} cycles delay length in cycles
|
||||||
|
* @synonyms delayt, dt
|
||||||
|
* @example
|
||||||
|
* s("bd bd").delay(.25).delaysync("<1 2 3 5>".div(8))
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const { delaysync } = registerControl('delaysync');
|
||||||
|
|
||||||
|
/**
|
||||||
* Specifies whether delaytime is calculated relative to cps.
|
* Specifies whether delaytime is calculated relative to cps.
|
||||||
*
|
*
|
||||||
* @name lock
|
* @name lock
|
||||||
* @param {number | Pattern} enable When set to 1, delaytime is a direct multiple of a cycle.
|
* @param {number | Pattern} enable When set to 1, delaytime is a direct multiple of a cycle.
|
||||||
|
* @superdirtOnly
|
||||||
* @example
|
* @example
|
||||||
* s("sd").delay().lock(1).osc()
|
* s("sd").delay().lock(1).osc()
|
||||||
*
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const { lock } = registerControl('lock');
|
export const { lock } = registerControl('lock');
|
||||||
/**
|
/**
|
||||||
* Set detune for stacked voices of supported oscillators
|
* Set detune for stacked voices of supported oscillators
|
||||||
|
|
|
||||||
|
|
@ -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 } 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';
|
||||||
|
|
@ -143,7 +143,7 @@ const defaultDefaultValues = {
|
||||||
delay: 0,
|
delay: 0,
|
||||||
byteBeatExpression: '0',
|
byteBeatExpression: '0',
|
||||||
delayfeedback: 0.5,
|
delayfeedback: 0.5,
|
||||||
delaytime: 0.25,
|
delaysync: 3 / 16,
|
||||||
orbit: 1,
|
orbit: 1,
|
||||||
i: 1,
|
i: 1,
|
||||||
velocity: 1,
|
velocity: 1,
|
||||||
|
|
@ -450,7 +450,7 @@ 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) => {
|
export const superdough = async (value, t, hapDuration, cps = 0.5) => {
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
t = typeof t === 'string' && t.startsWith('=') ? Number(t.slice(1)) : ac.currentTime + t;
|
t = typeof t === 'string' && t.startsWith('=') ? Number(t.slice(1)) : ac.currentTime + t;
|
||||||
let { stretch } = value;
|
let { stretch } = value;
|
||||||
|
|
@ -528,7 +528,8 @@ export const superdough = async (value, t, hapDuration, cps) => {
|
||||||
vowel,
|
vowel,
|
||||||
delay = getDefaultValue('delay'),
|
delay = getDefaultValue('delay'),
|
||||||
delayfeedback = getDefaultValue('delayfeedback'),
|
delayfeedback = getDefaultValue('delayfeedback'),
|
||||||
delaytime = getDefaultValue('delaytime'),
|
delaysync = getDefaultValue('delaysync'),
|
||||||
|
delaytime,
|
||||||
orbit = getDefaultValue('orbit'),
|
orbit = getDefaultValue('orbit'),
|
||||||
room,
|
room,
|
||||||
roomfade,
|
roomfade,
|
||||||
|
|
@ -547,6 +548,8 @@ export const superdough = async (value, t, hapDuration, cps) => {
|
||||||
compressorRelease,
|
compressorRelease,
|
||||||
} = value;
|
} = value;
|
||||||
|
|
||||||
|
delaytime = delaytime ?? cycleToSeconds(delaysync, cps);
|
||||||
|
|
||||||
const orbitChannels = mapChannelNumbers(
|
const orbitChannels = mapChannelNumbers(
|
||||||
multiChannelOrbits && orbit > 0 ? [orbit * 2 - 1, orbit * 2] : getDefaultValue('channels'),
|
multiChannelOrbits && orbit > 0 ? [orbit * 2 - 1, orbit * 2] : getDefaultValue('channels'),
|
||||||
);
|
);
|
||||||
|
|
@ -725,8 +728,8 @@ export const superdough = async (value, t, hapDuration, cps) => {
|
||||||
// delay
|
// delay
|
||||||
let delaySend;
|
let delaySend;
|
||||||
if (delay > 0 && delaytime > 0 && delayfeedback > 0) {
|
if (delay > 0 && delaytime > 0 && delayfeedback > 0) {
|
||||||
const delyNode = getDelay(orbit, delaytime, delayfeedback, t, orbitChannels);
|
const delayNode = getDelay(orbit, delaytime, delayfeedback, t, orbitChannels);
|
||||||
delaySend = effectSend(post, delyNode, delay);
|
delaySend = effectSend(post, delayNode, delay);
|
||||||
audioNodes.push(delaySend);
|
audioNodes.push(delaySend);
|
||||||
}
|
}
|
||||||
// reverb
|
// reverb
|
||||||
|
|
|
||||||
|
|
@ -68,3 +68,7 @@ export const _mod = (n, m) => ((n % m) + m) % m;
|
||||||
export const getSoundIndex = (n, numSounds) => {
|
export const getSoundIndex = (n, numSounds) => {
|
||||||
return _mod(Math.round(nanFallback(n, 0)), numSounds);
|
return _mod(Math.round(nanFallback(n, 0)), numSounds);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function cycleToSeconds(cycle, cps) {
|
||||||
|
return cycle / cps;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@ const hap2value = (hap) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
|
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
|
||||||
// uses more precise, absolute t if available, see https://codeberg.org/uzu/strudel/pulls/1004
|
// uses more precise, absolute t if available, see https://github.com/tidalcycles/strudel/pull/1004
|
||||||
export const webaudioOutput = (hap, deadline, hapDuration, cps, t) =>
|
export const webaudioOutput = (hap, deadline, hapDuration, cps, t) => {
|
||||||
superdough(hap2value(hap), t ? `=${t}` : deadline, hapDuration);
|
return superdough(hap2value(hap), t ? `=${t}` : deadline, hapDuration, cps);
|
||||||
|
};
|
||||||
|
|
||||||
Pattern.prototype.webaudio = function () {
|
Pattern.prototype.webaudio = function () {
|
||||||
return this.onTrigger(webaudioOutputTrigger);
|
return this.onTrigger(webaudioOutputTrigger);
|
||||||
|
|
|
||||||
|
|
@ -2585,6 +2585,19 @@ exports[`runs examples > example "delayfeedback" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "delaysync" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/2 | s:bd delay:0.25 delaysync:0.125 ]",
|
||||||
|
"[ 1/2 → 1/1 | s:bd delay:0.25 delaysync:0.125 ]",
|
||||||
|
"[ 1/1 → 3/2 | s:bd delay:0.25 delaysync:0.25 ]",
|
||||||
|
"[ 3/2 → 2/1 | s:bd delay:0.25 delaysync:0.25 ]",
|
||||||
|
"[ 2/1 → 5/2 | s:bd delay:0.25 delaysync:0.375 ]",
|
||||||
|
"[ 5/2 → 3/1 | s:bd delay:0.25 delaysync:0.375 ]",
|
||||||
|
"[ 3/1 → 7/2 | s:bd delay:0.25 delaysync:0.625 ]",
|
||||||
|
"[ 7/2 → 4/1 | s:bd delay:0.25 delaysync:0.625 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "delaytime" example index 0 1`] = `
|
exports[`runs examples > example "delaytime" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/2 | s:bd delay:0.25 delaytime:0.125 ]",
|
"[ 0/1 → 1/2 | s:bd delay:0.25 delaytime:0.125 ]",
|
||||||
|
|
@ -5125,6 +5138,15 @@ exports[`runs examples > example "linger" example index 0 1`] = `
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`runs examples > example "lock" example index 0 1`] = `
|
||||||
|
[
|
||||||
|
"[ 0/1 → 1/1 | delay:{s:sd} lock:1 ]",
|
||||||
|
"[ 1/1 → 2/1 | delay:{s:sd} lock:1 ]",
|
||||||
|
"[ 2/1 → 3/1 | delay:{s:sd} lock:1 ]",
|
||||||
|
"[ 3/1 → 4/1 | delay:{s:sd} lock:1 ]",
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`runs examples > example "loop" example index 0 1`] = `
|
exports[`runs examples > example "loop" example index 0 1`] = `
|
||||||
[
|
[
|
||||||
"[ 0/1 → 1/1 | s:casio loop:1 ]",
|
"[ 0/1 → 1/1 | s:casio loop:1 ]",
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,11 @@ export function Reference() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lowCaseSearch = search.toLowerCase();
|
const lowCaseSearch = search.toLowerCase();
|
||||||
return entry.name.toLowerCase().includes(lowCaseSearch) || (entry.synonyms?.some((s) => s.includes(lowCaseSearch)) ?? false);
|
return (
|
||||||
|
entry.name.toLowerCase().includes(lowCaseSearch) ||
|
||||||
|
(entry.synonyms?.some((s) => s.includes(lowCaseSearch)) ?? false)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}, [search]);
|
}, [search]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue