Utility
Utility functions for common audio tasks like output, MIDI conversion, and signal processing helpers.
out
Audio Output - Send signal to speakers.
| Param | Type | Description |
|---|---|---|
| L | signal | Left channel |
| R | signal | Right channel (optional, defaults to L) |
Aliases: output
Every Akkado patch needs an out() to produce sound. Pass one signal for mono, two for stereo.
// Mono output (same signal to both speakers)
sine(440) |> out(@) // Stereo output (different signals)
sine(440) |> out(@, sine(442)) // Panned signal
sine(440) * 0.7 |> out(@, @ * 0.3) out is an alias for bus(0, …) — it routes to the master bus. See the Bus Routing concept page for the full
signal-flow model.
bus
Route to a numbered bus - Sum a signal into bus N.
| Param | Type | Description |
|---|---|---|
| N | number | Bus index — a compile-time non-negative integer literal |
| L | signal | Left channel |
| R | signal | Right channel (optional, defaults to L) |
A bus is a stereo summing point. Every bus(N, …) writer for the same N sums together; the bus then feeds the master. Bus 0 is the master — out(…) is exactly bus(0, …). Non-zero buses auto-sum into bus 0 after
their own mixer chain runs.
The index must be a literal (E260 otherwise) — the buffer set is fixed at
compile time. Use a bus to process a group of voices together (a drum bus, a
reverb-send target) instead of each hit individually.
// A drum bus — process the bus, not each hit
kick |> bus(1, @)
snare |> bus(1, @)
mixer(1, (s) -> s |> comp(@, -8, 6)) mixer
Per-bus FX - Attach a processing closure to bus N’s summed signal.
| Param | Type | Description |
|---|---|---|
| N | number | Bus index — a compile-time non-negative integer literal |
| closure | closure | Runs once per block on the bus’s summed signal |
The closure runs after every bus(N, …) writer has contributed, and its
result replaces the bus signal downstream. Two arities are accepted: (s) -> … (one stereo value) and (l, r) -> … (left + right separately).
A closure may not contain a sink (out/bus/mixer/master/<>) —
that is E261. A bus with no mixer is pure identity.
// Glue the drum bus with a compressor
mixer(1, (s) -> s |> comp(@, -8, 6) |> softclip(@, 0.9)) // Per-channel processing
mixer(2, (l, r) -> stereo(softclip(l, 0.9), softclip(r, 0.9))) master
Master-bus FX - Alias for mixer(0, closure).
| Param | Type | Description |
|---|---|---|
| closure | closure | Runs once per block on the master bus |
Bus 0 carries a default soft-clip at 0.9. Supplying a master(…) (or mixer(0, …)) replaces that default tone chain. The forced safety
stage — NaN/Inf guard plus a hard ±1.0 rail — always runs afterward and
cannot be disabled. To run the master with no tone processing, pass the
identity closure master((s) -> s).
// Glue compressor + soft clip on the master
master((s) -> s |> comp(@, -12, 4) |> softclip(@, 0.85)) // Live-tweakable master drive
drive = param("master_drive", 0.85, 0.5, 1.0)
master((s) -> s |> softclip(@, drive)) diamond operator
<> / <>(N) - Statement-trailing sugar for routing to a bus.
| Sugar | Expands to | Meaning |
|---|---|---|
<> | \|> out(@) | route to the master bus |
<>(N) | \|> bus(N, @) | route to bus N |
The diamond is a one-token statement terminator. It binds looser than |>,
so it captures the whole pipe chain: a |> b |> c <>(1) routes (a |> b |> c) to bus 1. It is only valid trailing a complete statement —
elsewhere it is rejected with E263. The optional (N) is a non-negative
integer literal; <>(0) is identical to bare <>.
// Route to the master bus
saw(220) |> lp(@, 800) <> // Route to bus 2
n"c4 e4 g4" as e |> saw(e.freq) <>(2) mtof
MIDI to Frequency - Convert MIDI note number to frequency in Hz.
| Param | Type | Description |
|---|---|---|
| note | signal | MIDI note number (0-127) |
Converts MIDI note numbers to frequencies using equal temperament. Middle C (C4) is note 60 = 261.6 Hz.
// Middle C
sin(mtof(60)) |> out(@) // A4 (MIDI note 69 = 440 Hz)
sin(mtof(69)) |> out(@) // Chromatic scale using modulation
sin(mtof(48 + phasor(2) * 12)) |> out(@) dc
DC Offset - Constant value generator.
| Param | Type | Description |
|---|---|---|
| offset | number | Constant value to output |
Outputs a constant value. Useful for mixing with signals or providing a static parameter.
// Use as constant multiplier
sine(440) * dc(0.5) |> out(@) slew
Slew Rate Limiter - Caps how fast a signal can change, in units per second.
| Param | Type | Description |
|---|---|---|
| target | signal | Target value |
| rate | number | Slew rate (units per second; higher = faster) |
Rate-limited smoothing. Good for taming param sliders, slewing CVs, and audio-rate slew effects. For note-pitch glide between pattern events with a fixed duration regardless of interval size, reach for glide instead.
| Aspect | slew(target, rate) | glide(sig, time, …) |
|---|---|---|
| Time meaning | units per second | total ramp duration |
| Interval indep. | No — fast slides on big jumps | Yes — same time always |
| Shape | Linear | Linear / ease / cosine |
| Value-space | Linear | Linear or log |
| Best for | CV / knob smoothing, audio slew | Note glide, portamento |
// Smoothed pitch sweep (rate-limited)
sin(slew(mtof(48 + sqr(2) * 12), 10)) |> out(@) // Smooth filter sweep
saw(110) |> lp(@, slew(200 + sqr(0.5) * 2000, 5)) |> out(@) glide
Time-based glide / portamento - Slides to a new target over a fixed duration, regardless of interval size. Stereo-native.
| Param | Type | Default | Description |
|---|---|---|---|
| sig | signal | — | Target value (sample-and-hold patterns work well) |
| time | number | 0.05 | Ramp duration in seconds |
| curve | string | "linear" | "linear", "ease_in", "ease_out", "cosine" |
| space | string | "linear" | "linear" or "log" (musical pitch glide) |
Detects target changes by exact value compare and ramps from the current emitted value to the new target over time seconds. Pattern fields (@freq, @note, @vel) feed in cleanly because they arrive as sample-and-hold buffers. Use space: "log" for perceptually uniform glide over wide intervals — or feed @note through mtof, which is already log-pitch by construction.
glide is stereo-native: it auto-widens a mono target to stereo. To compose it with a mono-only slot (like saw(freq)), either feed via mtof(glide(@note, …)) (mtof keeps the chain mono) or wrap with mono(...). See the Glide & Interpolation concept page for the full discussion.
// Default 50 ms portamento between notes
n"c4 c5" |> saw(mtof(glide(@note, 0.05))) |> out(@) // 100 ms cosine S-curve glide
n"c4 c5" |> saw(mtof(glide(@note, 0.1, "cosine"))) |> out(@) // Wide-interval portamento — log space keeps the slide pitch-uniform
n"c2 c6" |> saw(mono(glide(@freq, 0.2, "ease_out", "log"))) |> out(@) // Smoother param-slider response
cutoff = param("cutoff", 1000, 100, 8000)
saw(220) |> lp(@, mono(glide(cutoff, 0.03))) |> out(@) See also: interp (primitive form), slew (rate-based), Glide & Interpolation.
interp
Time-based interpolator (linear) - Lower-level primitive used by glide. Stereo-native, no value-space conversion.
| Param | Type | Description |
|---|---|---|
| target | signal | Target value |
| time | number | Ramp duration in seconds |
Same change-detection and ramp behavior as glide(sig, time, "linear", "linear"), with fewer characters. Call directly when you don’t need curve or value-space options.
// 100 ms linear ramp between targets
n"c4 c5" |> saw(mtof(interp(@note, 0.1))) |> out(@) See also: glide, interp_ease_in, interp_ease_out, interp_cos.
interp_ease_in
Time-based interpolator (ease-in) - Quadratic-in shape: t². Starts slow, accelerates into the target.
| Param | Type | Description |
|---|---|---|
| target | signal | Target value |
| time | number | Ramp duration in seconds |
// Notes "settle into" their targets
n"c4 c5" |> saw(mtof(interp_ease_in(@note, 0.15))) |> out(@) See also: glide with curve: "ease_in".
interp_ease_out
Time-based interpolator (ease-out) - Quadratic-out shape: 1 - (1-t)². Starts fast, decelerates as it approaches the target.
| Param | Type | Description |
|---|---|---|
| target | signal | Target value |
| time | number | Ramp duration in seconds |
// Notes "spring toward" their targets
n"c4 c5" |> saw(mtof(interp_ease_out(@note, 0.15))) |> out(@) See also: glide with curve: "ease_out".
interp_cos
Time-based interpolator (cosine S-curve) - Shape ½(1 − cos πt). Smooth in and out; the classic “tape-stop”-style ramp.
| Param | Type | Description |
|---|---|---|
| target | signal | Target value |
| time | number | Ramp duration in seconds |
// Slow S-shaped pitch sweep
n"c4 c5" |> saw(mtof(interp_cos(@note, 0.4))) |> out(@) See also: glide with curve: "cosine".
sah
Sample and Hold - Captures a signal when triggered.
| Param | Type | Description |
|---|---|---|
| in | signal | Input signal to sample |
| trig | trigger | When to capture |
Samples the input signal each time the trigger fires and holds that value until the next trigger. Classic modular synth technique.
// Random pitches
sin(mtof(48 + sah(noise() * 24, trigger(4)))) |> out(@) // Stepped filter
saw(110)
|> lp(@, 200 + sah(noise() * 2000, trigger(2)))
|> out(@) clock
Master Clock - Returns the global clock signal.
No parameters.
Returns the master clock signal synchronized to the BPM. Useful for building custom timing logic.
// Clock-synced modulation
sin(440 + clock() * 100) |> out(@)