Tines
A pickup-position model for tuned tine voices.
A four-operator FM keyboard with no filter.
Engine preview
VST3
An FM operator is an oscillator and an envelope, and nothing else. There is no filter anywhere in this module, no cutoff, no resonance, no tone control, and it still makes metal, glass, wood and breath. That is the whole reason FM took over the eighties, and it is why a module with four sine waves in it needs an explanation before it needs a knob.
What decides which of those sounds you get is not a knob at all, it is the wiring. An operator either reaches the output, in which case you hear it, or it is connected to another operator's pitch, in which case you hear what it does to that one. Six wirings, algorithms, are published here, and the difference between them is larger than the difference between any two settings of anything else on the panel. The routing diagram is the module's hero for that reason: it is the one control whose effect you cannot guess.
Modulation depth is set as a multiple of the pitch being modulated rather than in hertz, and that choice is what makes a patch survive being played in a different octave. A fixed 200 Hz of deviation is a whole tone at the top of the keyboard and two octaves at the bottom; a deviation that scales with the note keeps the ratio between deviation and modulator frequency constant, and with it the spectrum. One patch, one timbre, the whole keyboard.
The exception is deliberate and is half of what FM is for. Five entries at the end of every ratio list are absolute frequencies, and an operator set to one of them does not track the note at all. Play up the keyboard and it stays where it is, which is a formant, and formants are how FM does vocal, wooden and percussive sounds that a ratio-locked patch cannot.
Velocity is wired to modulation index, not only to volume. Because a modulator's level is an index rather than a loudness, playing harder adds sidebands rather than just decibels, and that is the entire difference between an FM patch that feels played and one that feels triggered. The amount is a control, because a bell struck softly really is the same bell.
Operator 4 carries feedback, and it is computed rather than looped. A sine phase-modulating itself settles on a fixed harmonic spectrum, the same Bessel series that solves Kepler's equation, so the operator's waveform is built from those coefficients directly. It is exact, it cannot go unstable, and at the top of the knob it is a sawtooth, which is the well-known place operator feedback ends up. Past that the waveform stops being single-valued, which is why the control stops there.
The envelope table is curated rather than complete. Operators 1 and 2 get a full ADSR; operators 3 and 4 get an attack and a decay, and their sustain is fixed at zero. That is a reduction from twenty-odd envelope controls to twelve, and it is the right twelve because an operator decaying to nothing is the most characteristic gesture in the whole idiom, the modulator dies away and leaves the carrier as a pure sine, so a note starts as metal and ends as glass. Every FM electric piano is that shape. A patch that needs modulation held through the sustain uses operator 2, which has one.
This is a preview instrument. The DSP is hand-written Web Audio in the website's stand-in engine, real oscillators with their gains connected to real frequency parameters, but it is not a compiled kernel and it is not covered by any parity claim.
The downloadable FM Keys release supports the hosts and systems listed below.
Works in Ableton Live, Reaper, Cubase, Studio One, Bitwig and FL Studio.
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.
| Format | Result | Download |
|---|---|---|
| Browser package (JS) | Builtweb bundle sha256 ef4acf21e6af… · 336 KB | Built, but no downloadable archive was recorded. |
| Browser package (WASM) | Builtweb bundle sha256 30d7dfb38b44… · 2.0 MB | Built, but no downloadable archive was recorded. |
| VST3 | Builtdarwin-arm64Steinberg validator + VST3 host render: passed bundle sha256 320090f547ff… · 2.2 MB | CodexFmKeys-vst3-darwin-arm64.zip archive sha256 c316a827a5d9… · 2.2 MB · darwin-arm64 |
| Audio Unit | Not 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 |
| CLAP | Not 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 app | Not 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.
Start from a named sound, then adjust the instrument to make it yours.
Migration fallback: approximated from parameter groups, not a runtime wiring diagram.
Each voice builds four OscillatorNodes and four GainNodes, one envelope per operator, and wires them according to the selected algorithm. The modulation itself uses the fact that an AudioParam is a summing junction: a modulator's envelope feeds a GainNode whose output is connected to the target oscillator's `frequency` parameter, so the gain's value is added to the target's pitch sample by sample. That value is the peak frequency deviation in hertz. This is genuine frequency modulation rather than the phase modulation a DX-style chip runs, and for sine operators the two produce the same spectrum, which is what makes the approximation a fair one, and which stops being true exactly when feedback makes operator 4 non-sinusoidal.
The deviation for each connection is the modulating operator's index multiplied by the frequency of the operator it modulates, so every frequency in a patch scales with the played note together. The ratio between deviation and modulator frequency is therefore constant across the keyboard, and so is the spectrum. A deviation fixed in hertz would be a whole tone at the top of the keyboard and two octaves at the bottom, which is why nothing here is set in hertz except the five ratio entries that are meant to be, those are fixed-frequency operators, and they stay put while the keyboard moves under them.
The ratio control is stepped rather than continuous, and that is a usability decision with teeth. The musically meaningful ratios are a measure-zero subset of any continuous range, the whole numbers, plus a handful of irrationals, and everything between them is a detune that sounds like a mistake. Twenty positions cover the whole numbers from 0.5 to 8, the √2 family that produces inharmonic bell spectra, and five absolute frequencies.
Operator 4's feedback is closed form. A cycle in a Web Audio graph must contain a DelayNode, and the smallest available delay is a whole 128-sample render quantum, which would be a comb filter at a sample-rate-dependent frequency rather than feedback. Instead the steady state is computed: a sine phase-modulating itself at depth β has harmonic amplitudes 2·Jₙ(nβ)/(nβ), the Bessel series that also solves Kepler's equation, and a PeriodicWave built from those coefficients is that steady state exactly. It is deterministic, band-limited by the oscillator like any other periodic wave, and costs nothing per sample. The one thing it does not reproduce is the loop's build-up transient, which arrives fully formed here.
Velocity does two separate things. Carrier levels are scaled by velocity squared, the repo's standard curve, because loudness is not linear in amplitude and a straight mapping leaves the quiet end of the keyboard feeling dead. Modulator indices are scaled by a separate curve under the Vel → Index control, and because index is brightness that is what makes playing harder sound harder rather than only louder.
Envelope decays are scheduled as an exponential ramp to the sustain level and then a step onto it, because an exponential ramp cannot reach zero and most of this instrument's operators decay to exactly that. Releases start from wherever the envelope has actually got to rather than from the sustain level, so letting go during an attack fades from the partial level instead of jumping up first.
Levels, brightness and feedback are pushed onto sounding voices as they move, because those are the controls a player sweeps while holding a chord. The algorithm, the four ratios and the envelope times are read at note-on and take effect on the next note: rewiring a live graph or re-pitching a ringing operator would click, and a patch edit that lands on the next note is the honest behaviour rather than one worth hiding.
Voices are capped at eight with oldest-first stealing, and a re-pressed key replaces its own voice rather than summing with it. Nothing in the signal path is random, there is no exciter and no noise, and a four-operator FM voice has nothing to be random about, so the same patch, note and velocity produce the same waveform every time.
A pickup-position model for tuned tine voices.
A tonewheel organ with nine drawbars and no attack stage.
Single-cycle waves with continuous position morphing.