diff --git a/website/src/pages/learn/lfo.mdx b/website/src/pages/learn/lfo.mdx new file mode 100644 index 00000000..d4dfd273 --- /dev/null +++ b/website/src/pages/learn/lfo.mdx @@ -0,0 +1,294 @@ +--- +title: Low-frequency oscillators (LFO) +layout: ../../layouts/MainLayout.astro +--- + +import { MiniRepl } from '../../docs/MiniRepl'; +import { JsDoc } from '../../docs/JsDoc'; + +# Low frequency oscillators (LFO) + +A low frequency oscillator (or short LFO) is a common way on synthesizers to continuously modulate various signals. + +This documentation is an interactive version of glossing's tutorial https://www.youtube.com/watch?v=11frBA9L638 + +## Applying an LFO + +Here, the LFO will change the frequency of the `saw`. Put a comment like this `//.lfo()` to see and hear how it changes, and remove the comment again. + + + +By default, the LFO will modulate the control parameter which is right before `.lfo()`: + + + +Here, the LFO will modulate the low pass filter `.lpf`. + +## Moving away from the default + +The following sections explain how pass parameters to `.lfo`. Similar to `._spectrum` above, almost all the configuration of `lfo` lives inside a json object, starting with `{` and ending with `}`. +All the parameters (except `id`) are written as `key: value` inside and separated by `,`. + +The reference refers to them as `config.key`, i.e. for the following one as `config.control` but you use them like below. + +## Control + +`control` determines which parameter will be modulated. This allows you to place your `lfo` at different places, +not necessarily immediately after the controlled parameter. + +Here, we place `lfo` after the `s`, but it modulates the low pass filter. + + +You can even influence parameters which are always present, even if you haven't explicitly written them, like `gain`. + + + +`control` has an alias `c`. + +## Rate + +`rate` determines how often the `lfo` oscillates per second: + +"}) + .lpf(800) + ._spectrum({height: 300, width: 800})`} +/> +The alias of `rate` is `r`.{' '} + +## Sync + +Instead of controlling the frequency with `rate` by setting a frequency in Hz, you can use `sync` +to snychronize your lfo with your other patterns. + +`sync` expresses this frequency as "times per cycle" + +Try removing the `sync: "<2 4 8 0.5 >"` from the pattern and notice that there is something not in sync. + +"}) + ._spectrum({height: 300, width: 800})`} +/> + +You can put patterns into the parameters of `lfo` if you want them to change over time, as seen above. + +## Relative Depth + +`.depth` is relative depth, a value of 1 (the default) means that +the value goes above and below by half of the value which is being modulated + +E.g. for depth `1`, it modulates the frequency to oscillate between 32 = (64/2) and 96 (= 64 + 64/2). + +"}) + .lpf(800) + ._spectrum({height: 300, width: 800})`} +/> +The `freq` is not needed here, as this is the default frequency, it's just for instructive purposes. + +The aliases of `depth` are `dr` and `dep`. + +## Absolute Depth + +`depthabs` controls the absolute modulation depth. For example you can modulate +the low pass filter by exactly 250 Hz up and below: + + + +The alias of `depthabs` is `da`. + +## DC offset + +If you don't want to go up or down by the same amount with your modulation, then you can shift the center of the modulation with `dcoffset`. +The default value is -0.5, which is the middle point between: +"dcoffset = 0: All modulations increase the control parameter (or keep it constant)" +"dcoffset = -1: All modulations decrease the control parameter (or keep it constant)" + +Other values will work as well. + +"})`} +/> +The marvellous alias of `dcoffset` is `dc`. + +## Shape + +You can change the shape of the modulation with `shape`. The default is `triangle`, but other shapes are available too: + +"}) `} +/> +You can add `._spectrum()` to see the shape of the modulations in the spectrum. + +You can also get these shapes by using numbers: + +| Shape | number | +| -------- | ------ | +| triangle | 0 | +| sine | 1 | +| ramp | 2 | +| saw | 3 | +| square | 4 | + +this way, you can use a function like `irand` to generate numbers: + + + +The alias of `shape` is `sh`. + +## Skewing some shapes + +You can influence some of the shapes (`triangle` and `square`) in more detail. + +The default skew is 0.5, it does different things for these two. + +For `triangle`, it skews the top of the triangle to the left or right, +where 0 makes it look like `saw` and 1 makes it look like `ramp`. + +For `square`, the skew influences the pulse width (see reference for `pulse` and `.pw`): + +/5", + skew: "<0 0.25 0.5 0.75 1>"}) `} +/> +The alias of `skew` is `sk`.{' '} + +## Curve + +You can change the curves of your lfo and can make it more intense. +The default value is 1. Writing numbers greater than one can make it more intense, +numbers between 0 and 1 will make it less intense. +This will raise the lfo to the power of curve, so larger numbers (such as 10) can have very unexpected results. + +", curve: "<1.3 1 0.75 1>"}) `} +/> +## Referencing your lfos with id + +All the lfos are numbered from the first starting with 0, the second having an `id` of 1 and so on. + +You can refer to this in a later call if you want to modify a specific `lfo`. + +The ´id´ is outside of the config json (which is different from the other parameters of `lfo()` + +Try out how the sound changes when you replace the 0 with a 1. + +"}) +.sometimes(x => x.lfo({dr: "4"},0))`} +/> + +You can also name your lfos and refer to them by name, using the `id` parameter + +"}, "lfo_lpf") +.sometimes(x => x.lfo({dr: "4"},""))`} +/> + +## FX index + +If you are using `FX()` to reorder your effects, you dont need to write your lfos inside the `FX`, +but instead can refer to them by their FX index (starting with 0) + + + +## Modulating other LFOs with Sub-control + +LFOs can modulate other lfos and will modulate their frequency (given by `r` or `s`): + + +To modulate other parameters of the first lfo (like `skew`, `depth` and so on), we can specify this with `subControl`or +its alias `sc` + +