How it works
SIGIL
Sound-design instrument. A synth with six ways to make sound that plays in a browser tab or inside your DAW. Hunt breeds new patches from the ones you keep, so you find sounds by ear.
Invite-only for now · demos publicVisit the site ↗
Architecture
Hover a box to trace its connections; click it for what it does.
- request
- webhook, queue, schedule
- the heart
- outside service
APlay· 4Browser tab · MIDI · keyboard · Your DAW · Claude
Browser tabNext.js 16 · ReactUI
UI · Next.js 16 · React
The instrument in a browser. The public build keeps everything in the browser, with no accounts and nothing stored on a server.
Talks to
- → React UI
- → Server routes (gate)
MIDI · keyboardWebMIDI · computer keysUI
UI · WebMIDI · computer keys
Play from a controller or the computer keyboard, in a chosen key and scale. Every browser API is optional; missing ones fail quietly.
Talks to
- → React UI (notes)
Your DAWVST3 · standaloneEXTERNAL
EXTERNAL · VST3 · standalone
Ableton or any VST3 host, on Apple Silicon, loading the plugin build.
Talks to
- ← Bounce · record (drag WAV)
- ← JUCE plugin (VST3)
ClaudeMCP clientEXTERNAL
EXTERNAL · MCP client
Claude can list engines and presets, make and change patches, and write chord progressions.
Talks to
- → MCP endpoint (MCP)
BInterface· 5Bounce · record · React UI · Hunt · Names & glyphs · MCP endpoint
Bounce · recordWAV · drag outSERVICE
SERVICE · WAV · drag out
Renders a sound offline to WAV, or records it, then lets you drag the file onto a DAW track (in Chrome) or download it.
Talks to
- ← React UI
- → Your DAW (drag WAV)
React UIone UI for bothUI
UI · one UI for both
The same interface in the browser and inside the plugin: engines, macros, the XY pad, presets and Hunt.
Talks to
- ← Browser tab
- ← MIDI · keyboard (notes)
- ← Hunt (six takes)
- → AudioWorklet (params · notes)
- → Bounce · record
- → JUCE plugin (bundled)
Huntmutate · breed · tasteSERVICE
SERVICE · mutate · breed · taste
Six variations at a time, judged by ear. Keeping some nudges the next generation toward them, within limits, and the nudge fades unless you keep choosing it.
Talks to
- ← Presets (seeds)
- → Names & glyphs (name · mark)
- → React UI (six takes)
Names & glyphsfrom parametersSERVICE
SERVICE · from parameters
A patch’s name and mark are computed from its parameters, so the same sound gets the same name everywhere, with nothing stored.
Talks to
- ← Hunt (name · mark)
MCP endpoint13 tools · JSON-RPCAI
AI · 13 tools · JSON-RPC
A plain HTTP POST endpoint. The protocol layer knows nothing about music; every tool body is a tested function.
Talks to
- ← Claude (MCP)
- → Six engines (patches)
CSound· 4Presets · DSP core · Six engines · FX & character
Presets84 across the banksSTORE
STORE · 84 across the banks
Starting points for every engine, plus a percussion bank.
Talks to
- → Hunt (seeds)
DSP coreTypeScript · referenceSERVICE
SERVICE · TypeScript · reference
The synthesis itself, in plain TypeScript: no browser APIs and no allocation in the render loops.
Talks to
- ← AudioWorklet (renders)
- → Six engines
- → Parity check (goldens)
Six enginesanalog · FM · physical …SERVICE
SERVICE · analog · FM · physical …
Analog, FM, physical modelling, granular, wavetable and sampler voices, under one voice manager.
Talks to
- ← DSP core
- → FX & character
- ← MCP endpoint (patches)
FX & charactertwo chainsSERVICE
SERVICE · two chains
An effects chain and a character chain, available on every engine.
Talks to
- ← Six engines
DHosts· 3AudioWorklet · C++ engine · JUCE plugin
AudioWorkletseparate realmREALTIME
REALTIME · separate realm
Runs the DSP on the browser’s audio thread. It is bundled on its own and only hears what the page posts to it.
Talks to
- ← React UI (params · notes)
- → DSP core (renders)
C++ enginehand portSERVICE
SERVICE · hand port
The same DSP in C++, kept in step with the TypeScript.
Talks to
- ← JUCE plugin (process)
- → Parity check (compared)
JUCE pluginWebView UI insideSERVICE
SERVICE · WebView UI inside
Wraps the C++ engine as a VST3 and serves the React UI from inside the binary. Parameters are only ever appended, so saved automation never moves.
Talks to
- ← React UI (bundled)
- → C++ engine (process)
- → Your DAW (VST3)
EBuild· 3Server routes · PostgreSQL · Parity check
Server routespasscode gate · sign-upsSERVICE
SERVICE · passcode gate · sign-ups
The private build sits behind a passcode; the public one has none. One setting decides, not a fork.
Talks to
- ← Browser tab (gate)
- → PostgreSQL (SQL)
PostgreSQLsign-upsSTORE
STORE · sign-ups
Email sign-ups from the landing page.
Talks to
- ← Server routes (SQL)
Parity check197 golden rendersJOB
JOB · 197 golden renders
Renders fresh goldens from the TypeScript and measures the C++ against them on every build.
Talks to
- ← DSP core (goldens)
- ← C++ engine (compared)
Connections · 20
→ request · ⇢ webhook, queue or schedule
- Browser tab → React UI
- MIDI · keyboard → React UI · notes
- Presets → Hunt · seeds
- Hunt → Names & glyphs · name · mark
- Hunt → React UI · six takes
- React UI → AudioWorklet · params · notes
- AudioWorklet → DSP core · renders
- DSP core → Six engines
- Six engines → FX & character
- React UI → Bounce · record
- Bounce · record → Your DAW · drag WAV
- React UI → JUCE plugin · bundled
- JUCE plugin → C++ engine · process
- JUCE plugin → Your DAW · VST3
- DSP core → Parity check · goldens
- C++ engine → Parity check · compared
- Claude → MCP endpoint · MCP
- MCP endpoint → Six engines · patches
- Browser tab → Server routes · gate
- Server routes → PostgreSQL · SQL
Inside: the engines and Hunt
Each engine is a description plus a voice; the interface, the plugin parameters and Hunt are all built from the description. Hunt breeds sounds from a single seed, so a whole session can be replayed from one number.
Hover a box to trace its connections; click it for what it does.
ADescribe· 3Engine registry · Descriptors · Built interface
Engine registryone line per engineSERVICE
SERVICE · one line per engine
Adding an engine is one line here plus its module. No app code changes.
Talks to
- → Descriptors
Descriptorsparams · ranges · groupsSTORE
STORE · params · ranges · groups
Every parameter with its range, default, curve and group. Linear and exponential parameters are normalised differently so a step means the same thing to the ear.
Talks to
- ← Engine registry
- → Built interface (builds)
- → Voice manager (params)
Built interfacefrom descriptorsUI
UI · from descriptors
The controls draw themselves from the descriptor.
Talks to
- ← Descriptors (builds)
BVoices· 7Voice manager · Analog · FM · Physical · Granular · Wavetable · Sampler
Voice managerpolyphonySERVICE
SERVICE · polyphony
Owns polyphony so engines never think about it. Every voice is allocated up front, so playing a note allocates nothing.
Talks to
- ← Descriptors (params)
- → Analog (voices)
- ← Smoothing
- → Granular
Analogantialiased saw · ladderSERVICE
SERVICE · antialiased saw · ladder
Subtractive voice with an antialiased sawtooth, so the top end sounds clean rather than harsh, into a ladder filter.
Talks to
- ← Voice manager (voices)
FMvelocity → brightnessSERVICE
SERVICE · velocity → brightness
Frequency modulation where playing harder opens the timbre, like a real tine, and nothing you do can push a preset past the brightness it was voiced at.
Physicalmembrane · wood · metal · glassSERVICE
SERVICE · membrane · wood · metal · glass
A bank of resonant modes shaped like a drum head, a wooden bar, a bell or glass. Bowed excitation is bounded so it can never build up forever.
Talks to
- → Effects chain (mix)
Granularshared buffersSERVICE
SERVICE · shared buffers
Grain clouds panned across the field, sharing one buffer across voices instead of megabytes per note, with tapered windows so grains never click.
Talks to
- ← Voice manager
Wavetablesine → metallicSERVICE
SERVICE · sine → metallic
Tables that run from pure to complex: sine, triangle, soft organic, square, saw, two vocal formants and metallic.
Sampleryour samplesSERVICE
SERVICE · your samples
Every voice plays one shared sample; swapping a 30 MB recording is a single reference swap between audio blocks.
CSignal· 3Smoothing · Effects chain · Character chain
Smoothingevery parameterSERVICE
SERVICE · every parameter
Every parameter passes through a smoother. Unsmoothed changes cause zipper noise, the most common reason a digital synth sounds cheap.
Talks to
- → Voice manager
Effects chainchorus · delay · reverbSERVICE
SERVICE · chorus · delay · reverb
Where the signal becomes stereo. Each unit is skipped when its mix is silent.
Talks to
- ← Physical (mix)
- → Character chain
Character chainbounded ±1.2SERVICE
SERVICE · bounded ±1.2
Effects that make a listener ask what that was, allocation-free and guarded against denormals, and bounded so nothing can push the output past ±1.2.
Talks to
- ← Effects chain
DHunt· 6Seed · Mutate · Breed · Taste · Lineage · Name & glyph
Seedone numberSERVICE
SERVICE · one number
A deterministic generator: the same seed gives the same hunt on every machine, so a session can be shared as a single number.
Talks to
- → Mutate
Mutatesix distinct takesSERVICE
SERVICE · six distinct takes
Walks the current patch to six variations, retrying until they sound distinct from each other.
Talks to
- ← Seed
- ← Breed
- → Lineage (what changed)
Breedtwo kept parentsSERVICE
SERVICE · two kept parents
Crosses two patches you kept, with a little jitter.
Talks to
- → Mutate
- ← Taste (bias)
Tastebounded · blended · fadingSERVICE
SERVICE · bounded · blended · fading
Turns what you keep into a direction for the next generation: capped so it can’t pin a parameter, blended so one odd keep doesn’t define you, and fading unless you keep choosing it.
Talks to
- → Breed (bias)
Lineage“brighter”, “looser”SERVICE
SERVICE · “brighter”, “looser”
Names the one or two things that changed in a player’s words, and keeps the trail of moves that found a sound.
Talks to
- ← Mutate (what changed)
- → Name & glyph
Name & glyphfrom parametersSERVICE
SERVICE · from parameters
Computed from the parameter values, so the same sound always has the same name and mark.
Talks to
- ← Lineage
Connections · 13
→ request · ⇢ webhook, queue or schedule
- Engine registry → Descriptors
- Descriptors → Built interface · builds
- Descriptors → Voice manager · params
- Voice manager → Analog · voices
- Smoothing → Voice manager
- Voice manager → Granular
- Physical → Effects chain · mix
- Effects chain → Character chain
- Seed → Mutate
- Breed → Mutate
- Taste → Breed · bias
- Mutate → Lineage · what changed
- Lineage → Name & glyph
Two flows
Finding a sound
Walk through it and each step lights the parts it runs through in the drawings above.
By count
- engines
- 6
- presets
- 84
- actions Claude can take in it
- 13
Notes
- N.1A patch’s name and glyph come from how it sounds. The same sound is called the same thing on every machine, and a heavy dark patch can’t come out called Bright Tide.
- N.2Hunt shows no knobs. You choose by ear, and each patch keeps the moves that found it, written the way a player would say them.
- N.3The plugin and the browser make the same sound, so a patch you find in a tab sounds identical in your DAW.
Built by
I design, architect and build software products like this one.
More systems