Skip to content

A value with a memory — the [hold] table

An optional top-level [hold] table names bindings the engine re-samples on a musical edge and holds between edges (ADR-0180 rule 2). It sits beside [smoothing] and [latch] in every sense — same place in the file, same resolved-once-at-load treatment, same reset on a preset switch — and between the three of them the sentence is finished: [smoothing] shapes a value over time, [latch] holds an event, [hold] holds a value.

[params]
n = "3 + floor(bass * 5)" # a rose that would flicker between 3 and 8 petals
[hold]
n = "bar" # ...takes its petal count once a bar instead

The expression is still evaluated every frame; the entry decides which frame’s result the scene is shown.

entrywhen the value is re-taken
"beat"every frame the beat detector fires — the same gate the beat variable reads.
"bar"every time the bar counter moves.
a numberevery n seconds of render time, n > 0, bare (2.5) or quoted.

Anything else is a load error. The first frame a held binding is seen always takes a value, so a preset never opens on a default it did not ask for.

bar rides the downbeat estimator, and that estimator locks about 3 % of audible time (backlog 0042). The rest of the time the bar counter is derived from the beat count rather than tracked — it steps on something regular, not on a guaranteed downbeat. What the entry reliably buys is slow. Where you want the change on a hit, "beat" says so.

With [smoothing], the order is evaluate → hold → smooth → quantize. The smoother eases toward the held value, so a parameter that is both held and eased travels to each new figure rather than stepping to it — and a Structural parameter walks through the whole numbers on the way. Leave it out of [smoothing] for a clean jump.

A binding that reads index, or lives in [per_vertex], cannot be held: it is evaluated many times per frame and has no single value to hold, so an entry naming one is a load error rather than the warning the equivalent [smoothing] entry gets. An easing constant degrades to instant and still renders what you wrote; a hold has no degraded form, and the binding would go on flickering while the table looked applied. An entry naming a parameter the preset does not bind is a warning, like an inert [occupancy] exempt entry.

[layer.hold] reaches the layer’s own bindings and its mix, exactly as [layer.smoothing] does.

A hold makes a preset read as more reactive than it is. The static reachability walk sees a live expression naming bass and cannot see that the engine took its value once this bar. shot --report prints a HELD: line per held binding with its edge for that reason — read the reactivity columns beside it as the response the hold allows.

Built from a8ce055 at version 0.115.0. This site tracks main and is not versioned per release.