Eighteen read-only variables carry the live audio analysis into your expressions,
plus five that carry position rather than sound: index for a per-element
evaluation, and x/y/rad/ang for a per-vertex one.
Variable
Meaning
Notes
bass
Bass-band level (~20–250 Hz), as a fraction of its own recent peak.
0–1.> 0.5 means “loud for this track”.
mid
Mid-band level (~250–4000 Hz), same basis.
0–1.
treb
Treble-band level (~4–18 kHz), same basis.
0–1; reads lowest of the three on most material.
onset
Onset/attack strength, as a fraction of its own recent peak.
0–1. A transient, not a level — spikes on hits.
beat
1.0 on a hop where a beat fired, else 0.0.
A gate: beat * k adds k only on beat frames.
bar
Beat phase in [0, 1): 0 on each beat, ramping to the next.
A misnomer kept for compatibility — for real bar position use bar_phase.
time
The scene clock in seconds (monotonic).
Use time * k for slow drift; k sets the speed.
tempo
Tracked tempo in BPM.
Not a 0–1 band — see the warning below.
novelty
Spectral-change transient: ~0 within a steady segment, spiking at a track/section boundary.
Experimental — see below.
bass_raw
Absolute bass magnitude — the pre-normalization value.
Raw and small (mean 0.040): multiply up and clamp.
mid_raw
Absolute mid magnitude.
Raw and small (mean 0.006).
treb_raw
Absolute treble magnitude.
Raw and small (mean 0.006).
onset_raw
Absolute spectral flux.
Raw and very small (mean 0.002).
beat_index
Monotone onset counter, 0 before the first detection.
Integer-valued, and not a musical period — mod(beat_index, 4) is not “every 4th beat”. See Musical time.
time_since_beat
Seconds since the last beat; exactly 0 on a beat hop.
A retriggered ramp — good for decays.
beat_in_bar
Which beat of the bar, 0–3.
beat_in_bar == 0 is the downbeat.
bar_index
Bar counter — monotone except across an alignment change.
mod(bar_index, 8) for an 8-bar arc, which a lock can repeat or drop one bar of.
bar_phase
Position across the whole bar, [0, 1).
The genuine bar phase, unlike bar.
balance
Where the mix sits between the two channels: -1 hard left, 0 centred, +1 hard right.
Absolute, never levelled — and 0 on any mono source, forever. See below.
spread
How decorrelated the channels are: 0 identical, 0.5 fully decorrelated, 1 polarity-inverted.
Absolute too. 0.5 means decorrelated, not “half wide”.
bass_balance
balance over the bass band alone.
Same bands as bass/mid/treb. 0 when that band is silent.
mid_balance
balance over the mid band alone.
The expressive one: hats thrown sideways while the bass stays centred.
treb_balance
balance over the treble band alone.
index
The element’s own position in [0, 1] during a per-element evaluation.
The vertex’s position in [0, 1] during a per-vertex evaluation; y = 0 is the top.
Not audio. 0 outside a [per_vertex] table — see below.
rad
That vertex’s distance from the centre, aspect-corrected against the render target.
1.0 at the middle of the top and bottom edges on any display; further at the sides of a wide one.
ang
That vertex’s angle from the centre, [0, tau), counter-clockwise from +x as you look at the screen.
0 outside a [per_vertex] table.
The four headline levels are normalized
(ADR-0049): each is
divided by its own slowly-decaying running peak, with a silence floor so a quiet room reads 0 rather
than amplified noise. That is what makes a threshold portable across tracks and
gain staging. The cost is deliberate — absolute dynamics are hidden, so a quiet
passage and a loud one read alike. When a look should scale with real loudness,
use the *_raw twin and expect the old tiny magnitudes.
The five musical-time variables come from the beat tracker, and the three
bar-position ones sit behind a confidence gate with a counter fallback, so they are
always periodic and never confidently wrong about the music. 4/4 is assumed.
None of the five is a dependable musical period.beat_index counts onset
detections rather than beats, and the bar trio is the counter fallback most of the
time — both measured, and diagnosed, in
Musical time below. Read that section before you build structure
on any of them.
tempo is the one variable that is not roughly 0–1. It is 0 until the
tempo tracker warms up (the first several seconds of audio), then jumps to a
real BPM in the ~60–200 range. Using it raw will blow out any parameter.
Either scale it (tempo / 180) or — better — compare it:
select(tempo > 128, 2.5, 0.8) # a fast look above 128 BPM, a calm one below
novelty is experimental. It is a transient that spikes when the spectrum
changes character — useful for gating an accent on a track or section change
(beat * (novelty > 0.5)). Its DSP shape may change in a later release, or it
may be withdrawn; do not build a preset that only works with today’s exact
values.
The stereo field is absolute, and that is the whole design
balance, spread and the three per-band balances are the only variables here
that are not divided by a running peak
(ADR-0215). Every
level is levelled, so bass > 0.5 means “loud for this track”; balance = 0
means centred, on every track, forever. Three consequences, and none of them is
a bug to report:
A mono source reads 0 for all five, permanently. A mono file in foobar, a
mono capture device, --signal chord or any other synthesized kind that
predates pan: — all of
them duplicate one buffer into both channels, and duplicated channels carry no
position.
A preset leaning on stereo is silently still on perfectly ordinary input.
Real music sits well inside ±0.3 of centre most of the time. Bind
balance straight to a large visual move and the picture will look static and
you will suspect the engine. Multiply up and clamp, exactly as you would with
a *_raw level: clamp(balance * 3, -1, 1).
Levelling it would have been a lie you could not detect. Divided by a
running peak, a centred mix’s noise floor stretches into confident wandering
motion — convincing, and not in the music. Loudness is always present and only
its scale is in question; position can be genuinely absent, and a normalizer
cannot represent absence.
spread’s midpoint is the one number worth memorizing. 0.5 is fully
decorrelated, not “half as wide as it gets”: 0 is two identical channels,
0.5 is two channels sharing nothing, and 1 is a polarity-inverted pair, which
almost nothing but a test signal produces. A mono mix sits at 0; a wide one
averages well below 0.5 and only touches the top of the range in moments —
see the measured table below — so the useful gate is spread > 0.25 rather than
anything near 1.
The field is published raw, per hop, with no smoother — the same choice the
*_raw levels make. A hop is 10.7 ms, about one cycle of a low bass note, so
spread in particular jitters on bass-heavy material. Ease it yourself with
[smoothing]; a
smoother inside the analyzer would be a second opinion you could not turn off.
To see what a source actually produces, every --signal / --audio filmstrip
prints balance and spread rows beside the band rows
(capturing), and --signal pan:<p>,
wide:<seed> and split:<p> synthesize stereo on demand.
What real music reads, measured rather than guessed. Three 60-second clips of
commercial tracks — a 2025 electronic score, a 1992 piano record, a 1991 rock
record — plus a mono downmix of the first as a control, each about 5 100 analysis
hops through --audio on 2026-09-19:
clip
balance min / mean / max
spread min / mean / max
electronic, 2025
-0.390 / 0.024 / 0.409
0.001 / 0.156 / 0.925
piano, 1992
-0.536 / 0.001 / 0.617
0.006 / 0.174 / 0.836
rock, 1991
-0.510 / -0.018 / 0.430
0.034 / 0.327 / 0.832
that electronic clip, downmixed to mono
0.000 / 0.000 / 0.000
0.000 / 0.000 / 0.000
Three readings come off that table, and each one changes how you bind the field.
The mean is within 0.03 of centre on every track while single hops reach
±0.4..±0.6. The excursions are the signal and the average is not, so
multiply for the excursions: clamp(balance * 2.5, -1, 1) spends a full visual
range on them without sitting on the rail.
spread averages 0.16..0.33 even on wide material, and a reading past
0.8 is a moment rather than a mix. spread > 0.25 is a sustained-wide
gate, not a common one.
A hard pan carries no spread at all — one waveform at two gains is
perfectly correlated, which is exactly what pan:<p> synthesizes. The two
quantities are independent: gate colour or opacity on spread and you hide
balance precisely where it is largest.
The same bindings were watched against live loopback rather than only against
clips: a track with obvious stereo movement moves a balance-bound preset the
way it sounds, and a mono one sits visibly still
(ADR-0215).
Built from 13c7582 at version 0.158.0. This site tracks main and is not versioned per release.