Skip to content

2. Rhythm Section

Nimbus has dedicated drum machines for kick, snare, and hi-hat. They use drum-mode seq strings (x = hit, . = rest) instead of scale degrees.

The three drum machines

function* song(ctx) {
const kk = kick()
const sn = snare()
const hh = hat()
yield cast(kk, 'drums', seq(4, 'x.x.x.x.'), ctx)
yield cast(sn, 'drums', seq(4, '..x...x.'), ctx)
yield cast(hh, 'drums', seq(4, 'x.x.x.x.'), ctx)
}

Pass 'drums' as the second argument to cast whenever you use a drum machine — pitch is ignored.


kick — bass drum

kick() is a synthesized bass drum based on a pitch-swept sine wave. Key parameters:

ParameterDefaultEffect
pitch60 HzStarting frequency — higher = tighter, lower = boomy
decay0.3 sLength of the tail
punch0.8Transient click — higher = harder attack
gain0.8Output level
// Standard kick
kick()
// Tight and punchy (techno/house)
kick({ pitch: 80, decay: 0.15, punch: 1.0 })
// Deep and slow (hip-hop / trap)
kick({ pitch: 40, decay: 0.8, punch: 0.5 })
// High and clicky (dry click track)
kick({ pitch: 120, decay: 0.05, punch: 1.0, gain: 0.6 })

snare — snare drum

snare() combines a tonal body with a noise burst. Key parameters:

ParameterDefaultEffect
tone180 HzBody frequency — higher = brighter crack
snap0.9Noise punch amount
decay0.15 sLength of the tail
gain0.7Output level
// Standard snare
snare()
// Tight crack (reggae / pop)
snare({ tone: 220, snap: 1.0, decay: 0.08 })
// Deep rimshot
snare({ tone: 140, snap: 0.5, decay: 0.25 })
// Snappy clap-like hit
snare({ tone: 300, snap: 1.0, decay: 0.04, gain: 0.8 })

hat — hi-hat

hat() is a metallic noise oscillator. Key parameters:

ParameterDefaultEffect
decay0.05 sLength — short = closed, long = open
tone8000 HzFilter frequency — higher = brighter
gain0.5Output level
// Closed hi-hat (default — very short)
hat()
// Open hi-hat
hat({ decay: 0.35 })
// Ride cymbal feel
hat({ decay: 0.6, tone: 6000, gain: 0.4 })
// Shaker / ghost hat
hat({ decay: 0.02, tone: 10000, gain: 0.25 })

Drum patterns

Classic patterns

// 4/4 rock beat
yield cast(kk, 'drums', seq(4, 'x.x.x.x.'), ctx) // kick on 1, 2.5, 3, 4
yield cast(sn, 'drums', seq(4, '..x...x.'), ctx) // snare on 2 and 4
yield cast(hh, 'drums', seq(4, 'x.x.x.x.'), ctx) // 8th-note hat
// Straight four-on-the-floor (house/techno)
yield cast(kk, 'drums', seq(4, 'x...x...x...x...'), ctx) // 16th grid
// Trap hi-hat: dense 16th notes with gaps
yield cast(hh, 'drums', seq(4, 'x.xx.x.xx.xx.x..'), ctx)

Syncopation

Offset the kick or snare from the beat for groove:

// Syncopated kick (pushes beat 3)
yield cast(kk, 'drums', seq(4, 'x...x.x.....x...'), ctx)
// Reggaeton / dembow (kick on 1 and "and-3")
yield cast(kk, 'drums', seq(4, 'x.....x.x.......'), ctx)
yield cast(sn, 'drums', seq(4, '....x.......x...'), ctx)

Ghost notes with velocity

Add a (v:low) suffix to make a hit quieter (velocity 0–1):

// Snare with ghost notes — lowercase = implied low velocity in text, use w: for weighted
yield cast(sn, 'drums', seq(4, '..x...x.'), ctx) // main hits

Polymeter — different loop lengths

When a drum sequence has a different beats value from the other patterns, it loops at its own rate. This creates evolving, interlocking rhythms automatically.

function* song(ctx) {
const kk = kick()
const sn = snare()
const hh = hat()
yield cast(kk, 'drums', seq(4, 'x...x...x...x...'), ctx) // 4 beats
yield cast(sn, 'drums', seq(3, '..x.x.'), ctx) // 3 beats — loops every 12 beats
yield cast(hh, 'drums', seq(2, 'x.x.x.x.'), ctx) // 2 beats
}

The kick, snare, and hat are now in 4:3:2 ratio — they realign every 12 beats.


Full rhythm section example

A complete beat with melodic bass:

function* song(ctx) {
const kk = kick({ decay: 0.25 })
const sn = snare({ snap: 0.8 })
const hh = hat({ decay: 0.04 })
const ohh = hat({ decay: 0.3, gain: 0.3 })
const bass = vasynth({ wave: 'sine', cutoff: 600, attack: 0.01, release: 0.15, gain: 0.7 })
const bKey = scales(4, 'C2:minor')
yield cast(kk, 'drums', seq(4, 'x...x.x.....x...'), ctx)
yield cast(sn, 'drums', seq(4, '....x.......x...'), ctx)
yield cast(hh, 'drums', seq(4, 'x.x.x.x.x.x.x.x.'), ctx)
yield cast(ohh, 'drums', seq(4, '......x.......x.'), ctx)
yield cast(bass, bKey, seq(4, '0,_,_,4,_,2,_,_'), ctx)
}

Next

3. Melody & Harmony → — add chord progressions and multi-voice melody.