# Audio-Rate Modulation Any parameter can be modulated continuously using modulation words. Instead of a fixed value, these words produce a modulation string that the engine interprets as a moving signal. All time values are in **steps**, just like `attack`, `decay`, and `release`. At 120 BPM with speed 1, one step is 0.125 seconds. Writing `4 lfo` means a 4-step period. ## LFOs Oscillate a parameter between two values. ```forth saw snd 200 4000 4 lfo lpf . ( sweep filter over 4 steps ) saw snd 0.3 0.7 2 tlfo pan . ( triangle pan over 2 steps ) ``` | Word | Shape | Output | |------|-------|--------| | `lfo` | Sine | `min~max:period` | | `tlfo` | Triangle | `min~max:periodt` | | `wlfo` | Sawtooth | `min~max:periodw` | | `qlfo` | Square | `min~max:periodq` | Stack effect: `( min max period -- str )` ## Slides Transition from one value to another over a duration. ```forth saw snd 0 1 0.5 slide gain . ( fade in over half a step ) saw snd 200 4000 8 sslide lpf . ( smooth sweep over 8 steps ) ``` | Word | Curve | Output | |------|-------|--------| | `slide` | Linear | `start>end:dur` | | `expslide` | Exponential | `start>end:dure` | | `sslide` | Smooth (S-curve) | `start>end:durs` | Stack effect: `( start end dur -- str )` ## Random Randomize a parameter within a range, retriggering at a given period. ```forth saw snd 200 4000 2 jit lpf . ( new random value every 2 steps ) saw snd 200 4000 2 sjit lpf . ( same but smoothly interpolated ) saw snd 200 4000 1 drunk lpf . ( random walk, each step ) ``` | Word | Behavior | Output | |------|----------|--------| | `jit` | Sample & hold | `min?max:period` | | `sjit` | Smooth interpolation | `min?max:periods` | | `drunk` | Random walk | `min?max:periodd` | Stack effect: `( min max period -- str )` ## Envelope Modulation Apply an envelope to any parameter. The `env` word is the complete form: it sweeps from `min` to `max` following a full attack, decay, sustain, release shape. All times are in steps. ```forth saw snd 200 8000 0.01 0.1 0.5 0.3 env lpf . ``` Stack effect: `( min max attack decay sustain release -- str )` This is the building block. From it, three shorthands drop the parameters you don't need: | Word | Stack | What it does | |------|-------|-------------| | `env` | `( min max a d s r -- str )` | Full envelope (attack, decay, sustain, release) | | `eadr` | `( min max a d r -- str )` | No sustain (sustain = 0) | | `ead` | `( min max a d -- str )` | Percussive (sustain = 0, release = 0) | `eadsr` is an alias for `env`. ```forth saw snd 200 8000 0.01 0.3 ead lpf . ( percussive filter pluck ) saw snd 0 5 0.01 0.1 0.3 eadr fm . ( FM depth with release tail ) saw snd 200 8000 0.01 0.1 0.5 0.3 env lpf . ( full ADSR on filter ) ``` These work on any parameter — `lpf`, `fm`, `gain`, `pan`, `freq`, anything that accepts a value. ## Low Pass Gate The `lpg` word couples the amplitude envelope with a lowpass filter. Set your amp envelope first with `ad` or `adsr`, then `lpg` mirrors it to `lpf`. ```forth saw snd 0.01 0.1 ad 200 8000 1 lpg . ( percussive LPG ) saw snd 0.01 0.1 0.5 0.3 adsr 200 4000 1 lpg . ( sustained LPG ) ``` Stack effect: `( min max depth -- )` - `min`/`max` — filter frequency range in Hz - `depth` — 0 to 1, scales the filter range (1 = full, 0.5 = halfway) ```forth saw snd 0.01 0.5 ad 200 8000 0.3 lpg . ( subtle LPG, filter barely opens ) ``` `lpg` reads `attack`, `decay`, `sustain`, and `release` from the current sound. If none are set, it defaults to a short percussive shape. ## Combining Modulation words return strings, so they compose naturally with the rest of the language. Use them anywhere a parameter value is expected. ```forth saw snd 200 4000 4 lfo lpf 0.3 0.7 8 tlfo pan 0 1 0.01 0.1 ead gain . ```