diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs
index b3537db9..901a2ba3 100644
--- a/packages/core/controls.mjs
+++ b/packages/core/controls.mjs
@@ -83,8 +83,7 @@ const generic_params = [
*/
['f', 'amp', 'like @gain@, but linear.'],
/**
- * A pattern of numbers to specify the attack time of an envelope applied to each sample.
- * [More info about envelopes](/learn/synths-samples-effects/#envelope)
+ * Amplitude envelope attack time: Specifies how long it takes for the sound to reach its peak value, relative to the onset.
*
* @name attack
* @param {number | Pattern} attack time in seconds.
@@ -92,11 +91,7 @@ const generic_params = [
* note("c3 e3").attack("<0 .1 .5>")
*
*/
- [
- 'f',
- 'attack',
- 'a pattern of numbers to specify the attack time (in seconds) of an envelope applied to each sample.',
- ],
+ ['f', 'attack'],
/**
* Select the sound bank to use. To be used together with `s`. The bank name (+ "_") will be prepended to the value of `s`.
@@ -110,8 +105,8 @@ const generic_params = [
['f', 'bank', 'selects sound bank to use'],
/**
- * Gain envelope decay time = the time it takes after the attack time to reach the sustain level.
- * [More info about envelopes](/learn/synths-samples-effects/#envelope)
+ * Amplitude envelope decay time: the time it takes after the attack time to reach the sustain level.
+ * Note that the decay is only audible if the sustain value is lower than 1.
*
* @name decay
* @param {number | Pattern} time decay time in seconds
@@ -121,7 +116,7 @@ const generic_params = [
*/
['f', 'decay', ''],
/**
- * Gain envelope sustain level. [More info about envelopes](/learn/synths-samples-effects/#envelope)
+ * Amplitude envelope sustain level: The level which is reached after attack / decay, being sustained until the offset.
*
* @name sustain
* @param {number | Pattern} gain sustain level between 0 and 1
@@ -131,7 +126,7 @@ const generic_params = [
*/
['f', 'sustain', ''],
/**
- * Gain envelope release time. [More info about envelopes](/learn/synths-samples-effects/#envelope)
+ * Amplitude envelope release time: The time it takes after the offset to go from sustain level to zero.
*
* @name release
* @param {number | Pattern} time release time in seconds
@@ -151,30 +146,30 @@ const generic_params = [
],
// TODO: in tidal, it seems to be normalized
/**
- * Sets the center frequency of the band-pass filter.
+ * Sets the center frequency of the **b**and-**p**ass **f**ilter.
*
- * @name bandf
+ * @name bpf
* @param {number | Pattern} frequency center frequency
- * @synonyms bpf
+ * @synonyms bandf
* @example
- * s("bd sd,hh*3").bandf("<1000 2000 4000 8000>")
+ * s("bd sd,hh*3").bpf("<1000 2000 4000 8000>")
*
*/
- ['f', 'bandf', 'A pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.'],
['f', 'bpf', ''],
+ ['f', 'bandf', 'A pattern of numbers from 0 to 1. Sets the center frequency of the band-pass filter.'],
// TODO: in tidal, it seems to be normalized
/**
- * Sets the q-factor of the band-pass filter
+ * Sets the **b**and-**p**ass **q**-factor (resonance)
*
- * @name bandq
+ * @name bpq
* @param {number | Pattern} q q factor
- * @synonyms bpq
+ * @synonyms bandq
* @example
- * s("bd sd").bandf(500).bandq("<0 1 2 3>")
+ * s("bd sd").bpf(500).bpq("<0 1 2 3>")
*
*/
- ['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'],
['f', 'bpq', ''],
+ ['f', 'bandq', 'a pattern of anumbers from 0 to 1. Sets the q-factor of the band-pass filter.'],
/**
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
*
@@ -282,50 +277,49 @@ const generic_params = [
'In the style of classic drum-machines, `cut` will stop a playing sample as soon as another samples with in same cutgroup is to be played. An example would be an open hi-hat followed by a closed one, essentially muting the open.',
],
/**
- * Applies the cutoff frequency of the low-pass filter.
+ * Applies the cutoff frequency of the **l**ow-**p**ass **f**ilter.
*
- * @name cutoff
+ * @name lpf
* @param {number | Pattern} frequency audible between 0 and 20000
- * @synonyms lpf
+ * @synonyms cutoff
* @example
- * s("bd sd,hh*3").cutoff("<4000 2000 1000 500 200 100>")
+ * s("bd sd,hh*3").lpf("<4000 2000 1000 500 200 100>")
*
*/
- ['f', 'cutoff', 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.'],
['f', 'lpf'],
+ ['f', 'cutoff', 'a pattern of numbers from 0 to 1. Applies the cutoff frequency of the low-pass filter.'],
/**
- * Applies the cutoff frequency of the high-pass filter.
+ * Applies the cutoff frequency of the **h**igh-**p**ass **f**ilter.
*
- * @name hcutoff
+ * @name hpf
* @param {number | Pattern} frequency audible between 0 and 20000
- * @synonyms hpf
+ * @synonyms hcutoff
* @example
- * s("bd sd,hh*4").hcutoff("<4000 2000 1000 500 200 100>")
+ * s("bd sd,hh*4").hpf("<4000 2000 1000 500 200 100>")
*
*/
- ['f', 'hcutoff', ''],
['f', 'hpf', ''],
+ ['f', 'hcutoff', ''],
/**
- * Applies the resonance of the high-pass filter.
+ * Controls the **h**igh-**p**ass **q**-value.
*
- * @name hresonance
+ * @name hpq
* @param {number | Pattern} q resonance factor between 0 and 50
- * @synonyms hpq
+ * @synonyms hresonance
* @example
- * s("bd sd,hh*4").hcutoff(2000).hresonance("<0 10 20 30>")
+ * s("bd sd,hh*4").hpf(2000).hpq("<0 10 20 30>")
*
*/
- ['f', 'hpq', ''],
['f', 'hresonance', ''],
- // TODO: add hpq synonym
+ ['f', 'hpq', ''],
/**
- * Applies the cutoff frequency of the low-pass filter.
+ * Controls the **l**ow-**p**ass **q**-value.
*
- * @name resonance
+ * @name lpq
* @param {number | Pattern} q resonance factor between 0 and 50
- * @synonyms lpq
+ * @synonyms resonance
* @example
- * s("bd sd,hh*4").cutoff(2000).resonance("<0 10 20 30>")
+ * s("bd sd,hh*4").lpf(2000).lpq("<0 10 20 30>")
*
*/
['f', 'lpq'],
diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap
index 7320576a..148f12cc 100644
--- a/test/__snapshots__/examples.test.mjs.snap
+++ b/test/__snapshots__/examples.test.mjs.snap
@@ -861,44 +861,6 @@ exports[`runs examples > example "attack" example index 0 1`] = `
]
`;
-exports[`runs examples > example "bandf" example index 0 1`] = `
-[
- "[ 0/1 → 1/2 | s:bd bandf:1000 ]",
- "[ 1/2 → 1/1 | s:sd bandf:1000 ]",
- "[ 0/1 → 1/3 | s:hh bandf:1000 ]",
- "[ 1/3 → 2/3 | s:hh bandf:1000 ]",
- "[ 2/3 → 1/1 | s:hh bandf:1000 ]",
- "[ 1/1 → 3/2 | s:bd bandf:2000 ]",
- "[ 3/2 → 2/1 | s:sd bandf:2000 ]",
- "[ 1/1 → 4/3 | s:hh bandf:2000 ]",
- "[ 4/3 → 5/3 | s:hh bandf:2000 ]",
- "[ 5/3 → 2/1 | s:hh bandf:2000 ]",
- "[ 2/1 → 5/2 | s:bd bandf:4000 ]",
- "[ 5/2 → 3/1 | s:sd bandf:4000 ]",
- "[ 2/1 → 7/3 | s:hh bandf:4000 ]",
- "[ 7/3 → 8/3 | s:hh bandf:4000 ]",
- "[ 8/3 → 3/1 | s:hh bandf:4000 ]",
- "[ 3/1 → 7/2 | s:bd bandf:8000 ]",
- "[ 7/2 → 4/1 | s:sd bandf:8000 ]",
- "[ 3/1 → 10/3 | s:hh bandf:8000 ]",
- "[ 10/3 → 11/3 | s:hh bandf:8000 ]",
- "[ 11/3 → 4/1 | s:hh bandf:8000 ]",
-]
-`;
-
-exports[`runs examples > example "bandq" example index 0 1`] = `
-[
- "[ 0/1 → 1/2 | s:bd bandf:500 bandq:0 ]",
- "[ 1/2 → 1/1 | s:sd bandf:500 bandq:0 ]",
- "[ 1/1 → 3/2 | s:bd bandf:500 bandq:1 ]",
- "[ 3/2 → 2/1 | s:sd bandf:500 bandq:1 ]",
- "[ 2/1 → 5/2 | s:bd bandf:500 bandq:2 ]",
- "[ 5/2 → 3/1 | s:sd bandf:500 bandq:2 ]",
- "[ 3/1 → 7/2 | s:bd bandf:500 bandq:3 ]",
- "[ 7/2 → 4/1 | s:sd bandf:500 bandq:3 ]",
-]
-`;
-
exports[`runs examples > example "bank" example index 0 1`] = `
[
"[ 0/1 → 1/2 | s:bd bank:RolandTR909 ]",
@@ -921,6 +883,44 @@ exports[`runs examples > example "begin" example index 0 1`] = `
]
`;
+exports[`runs examples > example "bpf" example index 0 1`] = `
+[
+ "[ 0/1 → 1/2 | s:bd bpf:1000 ]",
+ "[ 1/2 → 1/1 | s:sd bpf:1000 ]",
+ "[ 0/1 → 1/3 | s:hh bpf:1000 ]",
+ "[ 1/3 → 2/3 | s:hh bpf:1000 ]",
+ "[ 2/3 → 1/1 | s:hh bpf:1000 ]",
+ "[ 1/1 → 3/2 | s:bd bpf:2000 ]",
+ "[ 3/2 → 2/1 | s:sd bpf:2000 ]",
+ "[ 1/1 → 4/3 | s:hh bpf:2000 ]",
+ "[ 4/3 → 5/3 | s:hh bpf:2000 ]",
+ "[ 5/3 → 2/1 | s:hh bpf:2000 ]",
+ "[ 2/1 → 5/2 | s:bd bpf:4000 ]",
+ "[ 5/2 → 3/1 | s:sd bpf:4000 ]",
+ "[ 2/1 → 7/3 | s:hh bpf:4000 ]",
+ "[ 7/3 → 8/3 | s:hh bpf:4000 ]",
+ "[ 8/3 → 3/1 | s:hh bpf:4000 ]",
+ "[ 3/1 → 7/2 | s:bd bpf:8000 ]",
+ "[ 7/2 → 4/1 | s:sd bpf:8000 ]",
+ "[ 3/1 → 10/3 | s:hh bpf:8000 ]",
+ "[ 10/3 → 11/3 | s:hh bpf:8000 ]",
+ "[ 11/3 → 4/1 | s:hh bpf:8000 ]",
+]
+`;
+
+exports[`runs examples > example "bpq" example index 0 1`] = `
+[
+ "[ 0/1 → 1/2 | s:bd bpf:500 bpq:0 ]",
+ "[ 1/2 → 1/1 | s:sd bpf:500 bpq:0 ]",
+ "[ 1/1 → 3/2 | s:bd bpf:500 bpq:1 ]",
+ "[ 3/2 → 2/1 | s:sd bpf:500 bpq:1 ]",
+ "[ 2/1 → 5/2 | s:bd bpf:500 bpq:2 ]",
+ "[ 5/2 → 3/1 | s:sd bpf:500 bpq:2 ]",
+ "[ 3/1 → 7/2 | s:bd bpf:500 bpq:3 ]",
+ "[ 7/2 → 4/1 | s:sd bpf:500 bpq:3 ]",
+]
+`;
+
exports[`runs examples > example "cat" example index 0 1`] = `
[
"[ 0/1 → 1/2 | s:hh ]",
@@ -1254,31 +1254,6 @@ exports[`runs examples > example "cut" example index 0 1`] = `
]
`;
-exports[`runs examples > example "cutoff" example index 0 1`] = `
-[
- "[ 0/1 → 1/2 | s:bd cutoff:4000 ]",
- "[ 1/2 → 1/1 | s:sd cutoff:4000 ]",
- "[ 0/1 → 1/3 | s:hh cutoff:4000 ]",
- "[ 1/3 → 2/3 | s:hh cutoff:4000 ]",
- "[ 2/3 → 1/1 | s:hh cutoff:4000 ]",
- "[ 1/1 → 3/2 | s:bd cutoff:2000 ]",
- "[ 3/2 → 2/1 | s:sd cutoff:2000 ]",
- "[ 1/1 → 4/3 | s:hh cutoff:2000 ]",
- "[ 4/3 → 5/3 | s:hh cutoff:2000 ]",
- "[ 5/3 → 2/1 | s:hh cutoff:2000 ]",
- "[ 2/1 → 5/2 | s:bd cutoff:1000 ]",
- "[ 5/2 → 3/1 | s:sd cutoff:1000 ]",
- "[ 2/1 → 7/3 | s:hh cutoff:1000 ]",
- "[ 7/3 → 8/3 | s:hh cutoff:1000 ]",
- "[ 8/3 → 3/1 | s:hh cutoff:1000 ]",
- "[ 3/1 → 7/2 | s:bd cutoff:500 ]",
- "[ 7/2 → 4/1 | s:sd cutoff:500 ]",
- "[ 3/1 → 10/3 | s:hh cutoff:500 ]",
- "[ 10/3 → 11/3 | s:hh cutoff:500 ]",
- "[ 11/3 → 4/1 | s:hh cutoff:500 ]",
-]
-`;
-
exports[`runs examples > example "decay" example index 0 1`] = `
[
"[ 0/1 → 1/2 | note:c3 decay:0.1 sustain:0 ]",
@@ -1898,61 +1873,61 @@ exports[`runs examples > example "gain" example index 0 1`] = `
]
`;
-exports[`runs examples > example "hcutoff" example index 0 1`] = `
+exports[`runs examples > example "hpf" example index 0 1`] = `
[
- "[ 0/1 → 1/2 | s:bd hcutoff:4000 ]",
- "[ 1/2 → 1/1 | s:sd hcutoff:4000 ]",
- "[ 0/1 → 1/4 | s:hh hcutoff:4000 ]",
- "[ 1/4 → 1/2 | s:hh hcutoff:4000 ]",
- "[ 1/2 → 3/4 | s:hh hcutoff:4000 ]",
- "[ 3/4 → 1/1 | s:hh hcutoff:4000 ]",
- "[ 1/1 → 3/2 | s:bd hcutoff:2000 ]",
- "[ 3/2 → 2/1 | s:sd hcutoff:2000 ]",
- "[ 1/1 → 5/4 | s:hh hcutoff:2000 ]",
- "[ 5/4 → 3/2 | s:hh hcutoff:2000 ]",
- "[ 3/2 → 7/4 | s:hh hcutoff:2000 ]",
- "[ 7/4 → 2/1 | s:hh hcutoff:2000 ]",
- "[ 2/1 → 5/2 | s:bd hcutoff:1000 ]",
- "[ 5/2 → 3/1 | s:sd hcutoff:1000 ]",
- "[ 2/1 → 9/4 | s:hh hcutoff:1000 ]",
- "[ 9/4 → 5/2 | s:hh hcutoff:1000 ]",
- "[ 5/2 → 11/4 | s:hh hcutoff:1000 ]",
- "[ 11/4 → 3/1 | s:hh hcutoff:1000 ]",
- "[ 3/1 → 7/2 | s:bd hcutoff:500 ]",
- "[ 7/2 → 4/1 | s:sd hcutoff:500 ]",
- "[ 3/1 → 13/4 | s:hh hcutoff:500 ]",
- "[ 13/4 → 7/2 | s:hh hcutoff:500 ]",
- "[ 7/2 → 15/4 | s:hh hcutoff:500 ]",
- "[ 15/4 → 4/1 | s:hh hcutoff:500 ]",
+ "[ 0/1 → 1/2 | s:bd hpf:4000 ]",
+ "[ 1/2 → 1/1 | s:sd hpf:4000 ]",
+ "[ 0/1 → 1/4 | s:hh hpf:4000 ]",
+ "[ 1/4 → 1/2 | s:hh hpf:4000 ]",
+ "[ 1/2 → 3/4 | s:hh hpf:4000 ]",
+ "[ 3/4 → 1/1 | s:hh hpf:4000 ]",
+ "[ 1/1 → 3/2 | s:bd hpf:2000 ]",
+ "[ 3/2 → 2/1 | s:sd hpf:2000 ]",
+ "[ 1/1 → 5/4 | s:hh hpf:2000 ]",
+ "[ 5/4 → 3/2 | s:hh hpf:2000 ]",
+ "[ 3/2 → 7/4 | s:hh hpf:2000 ]",
+ "[ 7/4 → 2/1 | s:hh hpf:2000 ]",
+ "[ 2/1 → 5/2 | s:bd hpf:1000 ]",
+ "[ 5/2 → 3/1 | s:sd hpf:1000 ]",
+ "[ 2/1 → 9/4 | s:hh hpf:1000 ]",
+ "[ 9/4 → 5/2 | s:hh hpf:1000 ]",
+ "[ 5/2 → 11/4 | s:hh hpf:1000 ]",
+ "[ 11/4 → 3/1 | s:hh hpf:1000 ]",
+ "[ 3/1 → 7/2 | s:bd hpf:500 ]",
+ "[ 7/2 → 4/1 | s:sd hpf:500 ]",
+ "[ 3/1 → 13/4 | s:hh hpf:500 ]",
+ "[ 13/4 → 7/2 | s:hh hpf:500 ]",
+ "[ 7/2 → 15/4 | s:hh hpf:500 ]",
+ "[ 15/4 → 4/1 | s:hh hpf:500 ]",
]
`;
-exports[`runs examples > example "hresonance" example index 0 1`] = `
+exports[`runs examples > example "hpq" example index 0 1`] = `
[
- "[ 0/1 → 1/2 | s:bd hcutoff:2000 hresonance:0 ]",
- "[ 1/2 → 1/1 | s:sd hcutoff:2000 hresonance:0 ]",
- "[ 0/1 → 1/4 | s:hh hcutoff:2000 hresonance:0 ]",
- "[ 1/4 → 1/2 | s:hh hcutoff:2000 hresonance:0 ]",
- "[ 1/2 → 3/4 | s:hh hcutoff:2000 hresonance:0 ]",
- "[ 3/4 → 1/1 | s:hh hcutoff:2000 hresonance:0 ]",
- "[ 1/1 → 3/2 | s:bd hcutoff:2000 hresonance:10 ]",
- "[ 3/2 → 2/1 | s:sd hcutoff:2000 hresonance:10 ]",
- "[ 1/1 → 5/4 | s:hh hcutoff:2000 hresonance:10 ]",
- "[ 5/4 → 3/2 | s:hh hcutoff:2000 hresonance:10 ]",
- "[ 3/2 → 7/4 | s:hh hcutoff:2000 hresonance:10 ]",
- "[ 7/4 → 2/1 | s:hh hcutoff:2000 hresonance:10 ]",
- "[ 2/1 → 5/2 | s:bd hcutoff:2000 hresonance:20 ]",
- "[ 5/2 → 3/1 | s:sd hcutoff:2000 hresonance:20 ]",
- "[ 2/1 → 9/4 | s:hh hcutoff:2000 hresonance:20 ]",
- "[ 9/4 → 5/2 | s:hh hcutoff:2000 hresonance:20 ]",
- "[ 5/2 → 11/4 | s:hh hcutoff:2000 hresonance:20 ]",
- "[ 11/4 → 3/1 | s:hh hcutoff:2000 hresonance:20 ]",
- "[ 3/1 → 7/2 | s:bd hcutoff:2000 hresonance:30 ]",
- "[ 7/2 → 4/1 | s:sd hcutoff:2000 hresonance:30 ]",
- "[ 3/1 → 13/4 | s:hh hcutoff:2000 hresonance:30 ]",
- "[ 13/4 → 7/2 | s:hh hcutoff:2000 hresonance:30 ]",
- "[ 7/2 → 15/4 | s:hh hcutoff:2000 hresonance:30 ]",
- "[ 15/4 → 4/1 | s:hh hcutoff:2000 hresonance:30 ]",
+ "[ 0/1 → 1/2 | s:bd hpf:2000 hpq:0 ]",
+ "[ 1/2 → 1/1 | s:sd hpf:2000 hpq:0 ]",
+ "[ 0/1 → 1/4 | s:hh hpf:2000 hpq:0 ]",
+ "[ 1/4 → 1/2 | s:hh hpf:2000 hpq:0 ]",
+ "[ 1/2 → 3/4 | s:hh hpf:2000 hpq:0 ]",
+ "[ 3/4 → 1/1 | s:hh hpf:2000 hpq:0 ]",
+ "[ 1/1 → 3/2 | s:bd hpf:2000 hpq:10 ]",
+ "[ 3/2 → 2/1 | s:sd hpf:2000 hpq:10 ]",
+ "[ 1/1 → 5/4 | s:hh hpf:2000 hpq:10 ]",
+ "[ 5/4 → 3/2 | s:hh hpf:2000 hpq:10 ]",
+ "[ 3/2 → 7/4 | s:hh hpf:2000 hpq:10 ]",
+ "[ 7/4 → 2/1 | s:hh hpf:2000 hpq:10 ]",
+ "[ 2/1 → 5/2 | s:bd hpf:2000 hpq:20 ]",
+ "[ 5/2 → 3/1 | s:sd hpf:2000 hpq:20 ]",
+ "[ 2/1 → 9/4 | s:hh hpf:2000 hpq:20 ]",
+ "[ 9/4 → 5/2 | s:hh hpf:2000 hpq:20 ]",
+ "[ 5/2 → 11/4 | s:hh hpf:2000 hpq:20 ]",
+ "[ 11/4 → 3/1 | s:hh hpf:2000 hpq:20 ]",
+ "[ 3/1 → 7/2 | s:bd hpf:2000 hpq:30 ]",
+ "[ 7/2 → 4/1 | s:sd hpf:2000 hpq:30 ]",
+ "[ 3/1 → 13/4 | s:hh hpf:2000 hpq:30 ]",
+ "[ 13/4 → 7/2 | s:hh hpf:2000 hpq:30 ]",
+ "[ 7/2 → 15/4 | s:hh hpf:2000 hpq:30 ]",
+ "[ 15/4 → 4/1 | s:hh hpf:2000 hpq:30 ]",
]
`;
@@ -2385,6 +2360,60 @@ exports[`runs examples > example "loopAtCps" example index 0 1`] = `
]
`;
+exports[`runs examples > example "lpf" example index 0 1`] = `
+[
+ "[ 0/1 → 1/2 | s:bd lpf:4000 ]",
+ "[ 1/2 → 1/1 | s:sd lpf:4000 ]",
+ "[ 0/1 → 1/3 | s:hh lpf:4000 ]",
+ "[ 1/3 → 2/3 | s:hh lpf:4000 ]",
+ "[ 2/3 → 1/1 | s:hh lpf:4000 ]",
+ "[ 1/1 → 3/2 | s:bd lpf:2000 ]",
+ "[ 3/2 → 2/1 | s:sd lpf:2000 ]",
+ "[ 1/1 → 4/3 | s:hh lpf:2000 ]",
+ "[ 4/3 → 5/3 | s:hh lpf:2000 ]",
+ "[ 5/3 → 2/1 | s:hh lpf:2000 ]",
+ "[ 2/1 → 5/2 | s:bd lpf:1000 ]",
+ "[ 5/2 → 3/1 | s:sd lpf:1000 ]",
+ "[ 2/1 → 7/3 | s:hh lpf:1000 ]",
+ "[ 7/3 → 8/3 | s:hh lpf:1000 ]",
+ "[ 8/3 → 3/1 | s:hh lpf:1000 ]",
+ "[ 3/1 → 7/2 | s:bd lpf:500 ]",
+ "[ 7/2 → 4/1 | s:sd lpf:500 ]",
+ "[ 3/1 → 10/3 | s:hh lpf:500 ]",
+ "[ 10/3 → 11/3 | s:hh lpf:500 ]",
+ "[ 11/3 → 4/1 | s:hh lpf:500 ]",
+]
+`;
+
+exports[`runs examples > example "lpq" example index 0 1`] = `
+[
+ "[ 0/1 → 1/2 | s:bd lpf:2000 lpq:0 ]",
+ "[ 1/2 → 1/1 | s:sd lpf:2000 lpq:0 ]",
+ "[ 0/1 → 1/4 | s:hh lpf:2000 lpq:0 ]",
+ "[ 1/4 → 1/2 | s:hh lpf:2000 lpq:0 ]",
+ "[ 1/2 → 3/4 | s:hh lpf:2000 lpq:0 ]",
+ "[ 3/4 → 1/1 | s:hh lpf:2000 lpq:0 ]",
+ "[ 1/1 → 3/2 | s:bd lpf:2000 lpq:10 ]",
+ "[ 3/2 → 2/1 | s:sd lpf:2000 lpq:10 ]",
+ "[ 1/1 → 5/4 | s:hh lpf:2000 lpq:10 ]",
+ "[ 5/4 → 3/2 | s:hh lpf:2000 lpq:10 ]",
+ "[ 3/2 → 7/4 | s:hh lpf:2000 lpq:10 ]",
+ "[ 7/4 → 2/1 | s:hh lpf:2000 lpq:10 ]",
+ "[ 2/1 → 5/2 | s:bd lpf:2000 lpq:20 ]",
+ "[ 5/2 → 3/1 | s:sd lpf:2000 lpq:20 ]",
+ "[ 2/1 → 9/4 | s:hh lpf:2000 lpq:20 ]",
+ "[ 9/4 → 5/2 | s:hh lpf:2000 lpq:20 ]",
+ "[ 5/2 → 11/4 | s:hh lpf:2000 lpq:20 ]",
+ "[ 11/4 → 3/1 | s:hh lpf:2000 lpq:20 ]",
+ "[ 3/1 → 7/2 | s:bd lpf:2000 lpq:30 ]",
+ "[ 7/2 → 4/1 | s:sd lpf:2000 lpq:30 ]",
+ "[ 3/1 → 13/4 | s:hh lpf:2000 lpq:30 ]",
+ "[ 13/4 → 7/2 | s:hh lpf:2000 lpq:30 ]",
+ "[ 7/2 → 15/4 | s:hh lpf:2000 lpq:30 ]",
+ "[ 15/4 → 4/1 | s:hh lpf:2000 lpq:30 ]",
+]
+`;
+
exports[`runs examples > example "lrate" example index 0 1`] = `
[
"[ 0/1 → 1/1 | n:0 s:supersquare leslie:1 lrate:1 ]",
@@ -3048,35 +3077,6 @@ exports[`runs examples > example "reset" example index 0 1`] = `
]
`;
-exports[`runs examples > example "resonance" example index 0 1`] = `
-[
- "[ 0/1 → 1/2 | s:bd cutoff:2000 resonance:0 ]",
- "[ 1/2 → 1/1 | s:sd cutoff:2000 resonance:0 ]",
- "[ 0/1 → 1/4 | s:hh cutoff:2000 resonance:0 ]",
- "[ 1/4 → 1/2 | s:hh cutoff:2000 resonance:0 ]",
- "[ 1/2 → 3/4 | s:hh cutoff:2000 resonance:0 ]",
- "[ 3/4 → 1/1 | s:hh cutoff:2000 resonance:0 ]",
- "[ 1/1 → 3/2 | s:bd cutoff:2000 resonance:10 ]",
- "[ 3/2 → 2/1 | s:sd cutoff:2000 resonance:10 ]",
- "[ 1/1 → 5/4 | s:hh cutoff:2000 resonance:10 ]",
- "[ 5/4 → 3/2 | s:hh cutoff:2000 resonance:10 ]",
- "[ 3/2 → 7/4 | s:hh cutoff:2000 resonance:10 ]",
- "[ 7/4 → 2/1 | s:hh cutoff:2000 resonance:10 ]",
- "[ 2/1 → 5/2 | s:bd cutoff:2000 resonance:20 ]",
- "[ 5/2 → 3/1 | s:sd cutoff:2000 resonance:20 ]",
- "[ 2/1 → 9/4 | s:hh cutoff:2000 resonance:20 ]",
- "[ 9/4 → 5/2 | s:hh cutoff:2000 resonance:20 ]",
- "[ 5/2 → 11/4 | s:hh cutoff:2000 resonance:20 ]",
- "[ 11/4 → 3/1 | s:hh cutoff:2000 resonance:20 ]",
- "[ 3/1 → 7/2 | s:bd cutoff:2000 resonance:30 ]",
- "[ 7/2 → 4/1 | s:sd cutoff:2000 resonance:30 ]",
- "[ 3/1 → 13/4 | s:hh cutoff:2000 resonance:30 ]",
- "[ 13/4 → 7/2 | s:hh cutoff:2000 resonance:30 ]",
- "[ 7/2 → 15/4 | s:hh cutoff:2000 resonance:30 ]",
- "[ 15/4 → 4/1 | s:hh cutoff:2000 resonance:30 ]",
-]
-`;
-
exports[`runs examples > example "restart" example index 0 1`] = `
[
"[ 0/1 → 1/2 | s:bd ]",
diff --git a/website/src/config.ts b/website/src/config.ts
index 6b7579e9..8d4d364e 100644
--- a/website/src/config.ts
+++ b/website/src/config.ts
@@ -76,6 +76,7 @@ export const SIDEBAR: Sidebar = {
{ text: 'REPL', link: 'technical-manual/repl' },
{ text: 'Docs', link: 'technical-manual/docs' },
{ text: 'Testing', link: 'technical-manual/testing' },
+ { text: 'Packages', link: 'technical-manual/packages' },
// { text: 'Internals', link: 'technical-manual/internals' },
],
},
diff --git a/website/src/pages/learn/effects.mdx b/website/src/pages/learn/effects.mdx
index 96a72afe..afe1c63c 100644
--- a/website/src/pages/learn/effects.mdx
+++ b/website/src/pages/learn/effects.mdx
@@ -12,13 +12,98 @@ import { JsDoc } from '../../docs/JsDoc';
Whether you're using a synth or a sample, you can apply any of the following built-in audio effects.
As you might suspect, the effects can be chained together, and they accept a pattern string as their argument.
-## bandf
+# Filters
-
+Filters are an essential building block of [subtractive synthesis](https://en.wikipedia.org/wiki/Subtractive_synthesis).
+Strudel comes with 3 types of filters:
-## bandq
+- low-pass filter: low frequencies may _pass_, high frequencies are cut off
+- high-pass filter: high frequencies may _pass_, low frequencies are cut off
+- band-pass filters: only a frequency band may _pass_, low and high frequencies around are cut off
-
+Each filter has 2 parameters:
+
+- cutoff: the frequency at which the filter starts to work. e.g. a low-pass filter with a cutoff of 1000Hz allows frequencies below 1000Hz to pass.
+- q-value: Controls the resonance of the filter. Higher values sound more aggressive. Also see [Q-Factor](https://en.wikipedia.org/wiki/Q_factor)
+
+## lpf
+
+
+
+## lpq
+
+
+
+## hpf
+
+
+
+## hpq
+
+
+
+## bpf
+
+
+
+## bpq
+
+
+
+## vowel
+
+
+
+# Amplitude Envelope
+
+The amplitude [envelope]() controls the dynamic contour of a sound.
+Strudel uses ADSR envelopes, which are probably the most common way to describe an envelope:
+
+
+
+[image link](https://commons.wikimedia.org/wiki/File:ADSR_parameter.svg)
+
+## attack
+
+
+
+## decay
+
+
+
+## sustain
+
+
+
+## release
+
+
+
+# Dynamics
+
+## gain
+
+
+
+## velocity
+
+
+
+# Panning
+
+## jux
+
+
+
+## juxBy
+
+
+
+## pan
+
+
+
+# Waveshaping
## coarse
@@ -28,50 +113,10 @@ As you might suspect, the effects can be chained together, and they accept a pat
-## cutoff
-
-
-
-## gain
-
-
-
-## hcutoff
-
-
-
-## hresonance
-
-
-
-## pan
-
-
-
-## resonance
-
-
-
## shape
-## velocity
-
-
-
-## vowel
-
-
-
-## jux
-
-
-
-## juxBy
-
-
-
# Global Effects
## Local vs Global Effects
diff --git a/website/src/pages/learn/synths.mdx b/website/src/pages/learn/synths.mdx
index f11388de..69c45394 100644
--- a/website/src/pages/learn/synths.mdx
+++ b/website/src/pages/learn/synths.mdx
@@ -28,15 +28,3 @@ The power of patterns allows us to sequence any _param_ independently:
Now we not only pattern the notes, but the sound as well!
`sawtooth` `square` and `triangle` are the basic waveforms available in `s`.
-
-## Ampltude Envelope
-
-You can control the envelope of a synth using the `attack`, `decay`, `sustain` and `release` functions:
-
->").s('sawtooth')
- .attack(.1).decay(.1).sustain(.2).release(.1)`}
-/>
-
-
diff --git a/website/src/pages/technical-manual/packages.mdx b/website/src/pages/technical-manual/packages.mdx
index b4beeda6..974b9f43 100644
--- a/website/src/pages/technical-manual/packages.mdx
+++ b/website/src/pages/technical-manual/packages.mdx
@@ -1,10 +1,79 @@
+---
+title: Strudel Packages
+layout: ../../layouts/MainLayout.astro
+---
+
+import { MiniRepl } from '../../docs/MiniRepl';
+
## Strudel Packages
+The [strudel repo](github.com/tidalcycles/strudel) is organized into packages, using [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces).
+Publishing packages is done with [lerna](https://lerna.js.org/).
+
There are different packages for different purposes. They..
- split up the code into smaller chunks
- can be selectively used to implement some sort of time based system
-Please refer to the individual README files in the [packages folder](https://github.com/tidalcycles/strudel/tree/main/packages)
+[See the latest published packages on npm](https://www.npmjs.com/search?q=%40strudel.cycles).
-TODO
+### Important bits
+
+- The [root package.json](https://github.com/tidalcycles/strudel/blob/main/package.json) specifies `packages/*` as `workspaces`
+- Each folder in `packages` comes with its own `package.json`, defining a package name of the format `@strudel.cycles/`
+- Running `npm i` from the root folder will symlink all packages to the `node_modules` folder, e.g. `node_modules/@strudel.cycles/core` symlinks `packages/core`
+- These symlinks allow importing the packages with their package name, instead of a relative path, e.g. `import { seq } from '@strudel.cycles/core'`, instead of `import { seq } from '../core/`.
+ This works because the [bare module import](https://vitejs.dev/guide/features.html#npm-dependency-resolving-and-pre-bundling) `@strudel.cycles/core` is resolved to `node_modules/@strudel.cycles/core`.
+ In a project that installs the published packages from npm, these imports will still work, whereas relative ones might not.
+- When a strudel package is importing from another strudel package, the package that is imported from should be listed in the `dependencies` field of the `package.json`.
+ For example, [@strudel.cycles/mini lists `@strudel.cycles/core` as a dependency](https://github.com/tidalcycles/strudel/blob/main/packages/mini/package.json).
+- In development, files in any package can be changed and saved to instantly update the dev server via [hot module replacement](https://vitejs.dev/guide/features.html#hot-module-replacement)
+- To publish packages, `npx lerna publish` will check which packages were changed since the last publish and publish only those.
+ The version numbers in the dependencies of each packages will be updated automatically to the latest version.
+
+### Building & Publishing
+
+Currently, all packages are only published as ESM with vite flavour.
+To build standardized ESM and CJS files, a `vite.config.js` like that is needed:
+
+```js
+import { defineConfig } from 'vite';
+import { dependencies } from './package.json';
+import { resolve } from 'path';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [],
+ build: {
+ lib: {
+ entry: resolve(__dirname, 'index.mjs'),
+ formats: ['es', 'cjs'],
+ fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' }[ext]),
+ },
+ rollupOptions: {
+ external: [...Object.keys(dependencies)],
+ },
+ target: 'esnext',
+ },
+});
+```
+
+This will build `index.mjs` (ESM) and `index.js` (CJS) to the dist folder.
+
+### What's the main file?
+
+Currently, each package uses the unbundled `index.mjs` as its main file, which must change for the published version.
+There are 2 ways to handle this:
+
+1. `main` = `dist/index.js`, `module` = `dist/index.mjs`. The built files are used. This means that changing a source file won't take effect in the dev server without a rebuild.
+2. Use different `package.json` files for dev vs publish. So the unbuilt `index.mjs` could be used in dev, while the built files can be used when publishing.
+
+Option 1 could be done with [workspace watching](https://lerna.js.org/docs/features/workspace-watching), although it might make the dev server less snappy..
+Option 2 can be done by [publishing just the dist folder and copying over the `package.json` file](https://stackoverflow.com/questions/37862712/how-to-publish-contents-only-of-a-specific-folder).
+Sadly, [this does not fit into how lerna works](https://github.com/lerna/lerna/issues/91).
+
+https://github.com/changesets/changesets
+
+https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing
+
+https://pnpm.io/workspaces