Rhythm & Patterns
The clock
Everything in Akkado syncs to a global clock. The trigger function creates pulses:
// Trigger 4 times per beat (16th notes)
trigger(4) Use triggers to control envelopes:
// Kick on quarter notes
sine(55) * ar(trigger(1), 0.01, 0.2) |> out(@) Building a basic beat
Combine different trigger rates for drum patterns:
// Simple kick and hi-hat
kick = sine(55) * ar(trigger(1), 0.005, 0.15)
hat = noise() |> hp(@, 8000) * ar(trigger(4), 0.001, 0.03) * 0.3
kick + hat |> out(@) Euclidean rhythms
The euclid function distributes hits evenly across a number of steps.
The fourth argument dur (default 4) sets the pattern span in cycles, so euclid(3, 8) spans 1 bar at 4/4 by default:
// Tresillo (3 hits over 8 steps, spread across 1 bar)
sine(55) * ar(euclid(3, 8), 0.01, 0.15) |> out(@) Classic Euclidean patterns:
euclid(3, 8)- Cuban tresilloeuclid(5, 8)- West African bell patterneuclid(7, 16)- Brazilian samba
euclid is a signal-domain trigger generator. To slow or speed it, change dur directly — .fast() and .slow() are pattern transforms and don’t apply
here. For pattern-style transforms over a Euclidean rhythm, use mini-notation
Euclidean syntax instead: n"c4(3,8)".slow(2).
// Layered Euclidean rhythms
kick = sine(55) * ar(euclid(4, 16), 0.005, 0.15)
perc = noise()
|> bp(@, 2000, 4)
* ar(euclid(5, 16), 0.001, 0.05) * 0.4
kick + perc |> out(@) Rotation
Rotate patterns to shift the accent:
// Rotated pattern - different feel, same hits
sine(55) * ar(euclid(3, 8, 1), 0.01, 0.15) |> out(@) Step sequencing
Use n"…" mini-notation for melodic patterns:
// 4-note melodic pattern
n"c3 e3 g3 c4" |> ((f) ->
saw(f) * ar(trigger(4)) |> lp(@, 800)
) |> out(@) Combining rhythm and melody
A complete sequence:
// Bass line with rhythm
n"c2 g2 d#2 a#1" |> ((f) ->
saw(f)
|> moog(@, 400 + ar(trigger(2)) * 800, 2)
* ar(trigger(2), 0.01, 0.2)
) |> out(@) LFO for movement
Add motion with LFOs:
// Rhythmic with filter movement
saw(110)
|> lp(@, 500 + lfo(0.25) * 1000)
* ar(trigger(4))
|> out(@) A complete drum pattern
// Kick drum
kick = sine(55 * (1 + ar(trigger(1), 0.001, 0.02) * 2))
* ar(trigger(1), 0.005, 0.2)
// Snare
snare = noise() |> bp(@, 1000, 2)
* ar(euclid(2, 8, 4), 0.001, 0.1) * 0.5
// Hi-hat
hat = noise() |> hp(@, 8000)
* ar(trigger(4), 0.001, 0.03) * 0.2
// Ride
ride = noise() |> bp(@, 6000, 8)
* ar(euclid(3, 8), 0.001, 0.1) * 0.15
kick + snare + hat + ride |> out(@) Polyrhythms
Layer two rhythms that don’t divide evenly into each other — 3 against 4 is the textbook example:
// 3 against 4
bass = saw(55) * ar(euclid(3, 12), 0.01, 0.15) |> lp(@, 400)
perc = noise()
|> hp(@, 4000)
* ar(euclid(4, 12), 0.001, 0.05) * 0.3
bass + perc |> out(@) Mini-notation patterns
For melodic sequences, use mini-notation:
// Melodic pattern
n"c3 e3 g3 c4" |> ((f) ->
saw(f) |> lp(@, 800) * ar(trigger(4))
) |> out(@) Conditional triggers
So far every gate has come from a pattern function (trigger, euclid, pat). You can also build gates from conditionals: comparisons and logic operators that work sample-by-sample.
Threshold gates
Compare a continuous signal against a value to produce a 0.0 / 1.0 gate:
// Open the kick only on the louder half of an LFO
loud = lfo(0.5) > 0
sine(55) * ar(loud, 0.005, 0.15) |> out(@) The > operator outputs 1.0 whenever its left-hand side is greater than its right-hand side, and 0.0 otherwise. Anything you can use as a trigger source you can build this way.
Selecting between two voices
select(cond, a, b) is a sample-rate ternary: it outputs a whenever cond > 0, otherwise b:
// Alternate timbre on every other beat
flip = n"1 0 1 0"
voice = select(flip, saw(110), sqr(110))
voice * ar(trigger(2), 0.005, 0.2) |> out(@) There’s no ?: ternary in Akkado. select is the canonical form.
Combining gates with && and ||
Logical AND (&&) fires only when both inputs are truthy. Logical OR (||) fires when at least one is truthy.
// OR: layer two patterns into a single gate
g1 = n"1 0 0 0"
g2 = n"0 0 1 0"
combined = g1 || g2 // "1 0 1 0"
sine(55) * ar(combined, 0.005, 0.15) |> out(@) // AND: accent only when a beat lines up with a slow LFO peak
loud = lfo(0.5) > 0.5
hit = trigger(4)
accent = loud && hit
noise() * ar(accent, 0.001, 0.05) |> out(@) The prefix ! operator inverts a gate, useful for “play during the rests”:
// A pad that fills the space between drum hits
gate = trigger(4)
sustain = !gate
sine(220) * sustain * 0.2 |> out(@) For the full operator precedence table and the complete list of comparison/logic builtins, see Operators and Conditionals & Logic.
Next steps
- Mini-Notation — the full pattern syntax.
- Pattern Modulation — patterns as values:
bend(notes, v"<0 0.5 -0.5>"), custome.cutoffproperties, scalar arithmetic. - Effects — reverbs and delays.
- Dynamics — compression, gating, limiting.