From b73f62405820993ad0be28291066023279580fad Mon Sep 17 00:00:00 2001 From: Aria Date: Wed, 19 Nov 2025 15:41:29 -0600 Subject: [PATCH] Trying out alias approach --- packages/core/controls.mjs | 54 ++++++++++++++--------- packages/core/pattern.mjs | 90 ++++++++++++++++++++------------------ 2 files changed, 82 insertions(+), 62 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index 6be21414b..732679d64 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -2097,7 +2097,8 @@ export const { envAttack, envatt, envattack } = registerControl('envAttack', 'en * .envDepth("4800:400") * .envTarget("source:lpf") * .envParam("detune:frequency") - * .envDecay("0.03:0.15").envCurve("exp:exp") + * .envDecay("0.03:0.15") + * .envDCurve(-0.4) */ export const { envDecay, envdec, envdecay } = registerControl('envDecay', 'envdec', 'envdecay'); @@ -2112,7 +2113,7 @@ export const { envDecay, envdec, envdecay } = registerControl('envDecay', 'envde * .envDepth("4800:400") * .envTarget("source:lpf") * .envParam("detune:frequency") - * .envDecay("0.03:0.15").envCurve("exp:exp") + * .envACurve(0.6).envDCurve(-0.2) * .envSustain(0.2) */ export const { envSustain, envs, envsustain } = registerControl('envSustain', 'envs', 'envsustain'); @@ -2129,29 +2130,12 @@ export const { envSustain, envs, envsustain } = registerControl('envSustain', 'e * .envDepth("4800:400") * .envTarget("source:lpf") * .envParam("detune:frequency") - * .envDecay("0.03:0.15").envCurve("exp:exp") + * .envDecay("0.03:0.15").envRCurve(0.5) * .envSustain(0.5) * .envRelease(3) */ export const { envRelease, envr, envrelease } = registerControl('envRelease', 'envr', 'envrelease'); -/** - * Selects the style of envelope: `exp` or `lin` (exponential or linear). - * - * @name envCurve - * @synonyms envc, envcurve - * @param {string | Pattern} envCurve Envelope curve style. - * @example - * n(irand(12).seg(8)).scale("F#3:minor").room(1) - * .lpf(100).release(2) - * .envTarget("source:lpf") - * .envParam("detune:frequency") - * .envDepth("500:4000") - * .envDecay("0.3:0.15") - * .envCurve("lin:exp") - */ -export const { envCurve, envc, envcurve } = registerControl('envCurve', 'envc', 'envcurve'); - /** * Sets the modulation depth of the envelope. * @@ -2167,6 +2151,36 @@ export const { envCurve, envc, envcurve } = registerControl('envCurve', 'envc', */ export const { envDepth, envd, envdepth } = registerControl('envDepth', 'envd', 'envdepth'); +/** + * Adjusts the curvature of the attack portion of the envelope. Positive values are snappy, + * negative values are slow + * + * @name envACurve + * @synonyms envac, envacurve + * @param {number | Pattern} envACurve Curvature amount (between -1 and 1). + */ +export const { envACurve, envac, envacurve } = registerControl('envACurve', 'envac', 'envacurve'); + +/** + * Adjusts the curvature of the decay portion of the envelope. Positive values are snappy, + * negative values are slow + * + * @name envDCurve + * @synonyms envdc, envdcurve + * @param {number | Pattern} envDCurve Curvature amount (between -1 and 1). + */ +export const { envDCurve, envdc, envdcurve } = registerControl('envDCurve', 'envdc', 'envdcurve'); + +/** + * Adjusts the curvature of the release portion of the envelope. Positive values are snappy, + * negative values are slow + * + * @name envRCurve + * @synonyms envrc, envrcurve + * @param {number | Pattern} envRCurve Curvature amount (between -1 and 1). + */ +export const { envRCurve, envrc, envrcurve } = registerControl('envRCurve', 'envrc', 'envrcurve'); + // TODO: slide param for certain synths export const { slide } = registerControl('slide'); // TODO: detune? https://tidalcycles.org/docs/patternlib/tutorials/synthesizers/#supersquare diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index ea9d0f34c..4ba24b206 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -3688,42 +3688,43 @@ export const phases = (list) => { return _ensureListPattern(list).as('phases'); }; -/** - * Selects which LFO number to use for modulation. Multiple LFOs - * can be applied using the ':' mininotation. There are an arbitrary number - * of LFOs available -- the number is only used to share LFOs across targets - * if desired (and to conserve processing power) - * - * @name lfoNum - * @param {number | Pattern} lfoNum Index of the LFO. - * setup: note("F2").sound("supersaw") - * .lpf(100) - * .lfoDepth(1000) - * .lfoRate(0.25) - * .lfoSynced(1) - * .lfoTarget("lpf") - * .lfoParam("frequency") - * .lfoNum(2) - * - * reuse: note("F3").sound("square").lpf(50) - * .lfoTarget("lpf") - * .lfoParam("frequency") - * .lfoNum(2) // uses the same LFO - */ +const configAliases = new Map(); +const addConfigAlias = (funcName, canonical, ...aliases) => { + const lowerFunc = String(funcName).toLowerCase(); + const aliasMap = configAliases.get(lowerFunc) ?? new Map(); + const allKeys = new Set([canonical, ...aliases]); + for (const alias of allKeys) { + aliasMap.set(String(alias).toLowerCase(), canonical); + } + configAliases.set(lowerFunc, aliasMap); +}; -/** - * Sets the target destination for the envelope modulation. Names are typically related - * to existing controls ("source", "lpf", "vibrato", etc.). You can try a value - * and if it fails, the console will print the available options. - * - * @name envTarget - * @param {number | Pattern} envTarget Target identifier for modulation. - * n(irand(12).seg(8)).scale("F#3:minor").room(1) - * .lpf(100) - * .envDepth("4800:400") - * .envTarget("source:lpf") - * .envParam("detune:frequency") - */ +const resolveConfigKey = (funcName, key) => { + const aliasMap = configAliases.get(String(funcName).toLowerCase()); + if (!aliasMap) return key; + const normalized = String(key).toLowerCase(); + return aliasMap.get(normalized) ?? key; +}; + +addConfigAlias('lfo', 'lfoTarget', 'lfot', 'lfotarget', 'target', 't'); +addConfigAlias('lfo', 'lfoParam', 'lfop', 'lfoparam', 'param', 'parameter', 'p'); +addConfigAlias('lfo', 'lfoRate', 'lfor', 'lforate', 'rate', 'r'); +addConfigAlias('lfo', 'lfoDepth', 'lfod', 'lfodepth', 'depth', 'd'); +addConfigAlias('lfo', 'lfoDCOffset', 'lfodc', 'lfodcoffset', 'dcoffset', 'offset', 'dc'); +addConfigAlias('lfo', 'lfoShape', 'lfosh', 'lfoshape', 'shape', 'sh'); +addConfigAlias('lfo', 'lfoSkew', 'lfosk', 'lfoskew', 'skew', 'sk'); +addConfigAlias('lfo', 'lfoCurve', 'lfoc', 'lfocurve', 'curve', 'c'); +addConfigAlias('lfo', 'lfoSync', 'lfos', 'lfosync', 'sync', 'synced', 's'); +addConfigAlias('env', 'envTarget', 'envt', 'envtarget'); +addConfigAlias('env', 'envParam', 'envp', 'envparam'); +addConfigAlias('env', 'envAttack', 'envatt', 'envattack'); +addConfigAlias('env', 'envDecay', 'envdec', 'envdecay'); +addConfigAlias('env', 'envSustain', 'envs', 'envsustain'); +addConfigAlias('env', 'envRelease', 'envr', 'envrelease'); +addConfigAlias('env', 'envDepth', 'envd', 'envdepth'); +addConfigAlias('env', 'envACurve', 'envac', 'envacurve'); +addConfigAlias('env', 'envDCurve', 'envdc', 'envdcurve'); +addConfigAlias('env', 'envRCurve', 'envrc', 'envrcurve'); /** * Establishes a signal chain. Can be called in sequence like pat.chain(...).chain(...) and so forth @@ -3738,12 +3739,17 @@ export const phases = (list) => { * @param {Pattern | Pattern[]} patterns Patterns to combine into a single chain * @returns Pattern */ -Pattern.prototype.chain = function (...pats) { - pats = pats.map(reify); - return this.withValue((v) => (vEff) => { - const currChain = v.chain ?? []; - return { ...v, chain: currChain.concat(vEff) }; - }).appLeft(parray(pats)); +Pattern.prototype.lfo = function (config) { + if (config == null || typeof config !== 'object') { + return this; + } + let output = this; + for (const [rawKey, value] of Object.entries(config)) { + const key = resolveConfigKey('lfo', rawKey); + const pat = reify(value); + output = output.set(pat.as(key)); + } + return output; }; -export const chain = (pats) => pure({}).chain(pats); +export const lfo = (config) => pure({}).lfo(config);