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: + +![ADSR](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/ADSR_parameter.svg/1920px-ADSR_parameter.svg.png) + +[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