← All modules
AvailableInstrument

Percussion Synth

A sample-free drum synth with ten circuits and sixteen steps.

Engine preview

VST3

About

Every sound in a classic drum machine is a circuit, not a recording, and each one is a trick you can state in a sentence. A kick is a sine wave whose frequency falls from four times its tuning to its tuning in about thirty milliseconds, that sweep is the whole sound, because a struck drum head is stiffest while the beater is still on it. A snare is two inharmonic modes near 1 : 1.59 (which is why a snare drum has no singable pitch) sitting over band-passed noise for the wires, and the one knob the circuit really has is the balance between them. Hats and cymbals are six square waves at ratios picked specifically so they cannot be heard as a chord, summed and then high-passed hard.

This module is those circuits. Nothing here is sampled and nothing is modelled from a membrane simulation, which is both the limit of what it claims and the reason its controls do what their labels say: turning the kick's decay up lengthens a sine's envelope, and you can hear that it is a sine.

The clap is the one worth listening for. It is not one noise burst but four, three short ones a few milliseconds apart and then a longer tail, because a clap is several hands landing at slightly different times in a room that answers them. Synthesised as a single filtered burst it comes out sounding like a snare with the treble rolled off, which is exactly what a one-burst clap sounds like everywhere it is done that way.

The hi-hats share a CHOKE GROUP, which is a real mechanism rather than a convenience: the open and closed hat are one pair of cymbals at two pedal positions, so they cannot sound at once. Striking the closed hat cuts a ringing open one, the pads wear a tie mark to say so, and the badge is drawn from the same membership table the engine cuts from, a picture of a rule the sound did not follow would be worse than no picture.

The sequencer runs on the audio clock rather than on a browser timer: a lookahead loop wakes every 25 ms, works out which hits fall in the next 120 ms, and commits each one at an absolute time the audio thread already holds. Timer jitter can therefore delay the decision and never move the hit, which is what keeps the pattern steady while the page is doing something else.

PATTERNS ARE FACTORY, and that is a deliberate limit rather than an oversight. A 16-step grid across ten voices is 320 on/off/accent decisions, which cannot be expressed cleanly as numeric parameters, it would be either hundreds of params or one packed integer, and both are hostile to a preset, to a shared link and to a host's automation lane. So the parameter is the SELECTION: six banks, a tempo and a run switch. What you cannot do here is draw your own bar. What you can do is play: the pads stay live the whole time the pattern is running, which is what a machine with a fixed bank is actually for.

This is a preview instrument. The DSP is hand-written Web Audio in the website's stand-in engine, good enough to hear the kick's sweep, the hat choke and the clap's four bursts, but it is not a compiled kernel and it is not covered by any parity claim.

System requirements.

The downloadable Percussion Synth release supports the hosts and systems listed below.

  • VST3macOS · arm64

    Works in Ableton Live, Reaper, Cubase, Studio One, Bitwig and FL Studio.

Version 0.1.0

Build evidence

Every row below is a recorded build row or the recorded absence of one. Nothing here is inferred from what this module is meant to support.

Module
music.codex.drum-synth v0.1.0
Built at
Closure hash
0925673bc11a…
Toolchain
  • scriptc 64acce1ae3b8…
  • moduleToolchainDist c621ffab721d…
  • pluginShellKitRuntime bca003784692…
  • faceShellGeneration 8533207ab81f…
  • uiPreservation cd28dbd7e3d6…
  • packagerVersion 3
Build result and download for each format
FormatResultDownload
Browser package (JS)
Builtweb

bundle sha256 4362d1fff680… · 399 KB

Built, but no downloadable archive was recorded.
Browser package (WASM)
Builtweb

bundle sha256 a6b39d534307… · 2.0 MB

Built, but no downloadable archive was recorded.
VST3
Builtdarwin-arm64Steinberg validator + VST3 host render: passed

bundle sha256 d84071d10eff… · 2.2 MB

CodexDrumSynth-vst3-darwin-arm64.zip

archive sha256 69afb73417de… · 2.2 MB · darwin-arm64

Audio UnitNot built

no recorded artifact row for au; native-lane-report.json is absent or records no au row for this module

Not built for macOS
CLAPNot built

no recorded artifact row for clap; native-lane-report.json is absent or records no clap row for this module

Not built for macOS, Windows or Linux
Standalone appNot built

no recorded artifact row for standalone; native-lane-report.json is absent or records no standalone row for this module

Not built for macOS, Windows or Linux

Parity

browser-js = browser-wasm = vst3 qualified against their own recorded digests. Not recorded: au, clap, standalone.

Presets

Start from a named sound, then adjust the instrument to make it yours.

InitBoom KitClub MachineDry RoomLo-Fi CrunchMetal ShopSoft Brush

Signal graph.

Experimental

Migration fallback: approximated from parameter groups, not a runtime wiring diagram.

How it works.

Each voice is rendered ONCE per setting into an AudioBuffer and played back with a BufferSource, rather than being built as a node graph per hit. Every drum here is a one-shot, struck, decaying, unchangeable afterwards, so there is nothing a live graph could do that a buffer cannot, and the difference at sixteen hits a second is one node per strike instead of six. It is the arrangement the pluck module uses for the same reason, and it has a second payoff: the recipes become a pure function of (voice, params, sample rate), so the kick's sweep and the tone control's flat centre are asserted in Node rather than described.

The kick integrates its phase sample by sample as the frequency falls, rather than evaluating sin(2·pi·f(t)·t). The second form is the classic sweep bug: as f falls, the phase argument can run backwards, and the sweep arrives with a discontinuity in it. Everything with a pitch envelope here, the kick, both toms, is written the first way.

Every noise source is drawn from the SDK's seeded xorshift32, forked by the voice's own id. Math.random() is forbidden in DSP in this repo, and rendering to a buffer makes the rule easy to keep rather than merely stated: the same snare produces the same samples on every machine and in every run, and forking per voice rather than sharing one stream means adding a voice later cannot shift the noise in the ones beside it.

The choke group is two rules kept separate. RETRIGGER: a voice struck again cuts its own previous ring, which every voice does because one drum cannot be hit twice at once. CHOKE: a voice struck cuts every other member of its group, which only the hats have. Both cut with a 4 ms fade rather than a hard stop, because a buffer stopped mid-cycle is a click and a click on every closed hat would be the loudest thing in the mix.

The step player lives inside the voice pool, not in the React layer. A setTimeout in a component fires whenever the main thread gets round to it, so a pattern driven from React drifts audibly under any load; instead a timer wakes every 25 ms, asks a pure function which hits fall in the next 120 ms, and commits each one with an absolute audio-clock time. The pure half, which hits, at what times, with which accent velocities, is a function of an origin and a window, so it is tested from a mocked clock with no audio in the loop at all.

Accent is a velocity, not a second sound: 118 against 86 on the unaccented steps, which through the velocity-squared law comes out about 5 dB louder. A linear velocity map would put those two 3 dB apart and make the accent switch look broken, which is the whole reason the law is squared here as it is everywhere else in this repo.

The pad grid and the step lane are ui-kit registry items rather than parts of this page. Their layout, hit testing, velocity law, drag-paint rule and playhead maths sit in pure cores beside them with their own tests, per the surface catalog's rule that gesture maths lands in the kit first, which is also what lets the pads' choke badge and the engine's choke cut be the same function.

Goes well with.

Preview

OSC Mini

A compact subtractive synth for learning the signal path.

Preview
Preview

Arpeggiator

Walk held notes through a rhythmic pattern.

PreviewNot built for macOS, Windows or Linux
Preview

Pretty Chord

136 chord banks with random selection.

PreviewNo build recorded