#name starts a new effect; slider positions travel with the text as the #param start value; #off under a name bypasses that effect.
Or write your own:
One statement per line. The value of the last line becomes the output sample. The code runs once per sample, per channel.
Any name you haven't declared as a parameter is state: it keeps its value into the next sample and starts at 0. That is how you write filters and envelopes.
Lines starting with # are directives, // is a comment.
#name My effect#param drive 4 1 40 — name, start, min, max. Becomes a slider.#param steps 4 1 8 1 — a fifth number makes it move in steps and jump instead of glide.#param scale 0 0 2 1 chromatic major minor — words after the step name each position; _ shows as a space.x input sample, −1…1t seconds, n sample countsr sample rate, ch channel (0 = left)pi, esin cos tan tanh atan exp log sqrt abs sign floor ceil round min max pow mod clamp noise bshift pshift psola pitch vocoder
Four per effect, up to 2 seconds, fractionally interpolated. dw(v) writes, delay(n) reads n samples back. Lines 2–4 use dw2 delay2 … dw4 delay4.
Echo with feedback: d = delay(time*sr) then dw(x + d*fb) then x + d*mix.
bshift(x, ratio, bands) — the low-latency pitch shifter: ratio 0.25…4; 2 is an octave up, pow(2, st/12) converts semitones. It follows within about 8 ms in the middle of the guitar (about 24 ms on a low E), because it works on a bank of filters instead of a window. bands per octave is a plain number from 6 to 48, default 24: more holds chords together, 16 is a little quicker and lighter on single notes. Two calls on x with the same bands share their filters. Not inside ?:.
pshift(x, ratio, ms) — the most accurate pitch shifter, with a delay: ratio 0.25…4; 2 is an octave up, pow(2, st/12) converts semitones. ms is the analysis window, a plain number, default 85. It is also how late the shifted signal arrives, and the latency readout includes it. Longer holds chords together, shorter reacts faster. Call it on every sample, not inside ?:.
pitch(x, ms) — the detected pitch of x in Hz, 0 when nothing periodic is playing. Window default 43 ms (lowest note about 50 Hz); 85 reaches a bass's low E. Updates every quarter window, adds no delay to the signal. Same rule: not inside ?:.
psola(x, ratio, lowest) — a pitch shifter for one voice or single notes. It keeps a voice sounding like the same person (no chipmunk), and its delay is set by the lowest note it has to follow: lowest in Hz, a plain number, default 75, gives 27 ms; 150 gives 13 ms. On chords, or for big jumps on an instrument, use bshift. Not inside ?:.
vocoder(voice, carrier, bands) — gives carrier (any sound you make in the formula, usually a synth) the changing tone of voice, so the synth seems to talk. bands is a plain number from 8 to 32, default 20: more is clearer, fewer more robotic. No added delay. Not inside ?:.
+ - * / % ^ < > <= >= == != && || ! cond ? a : b
Any recirculating loop has a DC gain of 1/(1−g), so a small standing offset grows until it eats the headroom. DC block handles the input; inside your own loop, subtract it first: s = x - px + 0.997*s then px = x.
Each channel is processed on its own, so an effect can't mix left into right. Use ch to make the two sides behave differently.
Parameters glide over about 10 ms when you move a slider, so sweeps don't click.
Everything here stays free.
The browser version plays for an hour at a time. Continue for another hour, or get the app for uninterrupted sound.