Track 5 — Waves and shapes
Everything so far distorts the feedback loop — the paint already on screen. Waves and shapes are the new ink laid on top each frame, before the loop's distortion is applied to it next time around. They're not a minor feature: 88% of the bundled catalog uses custom waves, and 99% uses custom shapes — this is the layer most presets draw with.
Lesson 1 · A second waveform
Every preset has one built-in waveform (wave_r/wave_g/wave_b, the one you've been coloring since Track 1). Custom waves are additional ones, up to eight, each fully independent:
wavecode_0_enabled=1
wavecode_0_samples=200
wavecode_0_scaling=1
wavecode_0_smoothing=0.5
wavecode_0_r=1
wavecode_0_g=0.7
wavecode_0_b=0.2
wavecode_0_a=1
wavecode_0_* are static parameters — enable it, give it 200 sample points and an amber color. On its own it draws the audio waveform again, just as a second colored line. The interesting part is next.
Lesson 2 · Shaping every sample point
wave_N_per_point equations run once per sample point of the wave — the finest-grained code in the whole language, potentially hundreds of times a frame for one wave:
wave_0_per_point1=t=sample*6.283185+time*0.3;
wave_0_per_point2=x=0.5+0.3*sin(t*3)*(1+0.3*value);
wave_0_per_point3=y=0.5+0.3*cos(t*2)*(1+0.3*value);
The two inputs unique to this context:
sample— this point's position along the wave,0to1. Multiplying by6.283185(2π) turns it into a full angle sweep — the standard move whenever a wave should trace a closed curve instead of a left-to-right line.value— the actual audio sample at this point, roughly-1..1. Folding it into the radius (1+0.3*value) is how the shape stays a recognizable curve while still visibly responding to the waveform, rather than the waveform being replaced outright.
You must set x/y yourself here — nothing else positions the point. This is the fundamental deal with per-point code: total control over where every point of the wave lands, in exchange for writing the geometry from scratch.
Lesson 3 · A shape, sitting still
Custom shapes (up to four, each with 3–100 sides and up to 1024 instances) are the other half of this layer — solid polygons instead of lines:
shapecode_0_enabled=1
shapecode_0_sides=5
shapecode_0_thickoutline=1
shapecode_0_x=0.5
shapecode_0_y=0.5
shapecode_0_rad=0.15
shapecode_0_r=0.9
shapecode_0_g=0.6
shapecode_0_b=0.1
Static params only — the pentagon just sits there. shapecode_0_* mirrors wavecode_0_*: _enabled, geometry (sides, x, y, rad, ang), and color (r/g/b/a).
Lesson 4 · Giving a shape a per_frame
shape_N_per_frame runs once per frame for that shape instance — the same rhythm as the root per_frame, just scoped to one shape:
shape_0_per_frame1=x=0.5+0.25*sin(time*0.7);
shape_0_per_frame2=y=0.5+0.25*cos(time*0.7);
shape_0_per_frame3=ang=time*0.7;
Nothing new mechanically — this is Track 1's sin(time) heartbeat, just steering a shape's position instead of a screen-wide knob. shape_N_init (unused here) runs once, the first frame only, for one-time setup.
Lesson 5 · Morphing instead of moving
A shape doesn't have to move to be alive — it can change identity entirely, frame by frame. Pattern 12 from the coding guide:
shape_0_per_frame1=s=frame%6+4;
shape_0_per_frame2=sides=s;
shape_0_per_frame3=rad=0.08+s*0.01;
shape_0_per_frame4=ang=s*0.3;
shape_0_per_frame5=r=sin(s*1.1)*0.5+0.5;
shape_0_per_frame6=g=sin(s*2.2)*0.5+0.5;
shape_0_per_frame7=b=sin(s*3.3)*0.5+0.5;
frame%6+4 cycles s through 4, 5, 6, 7, 8, 9, 4, 5, … — one step every frame. Every other line reads that same s: sides count, radius, rotation, and all three color channels are just different functions of it. The shape isn't animating a fixed pentagon — it's cycling through six entirely different polygon identities, each with its own look, six times a second at 36fps-equivalent stepping. This is the technique behind shapes that seem to "breathe" between forms rather than move.
Lesson 6 · Wired to the music
Everything in this track has run on time alone. Bridge it to audio exactly the way Track 4 did — smooth in per_frame, write a q-var, read it wherever it's needed:
per_frame_1=ra=6/fps;
per_frame_2=bass_avg=bass_avg*(1-ra)+ra*bass;
per_frame_3=q8=bass_avg;
wave_0_per_point1=t=sample*6.283185+time*0.3;
wave_0_per_point2=x=0.5+(0.2+0.15*q8)*sin(t*3);
wave_0_per_point3=y=0.5+(0.2+0.15*q8)*cos(t*2);
shape_0_per_frame1=rad=0.1+q8*0.15;
shape_0_per_frame2=ang=time*0.5;
▶ Run the reactive wave and shape
q8 is computed exactly once, in the root per_frame, and both the wave's per-point code and the shape's per-frame code read the same value that frame. This is the general answer to "how do waves/shapes hear the music": they don't read audio directly — per_frame does the listening (Track 3), and everything downstream just reads the result.
What you can now build
Waves and shapes are how a preset draws something recognizable rather than just distorting a blur — lines that trace curves, polygons that orbit or morph, both wired into the same audio pipeline as everything else. Between Tracks 1–5, you can now read the per_frame/per_pixel/wave/shape portion of almost any preset in the catalog.
Next: Track 6 — Shaders, the one piece left: the GLSL warp_shader/comp_shader pair that 64% of modern presets use for the effects equations alone can't reach.