Signals and DAGs
A signal in NKIDO is any value that changes over time. Usually audio, but also control values like envelopes or LFOs. Every patch is a graph of signals flowing through operators.
Everything is a graph
When you write a patch, you’re describing a DAG (directed acyclic graph) of DSP nodes. Each node takes signals as input and produces a signal as output. The pipe operator |> connects them.
osc("sin", 440) * 0.3
|> lp(@, 1200)
|> reverb(@, 0.4)
|> out(@) NKIDO compiles this graph to bytecode that runs in a stack-based VM, one audio block at a time. No per-sample allocations, no runtime garbage collection.
Signal rates
Signals run at one of two rates:
- Audio-rate: one value per sample (48 kHz typical). Oscillators, filters, delays, mixers all produce audio-rate signals.
- Control-rate: one value per audio block (~128 samples). Cheaper; used for parameter modulation like LFOs and envelopes.
You rarely need to think about rates directly (operators coerce as needed) but control-rate modulation is how you get CPU-efficient sweeps and LFOs.
Why a DAG?
A DAG has no cycles, which means every signal can be computed in topological order with a single pass through the graph. That’s what makes NKIDO fast enough to run on a microcontroller and still predictable enough to hot-swap safely.
Feedback loops (delays, reverb tails) are modeled as explicit delay-line nodes, not as cycles in the graph. This keeps the DAG acyclic while still letting you build feedback-heavy patches.