Skip to content

The SoundDoc nodes ​

Every field and node in a SoundDoc — the JSON synthesis graph tono renders. tono schema prints the machine-readable JSON Schema (for editor autocomplete and validation).

A doc skeleton: { "name": ..., "duration": secs, "sample_rate": 44100, "seed": 0, "root": <node> }. root is a single node; every node is a mono signal. Multiply a source by an envelope (mul), layer sources with mix, pipe a source through processors with chain. Any numeric param is a constant, a note name, or a modulator.

Node vocabulary ​

Document-level fields:

fielddefaultnotes
name—label; names the output files
duration0.3length in seconds
sample_rate44100Hz
seed0drives every noise source, dust train, and pluck burst
version2current document schema; other revisions are rejected
engine5current deterministic DSP kernels; other revisions are rejected
stereomono{ "mode": "wide" } or { "mode": "haas", "ms": 12, "pan": 0.3 } treatment on the final render; a tracks root builds its image from per-track pan instead
normalizeunset ⇒ a transparent −0.1 dBFS sample-peak safety limit onlyloudness match + true-peak limit
playbackoneshotor loop
root—the signal graph

Sources (output audio):

nodefieldswhat it is
sine / triangle / sawtoothfreqbasic waves
squarefreq, duty = 0.5pulse wave; modulate duty for PWM
noisecolor = whitepink −3 dB/oct (wind/rumble), brown −6 dB/oct (booms)
fmfreq, ratio, index2-op FM — bells, e-piano; slide index down for a struck attack
superwave = sawtooth, freq, voices = 7 (1..=16), detune_cents = 15detuned unison stack (supersaw)
seqbpm, wave, env, notes, …note sequencer — see Compose songs
impacthardness = 0.5, velocity = 1strike exciter; feed a modal bank
dustdensity, decay = 0.02Poisson click train; decay 0 = bare impulses
enva, d, s, r, punchADSR control signal 0..1 (not audio)

Combinators:

nodefieldswhat it is
mixinputssum (layer) all inputs
mulinputsmultiply (typically source × envelope)
chainstagesserial pipe: stage 0 is a source, later stages process it
trackstracks, master, busesstereo mixing console — document root only

Processors (chain stages):

nodefieldswhat it is
gainamountscale the signal (modulatable)
lowpass / highpass / bandpass / notchcutoff, q = 0.707resonant filters; notch removes a narrow band (hum)
peakcutoff, q = 0.707, gain_db = 0boost/cut one band (surgical EQ)
lowshelf / highshelfcutoff, gain_db = 0tilt everything below/above the corner
delaysecs, feedback = 0feedback echo / comb
reverbroom = 0, mix = 0Schroeder-style reverb
modalmodes = [{freq, decay=0.4, gain=1}] (1..=64), mix = 1resonator bank — a struck body
driveamount, shape = tanh, aa?waveshaper: tanh warm, hard clip, fold metallic; ADAA by default; aa: false selects the raw curve
tremolorate = 6, depth = 0.5amp wobble
chorusrate = 1.5, depth = 0.5, mix = 0.5thickening / width
compressthreshold, ratio, attack = 0.005, release = 0.08, makeup = 0glue / loudness

Sidechain ducking lives on the mixer: a tracks layer's sidechain (source, amount, attack, release) follows another layer's signal.

Modulators (any numeric param, in place of a constant). Unlike nodes they carry no type field: the modulator name wraps its fields, { "slide": { "from": 880, "to": 220, "secs": 0.3 } }. A pitch glide on a sine:

json
{
  "name": "glide",
  "duration": 0.4,
  "root": { "type": "mul", "inputs": [
    { "type": "sine", "freq": { "slide": { "from": 880, "to": 220, "secs": 0.3, "curve": "exp" } } },
    { "type": "env", "a": 0.005, "d": 0.3, "s": 0.0, "r": 0.05 } ] }
}
modulatorfieldswhat it does
constant / note name440, "C4", "F#3", "Gb5", "midi:60"note names resolve to Hz (A4 = 440)
slidefrom, to, secs, curve = lin|expglide, then hold at to; exp reads as natural pitch glide
lfoshape = sine (square/triangle/saw), rate, depth, centerperiodic oscillation around center
arpsteps, ratecycle values at rate steps/sec
enva, d, s, r, punch + from, toADSR mapped onto the from→to range
randfrom, to, rate, seed = 0smooth random walk; self-seeded and edit-stable

MIT licensed — permissive, no warranty.