Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DSL overview

The sndlab DSL is a small set of Rhai functions for describing audio signals. Every primitive — source, transform, or combinator — builds a node in a single Signal graph. The graph is lazy: nothing is computed until the engine decides what to do with it.

What the engine does depends on the patch’s role:

  • One-shot patches render the graph into a finite buffer at patch-registration time, driven by whatever bounded duration the graph supplies (a take(...), a chirp(...), or a sound primitive called with a duration argument). The buffer plays through Kira’s low-latency StaticSoundData path.
  • Ambient patches keep the graph as a lazy description. At play time a fresh runner is spawned and ticks the graph at audio rate for as long as the ambient stays enabled. There is no looping — ambients are generated, not played back.

The single-graph design means there’s no distinction between “buffer DSL” and “stream DSL.” sine(440) is the same primitive whether it ends up in a one-shot or an ambient — only the duration context differs.

Status

PrimitiveStatusPurpose
patchshippedRegister a named patch.
sineshippedA sine oscillator. sine(freq) is unbounded; sine(freq, dur) wraps in take.
chirpshippedLinear-FM sweep, bounded by its duration argument.
noiseshippednoise(kind) is unbounded; noise(kind, dur) wraps in take.
envshippedAttack + exponential decay applied to a signal.
takeshippedTruncate a signal to duration_s. Sources support this implicitly via their two-arg form.
fade_outshippedCosine-squared fade over the buffer’s last duration_s. Requires a bounded source.
fade_inshippedsin² fade-up at the start. Complementary to fade_out — together they sum to constant power.
delayshippedPrepend silence before the source. Stagger entries in a mix(…).
tremoloshippedSine LFO amplitude modulation.
gainshippedLinear amplitude scaling.
bandpassshippedBiquad bandpass.
lowpassshippedBiquad lowpass.
highpassshippedBiquad highpass.
mixshippedSum multiple signals.
tapshippedA delay tap, used by with_taps. (Per-tap exponential decay is honoured in one-shots only; ambient streams use fixed-gain delay copies.)
grainsshippedStochastic damped-sine grain generator — bubbles, drips, rain.
sampleshippedLoad an audio file (MP3/WAV/Ogg/FLAC) as a Signal. sample(path) plays once; sample_loop(path) wraps.

Conventions

  • Frequencies in Hz. Integers and floats both accepted.
  • Durations in seconds.
  • Amplitudes linear, 0..1.

Fluent style

sine(330.0).env(0.008, 1.4).gain(0.32).take(3.5)

Equivalent to nesting calls — the engine’s Rhai layer just registers each function as both a free fn and a method on Signal.

Bounding rules

One-shot patches need a finite duration somewhere in the graph. The engine walks the tree and uses the longest take / chirp / bounded fade_out it finds; if nothing’s bounded it caps at a 10 s safety default and logs a warning. Ambient patches ignore bounded sub-trees and simply run forever.