Generated from Markdown source. Edit the source, not this HTML.
Sound design workflow #
Example 12 (checkout-only) is a browser FM designer built only on the public API (OPM, playNote, updateNote). It is a demo helper, not part of the engine. Start it over HTTPS or localhost, click Start, then hold a note (button or Space) and edit while it sounds. Begin at a low device volume: host gain defaults to 0.15 and is capped at 0.3.
What you can edit #
| Area | Controls |
|---|---|
| Topology | Algorithm 0–7 with a live signal graph (arrows run from modulator to recipient; carriers reach the output), operator-1 feedback 0–7, modulation index |
| Operators | Ratio, level, detune, waveform, noise hold rate (20–20000 Hz) and four-stage ADSR for each operator |
| LFO | Rate, AM depth, PM cents, waveform, delay, note/global sync, phase, and a 0–1 AM and PM target weight per operator (the selective-LFO fields) |
| Envelopes | A dB-versus-time plot of each operator for a chosen gate length. It evaluates the engine's own envelopeAt, so segments that are straight in dB are exponential in amplitude, and −96 dB is the engine floor. |
| Starting points | Every bundled recipe, with its provenance, intended register, velocity range and host trim shown beside it |
| Audio | DSP profile (eco / standard / high), note, velocity, host gain |
Live edits versus retriggers #
A held note is edited natively where the engine has a live control, and retriggered otherwise:
| Edit | Behavior while a note is held |
|---|---|
| Operator ratio | operatorRatios ramp (20 ms) |
| Any ADSR stage | operatorADSR, re-anchored at the current dB level |
| Feedback | feedback ramp (20 ms) |
| LFO rate, AM depth, PM depth | lfoRate, amDepth, pmDepth ramp |
| Algorithm, selective target weights, level, detune, operator/LFO waveform, noise rate, delay/sync/phase, modulation index | The note is released and retriggered, because these are fixed when a note is admitted |
| Name | No audio change |
The envelope plot shows a fresh note. Key-rate scaling, pitch envelopes, velocity and the LFO can alter an actual note, and a live ADSR edit starts from the sounding level, so the plot is a guide rather than an oscilloscope.
Patch JSON #
The page exports and imports one canonical version 7 patch (at most 16 KiB). Import uses the strict single-voice path: unknown fields, accessors, non-finite numbers and out-of-range values are rejected visibly, and legacy versions 1–6 are normalized to version 7. The exported file can be passed straight to opm.playNote({ voice: patch, note: 60 }) or loaded with opm.loadVoice(name, patch). Nothing is uploaded; use the bank tools for many voices at once.
Choose noise for an unpitched deterministic held-noise oscillator; noise rate is ignored for periodic shapes. Ratio/fixed-Hz/live pitch controls do not pitch noise, but envelopes, levels, velocity, key scaling and AM still apply. Noise can modulate or act as a carrier on any operator, an OPM.js extension rather than a hardware-fidelity claim. Square/saw/noise are not alias-free despite per-voice oversampling. The recipe selector automatically includes original noise-snare, noise-hihat and explosion starting points; see oscillator formulas.
Designing with selective LFO #
By default the LFO touches every operator. Set pmTargets / amTargets to confine it:
PM on a carrier wobbles the pitch you hear; PM on a modulator changes brightness without vibrato.
AM on a carrier is tremolo of that carrier; AM on a modulator moves sideband strength.
A weight of 0 leaves an operator untouched; fractional weights scale the depth for that operator.
tide_keys, ember_bass and orbit_pad in the voice quality guide are worked examples, and the audition page (checkout-only) can A/B them against other recipes with a held ratio/feedback/ADSR control phrase.
Limits #
The designer previews one note at a time on the main OPM instance of the page. It does not predict polyphonic loudness; leave headroom when chords are played (see the suggested polyphony and trim in the usage table). No listening judgment is built in.