A cell remembers one number. A delay line remembers the last second of them. Put dline 500ms in a kernel's init and the matching binder becomes a line you can read from any point in its past — which is all an echo, a chorus, a comb filter or a reverb really is.
process2 (\x line -> [x + 0.5 * dtapi line 12000.0, x]) (dline 500ms): dtapi line d reads the sample from d samples ago (d = 1 is the previous one), and the list's second element is what goes into the line this sample.
Feed the output back in instead of the input — push x + fb * delayed — and each repeat carries the next: a feedback echo. Keep fb below 1 or the repeats never die.
An echo belongs on the track, not in the patch: a voice kernel's line starts empty at every note and stops with the voice. play … |> audioFx (\bus -> bus |> process2 echoLaw [dline 1s]) runs the kernel once on the track's stereo bus, and its line keeps ringing across notes.
dtap (no i) reads between samples with Hermite interpolation — move its offset with an LFO-driven phase and the echo becomes a chorus.
The starting point#
The lesson opens with this song in the editor. Every edit recompiles and plays.
-- Delay lines: a dry pluck. Give it an echo you write yourself.
pluck = patch {
source = pulse (freq pitch) 0.3,
ampEnv = adsr 1ms 160ms 0 60ms,
gain = vel * 0.3
}
melody = play pluck !"e4 ~ g4 ~ b4 ~ ~ ~"
What to watch#
Play a single note and watch the scope: copies of the note march away at the delay time, each one smaller by your feedback factor.
Goals#
The workbench checks these as you work; the solution is there when you want it.
- Give the kernel a delay line:
dline 500ms - Run it on the track with
audioFxso the echoes outlive the note - Stretch: a stereo ping-pong with
processS
Make it yours#
Put a one-pole lowpass inside the loop so each repeat is darker than the last — the tape-echo sound. You need a cell for the filter beside the line: [0.0, dline 1s].
Further reading#
Write a custom audio processor in the reference.