Sample & Hold / Buffer / Decimate

Shippingstateful
sample_hold

Stateful: classic S&H latch, ring-buffer capture, or decimation

Signature

Inputs

  • signalSignalrequired
  • triggerSignal

Outputs

  • outputSignal
  • fullSignal

Parameters

KeyTypeDefaultNotes
modeenumsample_holdone of: sample_hold, buffer, decimate
hold_everyint1
trigger_edgeenumrisingone of: rising, falling, any
buffer_sizeint1024
decimate_nint4
initial_valuefloat0.0

Description

Sample & Hold / Buffer / Decimate is a single stateful node that captures samples from its signal input and re-emits them under one of three mode policies. In `sample_hold` mode it acts as a classic latch: on each qualifying edge of the optional trigger input it captures the current signal value and holds it constant on output until the next trigger; between triggers the output is frozen. In `buffer` mode it writes incoming samples into a ring buffer of length buffer_size, asserting the full output when the buffer wraps. In `decimate` mode it passes every decimate_n-th sample and discards the rest, reducing the effective sample rate.

The node is stateful (SHState): it retains the held value, the ring-buffer contents and write index, and the previous trigger level needed for edge detection across evaluation ticks. The trigger_edge parameter selects rising, falling, or any transitions; if no trigger is wired in sample_hold mode, the hold_every parameter provides an internal sample cadence (capture every -th sample). Before the first capture the output takes initial_value.

Sample & Hold is a value-domain operation: it never interpolates or synthesizes new numbers, so the physical unit of signal passes through unchanged and each held or forwarded sample carries its original uncertainty verbatim. Holding a value does not shrink its variance, and decimation does not average — the surviving samples keep their exact . Unlike a filter, no error is combined across samples.

Mathematics

Examples

Latch on a rising trigger edge

With mode = sample_hold and trigger_edge = rising, wire a strobe into trigger. Each low-to-high transition captures the instantaneous signal value and holds it. Between edges the output is a flat staircase:

signal:  1.2  1.7  2.3  2.9  3.1
trigger:  0    1    0    1    0     (rising at samples 1 and 3)
output:  0.0  1.7  1.7  2.9  2.9

The pre-trigger samples emit initial_value (here 0.0).

Decimate a 48 kHz stream to 12 kHz

Set mode = decimate and decimate_n = 4. The node forwards every 4th sample, dropping the intermediate three, yielding a effective rate. Because no averaging occurs, any signal energy above will alias — precede with iir_filter or smoothing as an anti-alias stage if the band is not already limited.

Applications

  • ADC front-end modeling: freezing an analog signal on a convert-start strobe so downstream logic sees a stable value during conversion.
  • Multi-rate DSP: down-sampling a fast sensor or audio stream to a slower processing rate via `decimate` after band-limiting.
  • Block/frame acquisition: filling a fixed-length `buffer` and using the `full` flag to trigger FFT, statistics, or windowed analysis on complete frames.
  • Event-driven measurement: latching a meter reading at the moment an external event (trigger edge) occurs, e.g. peak-time capture in a physics experiment.

Neat

The same node covers three textbook operations — zero-order hold, framing/ring-buffering, and integer decimation — because all three are pure sample-selection policies over shared latch state; only the emit rule differs.

In `buffer` mode the `full` output is an edge flag that fires exactly when the write index wraps past `buffer_size`, letting you drive frame-synchronous processing without an external counter.

Known issues

`decimate` performs no anti-alias filtering: spectral content above half the decimated rate folds back into band. Band-limit upstream when this matters.

In `sample_hold` mode with no `trigger` wired, capture falls back to the `hold_every` cadence; if you expected edge behavior but left `trigger` unconnected, the output will instead update every $n$-th sample rather than holding indefinitely.

See also

sample-and-holddecimationbufferstatefulmultiratetrigger