diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index 5a275294..3d3530d5 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -47,12 +47,16 @@ export function createParam(names) {
return func;
}
+// maps control alias names to the "main" control name
+const controlAlias = new Map();
+
export function registerControl(names, ...aliases) {
const name = Array.isArray(names) ? names[0] : names;
let bag = {};
bag[name] = createParam(names);
aliases.forEach((alias) => {
bag[alias] = bag[name];
+ controlAlias.set(alias, name);
Pattern.prototype[alias] = Pattern.prototype[name];
});
return bag;
@@ -1614,3 +1618,26 @@ export const ar = register('ar', (t, pat) => {
const [attack, release = attack] = t;
return pat.set({ attack, release });
});
+
+export const getControlName = (alias) => {
+ if (controlAlias.has(alias)) {
+ return controlAlias.get(alias);
+ }
+ return alias;
+};
+
+/**
+ * Sets properties in a batch.
+ *
+ * @name as
+ * @param {Array} mapping the control names that are set
+ * @example
+ * "c:.5 a:1 f:.25 e:.8".as("note:clip")
+ */
+export const as = register('as', (mapping, pat) => {
+ return pat.fmap((v) => {
+ v = Array.isArray(v) ? v : [v];
+ v = Object.fromEntries(mapping.map((prop, i) => [getControlName(prop), v[i]]));
+ return v;
+ });
+});
diff --git a/packages/core/test/controls.test.mjs b/packages/core/test/controls.test.mjs
index 3b926685..9dcbd830 100644
--- a/packages/core/test/controls.test.mjs
+++ b/packages/core/test/controls.test.mjs
@@ -4,7 +4,7 @@ Copyright (C) 2023 Strudel contributors - see .
*/
-import { s, pan } from '../controls.mjs';
+import { s, pan, getControlName } from '../controls.mjs';
import { mini } from '../../mini/mini.mjs';
import { describe, it, expect } from 'vitest';
import Fraction from '../fraction.mjs';
@@ -39,4 +39,8 @@ describe('controls', () => {
it('combines tactus of the pattern for .mix as lcm', () => {
expect(s(mini('bd cp mt').set.mix(pan(mini('1 2 3 4')))).tactus).toEqual(Fraction(12));
});
+ it('finds control name by alias', () => {
+ expect(getControlName('lpf')).toEqual('cutoff');
+ expect(getControlName('cutoff')).toEqual('cutoff');
+ });
});
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index c8d53858..e6f2000e 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -912,6 +912,27 @@ exports[`runs examples > example "arrange" example index 0 1`] = `
]
`;
+exports[`runs examples > example "as" example index 0 1`] = `
+[
+ "[ 0/1 → 1/4 | note:c clip:0.5 ]",
+ "[ 1/4 → 1/2 | note:a clip:1 ]",
+ "[ 1/2 → 3/4 | note:f clip:0.25 ]",
+ "[ 3/4 → 1/1 | note:e clip:0.8 ]",
+ "[ 1/1 → 5/4 | note:c clip:0.5 ]",
+ "[ 5/4 → 3/2 | note:a clip:1 ]",
+ "[ 3/2 → 7/4 | note:f clip:0.25 ]",
+ "[ 7/4 → 2/1 | note:e clip:0.8 ]",
+ "[ 2/1 → 9/4 | note:c clip:0.5 ]",
+ "[ 9/4 → 5/2 | note:a clip:1 ]",
+ "[ 5/2 → 11/4 | note:f clip:0.25 ]",
+ "[ 11/4 → 3/1 | note:e clip:0.8 ]",
+ "[ 3/1 → 13/4 | note:c clip:0.5 ]",
+ "[ 13/4 → 7/2 | note:a clip:1 ]",
+ "[ 7/2 → 15/4 | note:f clip:0.25 ]",
+ "[ 15/4 → 4/1 | note:e clip:0.8 ]",
+]
+`;
+
exports[`runs examples > example "attack" example index 0 1`] = `
[
"[ 0/1 → 1/4 | note:c3 attack:0 ]",
diff --git a/website/src/pages/functions/value-modifiers.mdx b/website/src/pages/functions/value-modifiers.mdx
index 19843e10..e290eb4e 100644
--- a/website/src/pages/functions/value-modifiers.mdx
+++ b/website/src/pages/functions/value-modifiers.mdx
@@ -132,6 +132,10 @@ This group of functions allows to modify the value of events.
+## as
+
+
+
# Custom Parameters
You can also create your own parameters: