all 35 waves

Each wave is a deterministic function: pass a number in, get a number back. The output range is roughly [−0.5, +0.5] before you scale it. Every preview here is traced live in SVG - no <canvas> - and the numbers are bit-identical to p5.waves v3.6.0.

idx name formula harsh = breaks rhythm closing = periodic at 2π·n T = measured period (— = no clean close)

Pure sine

The reference shapes. Smooth, periodic, easy to predict.

00
classic sine
sin(x*.1)*.4
gentleclosingT 62.83
01
sine
sin(x*.2)*.25
gentleclosingT 31.42
02
sharp peaks
abs(sin(x*.1))*.5
gentleclosingT 31.42
33
smooth solid sine
sin(x*3.1)*.25
gentleclosingT 2.03

Peaks & valleys

Modulated sines that emphasise crests or troughs.

06
mountain peaks
abs(cos(x*.1))*.35 + sin(x*.1)*.25
gentleclosingT 62.83
07
valleys
abs(cos(x*.1))*-.35 + sin(x*.1)*.25
gentleclosingT 62.83
09
batman
sin(x*.1)*.7 % .4
gentleclosingT 62.83
10
offset sine
ceil(cos(x*.1))*.25 − sin(x*.1)*.25
gentleclosingT 62.83

Stepped & pulses

Quantised waves: ceil / round / modulo carve smooth shapes into plateaus.

05
stepped sine
ceil(sin(x*.1))*.25
gentleclosingT 62.60
11
steps down
ceil(tan(x*.1))*.25
harshclosingT 31.42
12
steps
round(sin(−x*.1))*.25
gentleclosingT 62.82
08
zig-zag sine
sin(x*.2)*.4 % .12
gentleclosingT 31.42
03
square
(x*.025)%1 < .5 ? −.5 : .5
gentleT 40
04
pulse
(x*.5)%20 < 1 ? −.5 : .5
gentleT 40

Layered & modulated

Two or more sines multiplied, added, or modulated.

13
squared sine
sq(sin(x*.1))*.25
gentleclosingT 31.42
14
bumpy sine
sin(x*.1)*.25 + sin(x*.5)*.1
gentleclosingT 62.83
15
wobble sine
sin(x*.1)*cos(x*.2)*.5
gentleclosingT 62.83
17
meta sine
sin(x*.45 + radians(x))*cos(x*.4)*.5
gentleT —
31
round linked sine
sin(x*.1)*cos(x*1)*.5
gentleclosingT 62.83
29
ramp up sine
sin(x)*(x*.01%.5)
gentleT —
30
triangle sine
sin(x)*(x*.01%1−.5)
gentleT —
32
half sine
sin(x*.05)*(x*.1%.5)
harshT —

Linear & saw

No trig, just modulo and absolute value. Sharp, predictable.

18
triangle
abs((x*.03) % 1 − .5)
gentleT 33.33
19
ramp
−(x*.02%1) + .5
gentleT 50
20
saw down
x*.03 % .5
gentleT 16.67
21
saw up
−x*.03 % .5
gentleT 16.67

Chaos & special

Tangents, noise, logarithms and random values. Most are flagged harsh: they use a seeded PRNG or a non-trig function with surprising spikes.

16
up down noise
x*sin(x*.1) % .5
harshT —
22
shake out
sin(log(sq(min(abs(x)%62.8319,62.8319-abs(x)%62.8319))+1)*3)*.5
gentleclosingT 62.83
23
grow random
random(x*.003)
harshT —
24
noise
noise(x*.1) − .5
harshT —
25
fuzzy pulse
tan(x*20)*.05
harshT 17.75
26
up down pulse
tan(x*.1)*.05
harshclosingT 31.42
27
bald patch
sq(x*.05) % .5
harshT —
28
fuzzy peak sine
sin(x*.1) < 0 ? random(−.2, .2) : sin(x*.1)*.5
harshT —
34
spike sine
sq(sq(sin(x*.1)))*sin(x*.1)*.5
gentleclosingT 62.83

Periodicity

A wave is periodic when there is a distance T such that wave(x) == wave(x + T) for every x. That distance is the wave's period. Knowing it lets you close a shape cleanly: sample a wave around a ring over an integer number of periods and the last point lands exactly on the first - no seam.

Period coordinates. wave(x) treats x as a generic coordinate - the same mental model as noise(x) - not an angle. Nine of the 35 waves are not sine-based at all (square, triangle, ramp, noise…), so radians would be meaningless for them.

Every period value was measured, not derived: the periodicity harness in the p5.waves repo samples each wave, finds the smallest T where the mean error between wave(x) and wave(x + T) stays below 0.002, then confirms with multiples. vanilla.waves produces numerically identical output, so the same periods hold.

Closed-ring recipe (canvasless)

Build an SVG path from the sampled values. Set an integer lobes count and read the sweep from sampler.period. Use the closing group when shifting; its periods are measured approximations (see the guide).

// A closed wobble ring in SVG. No visible seam.
const ring = VanillaWaves.createSampler({
  group: 'closing', shift: true, amplitude: 30
});
const lobes = 8, steps = 240;
const sweep = ring.period * lobes;   // integer multiple = clean close

let d = '';
for (let i = 0; i < steps; i++) {
  const a = (i / steps) * Math.PI * 2;
  const r = 140 + ring.sample(i / steps * sweep, t);
  d += (i ? 'L' : 'M') + (200 + r*Math.cos(a)) + ' ' + (200 + r*Math.sin(a));
}
path.setAttribute('d', d + 'Z');   // Z closes it

Quick lookup

26 waves close cleanly, 9 don’t. Each card above also shows its measured period.

Period TWaves
2.0333 smooth solid sine
16.6720 saw down, 21 saw up
17.7525 fuzzy pulse (valid close, not the fundamental)
31.421 sine, 2 sharp peaks, 8 zig-zag sine, 11 steps down, 13 squared sine, 26 up down pulse
33.3318 triangle
403 square, 4 pulse
5019 ramp
62.830 classic sine, 5 stepped sine, 6 mountain peaks, 7 valleys, 9 batman, 10 offset sine, 12 steps, 14 bumpy sine, 15 wobble sine, 22 shake out, 31 round linked sine, 34 spike sine
—no clean close: 16 up down noise, 17 meta sine, 23 grow random, 24 noise, 27 bald patch, 28 fuzzy peak sine, 29 ramp up sine, 30 triangle sine, 32 half sine

How to read the result

For a shape that stays closed while shifting between formulas, use group: 'closing' - a pool of 19 waves that all share the base period 62.8319 - and read the sweep from sampler.period. See Closing shapes in the guide.