Drums

Showcase panel 21: silent until clicked: a Synth note (x sets the pitch), a Pluck, and a bar of Kick, Snare and HiHat in a Sequencer with its playhead and a Reverb on the master, with master.spectrum() and master.level() drawn live; needs kiln-gl[sound].

Showcase panel 21: silent until clicked: a Synth note (x sets the pitch), a Pluck, and a bar of Kick, Snare and HiHat in a Sequencer with its playhead and a Reverb on the master, with master.spectrum() and master.level() drawn live; needs kiln-gl[sound].
Try it live: run uv run python examples/showcase.py, then click panel 21, or see the showcase.

Kiln has a drum machine built in: eight drums, one class each, made the way the Roland TR-808 and TR-909 make them. Nothing is a recording. A kick is a resonator struck by a click, a hi-hat is six square waves through a filter, a clap is noise that strikes four times. So every drum has knobs, and every hit is a little different, as on the real machines.

Drum What it is made of
kiln.Kick a struck resonator whose pitch falls, a click, optional drive
kiln.Snare two struck resonators, and noise for the snare wires
kiln.Clap band-passed noise that strikes four times, 10 ms apart
kiln.HiHat six square waves at odd, metallic pitches, high-passed
kiln.Tom the kick’s recipe, higher, with a little noise
kiln.Rimshot two short resonators, a click and some drive
kiln.Cowbell two square waves, band-passed
kiln.Cymbal the hi-hat’s squares in two bands, ringing long

You need the sound extra: pip install "kiln-gl[sound]". As on the Sound page, the examples here are recorded with with record(): and wait(seconds), and each recording is raised to a comfortable listening level.

Hit it

A drum is an instrument you hit(). That’s all:

import kiln

with record():
    kick = kiln.Kick()
    for _ in range(4):
        kick.hit()
        wait(0.5)

waveform of the sound

hit() takes a velocity, from 0 to 1, which is how hard you hit: there’s more on it under Accents. A drum rings out on its own, so there is no note_off: you hit it and let it go.

Kick

The kick’s pitch starts at tune * drop and falls to tune over drop_time. decay is how long the boom takes to die away (60 dB down). A long decay with a small drop is the 808’s boom; a deep, fast drop with some drive and click is the 909’s punch. Here is one, then the other:

import kiln

with record():
    kick = kiln.Kick()
    kick.tune, kick.decay, kick.drop = 48, 1.2, 1.5     # 808: a long, low boom
    kick.hit()
    wait(1.0)
    kick.tune, kick.decay, kick.drop = 55, 0.35, 5.0    # 909: a deep, fast sweep
    kick.click, kick.drive = 0.7, 0.6                   # and a hard, driven attack
    kick.hit()
    wait(0.6)

waveform of the sound

Snare and clap

A snare is a drum skin (two resonators, at tune and about 1.8 times it) and the rattle of the snare wires underneath, which is noise. snappy is how much wire. The clap is noise too, struck four times about 10 ms apart, as several hands never clap at quite the same moment:

import kiln

with record():
    snare = kiln.Snare()
    snare.hit()
    wait(0.4)
    snare.snappy = 1.0          # all wires
    snare.tune = 230
    snare.hit()
    wait(0.4)
    clap = kiln.Clap()
    clap.hit()
    wait(0.5)

waveform of the sound

Hi-hats

A hi-hat is closed (a short tick) or open (it rings). Make one of each: kiln.HiHat() and kiln.HiHat(open=True). They choke each other like a real pair of hats: a closed hat cuts a ringing open one short. Listen to the open hat ring out the first time and get cut off by the closed one the second time:

import kiln

with record():
    closed = kiln.HiHat()
    opened = kiln.HiHat(open=True)
    opened.hit()
    wait(0.6)
    opened.hit()
    wait(0.15)
    closed.hit()                # chokes the open hat
    wait(0.35)

waveform of the sound

Toms, rimshot, cowbell, cymbal

A tom is tuned: note_on(freq) hits it at that pitch (hit() is the same as note_on(tom.tune)), so a few notes make a fill. The rest are the 808’s odd ones:

import kiln

with record():
    tom = kiln.Tom()
    for freq in (196, 165, 131, 110):     # a fill, high to low
        tom.note_on(freq)
        wait(0.12)
    wait(0.25)
    kiln.Rimshot().hit()
    wait(0.25)
    kiln.Cowbell().hit()
    wait(0.35)
    kiln.Cymbal().hit()
    wait(1.4)

waveform of the sound

Accents

Drum machines have an accent button that makes a step hit harder. In Kiln that is the velocity: hit(1.0) against hit(0.5). A harder hit isn’t only louder, it’s brighter too (a sharper click, a higher band of noise, a deeper sweep), as a real drum is. Here are sixteenth-note hats with every fourth one accented:

import kiln

with record():
    hat = kiln.HiHat()
    for i in range(16):
        hat.hit(1.0 if i % 4 == 0 else 0.5)
        wait(0.123)

waveform of the sound

A beat

Put them together with a kiln.Sequencer, the drum machine’s step grid: one pattern per drum, a character per sixteenth note (x a hit, X an accent, . a rest). Here is a kick on every beat, open hats on the off-beats, closed hats in between and a clap on beats 2 and 4, at 122 beats per minute:

import kiln

with record():
    kick, clap = kiln.Kick(), kiln.Clap()
    closed, opened = kiln.HiHat(), kiln.HiHat(open=True)
    kick.volume = 0.9
    seq = kiln.Sequencer(bpm=122)
    seq.pattern(kick,   "X...x...X...x...")
    seq.pattern(opened, "..x...x...x...x.")
    seq.pattern(closed, ".x.x.x.x.x.x.x.x")
    seq.pattern(clap,   "....x.......x...")
    seq.start()
    wait(3.9)                     # two bars (and the next downbeat, already queued)
    seq.stop()
    wait(0.4)

waveform of the sound

Every hit lands on its exact sample, however busy your draw() is, and a drum in a pattern plays at its tune. The Sequencer page has the rest: swing, notes, automation and drawing on the beat. examples/14_drums.py puts one behind a 16-step grid you click to edit, with a picture that pumps with the kick, flashes with the clap and throws sparks with the hats. Run it with uv run python examples/14_drums.py.

How many drums at once

Each drum plays one hit at a time by default (polyphony=1): a new hit chokes the last one, as on the 808, where each drum is one circuit. Give a cymbal kiln.Cymbal(polyphony=3) to let crashes overlap.

Drums are cheap. Kiln keeps the sound within a budget of 24 synth voices’ worth (see kiln.Instrument), and a drum hit counts as a small fraction of a synth voice: a kick or a snare about a twentieth, a hi-hat or a cymbal up to about a half (they make twenty-four square waves a sample). A whole kit on one step costs less than two synth notes.

Try this

Make the beat swing: kiln.Sequencer(bpm=122, swing=0.3) delays every second sixteenth by almost a third of a step. Then add a tom fill on the last beat of the bar, seq.pattern(tom, "............xxXx").

Or make the kick melodic: call kick.note_on(freq) with a bass line instead of kick.hit(), and turn its decay up.

Where the recipes come from

The drums follow Gordon Reid’s Synth Secrets articles on the 808 and 909 (Sound On Sound, 2002, parts 34 to 37) and the physically informed models of the TR-808’s bass drum and cymbal by Kurt James Werner, Jonathan Abel and Julius Smith (DAFx 2014 and ICMC 2014). kiln.sound.dsp.drums has the details.