A waveshaper forgets each sample the moment it is done with it. A filter cannot: to smooth a signal it has to remember where it was. process2 gives your law memory — a state cell it reads at every sample and hands back updated — and with one cell you can build the most important filter there is.
process2 (\x s -> [out, next]) 0.0 passes the law the input x and the cell s, and expects a list back: what to play, and what s should be on the next sample. The 0.0 after the lambda is the cell's starting value.
The one-pole lowpass is one line of state: y = s + a * (x - s) — move a fraction a of the way from where you were toward the input. Small a means slow, dark, smooth; a = 1 passes everything.
To tune it in Hz, the fraction comes from the cutoff and the sample rate: a = 1 - exp(-2π·cut / sampleRate). sampleRate is readable only inside kernels, and a let that depends only on it and constants is computed once per block, not per sample.
Write the law as a named lambda with the cutoff first — onePoleLp = \cut x s -> … — and apply it partially: process2 (onePoleLp 800.0) 0.0. The recipe's leading arguments can be numbers or macros; the rest are the kernel's.
The starting point#
The lesson opens with this song in the editor. Every edit recompiles and plays.
-- State: this pluck is a raw saw — every harmonic, all the way up.
-- Give it a filter you write yourself.
pluck = patch {
source = saw (freq pitch),
ampEnv = adsr 2ms 220ms 0 120ms,
gain = vel * 0.2
}
line = play pluck !"a2 c3 e3 a3 g3 e3 c3 e3"
What to watch#
Watch the spectrum while you lower the cutoff: the upper bars fall away at 6 dB per octave — gently, compared with the builtin 12 dB filters — and the scope's saw teeth round off into curves.
Goals#
The workbench checks these as you work; the solution is there when you want it.
- Give the kernel memory:
process2 (\x s -> [y, y]) 0.0 - Tune it in Hz with
sampleRate - Stretch: ride the cutoff with a macro
Make it yours#
Return x - y instead of y (keep y as the next state): the same one cell becomes a highpass. Then chain a lowpass and a highpass to make a band.
Further reading#
Write a custom audio processor in the reference.