A traditional FM engine: operators and algorithms as the DX7, DX1 and FM-X have them, without the pair's additive carrier #138

Open
opened 2026-10-06 00:13:39 +00:00 by bcox · 0 comments
Owner

bcox asked on 2026-10-05 for this ticket, to cover the DX7 algorithms the importer refuses and the operator features the pair has no place for, with Yamaha's later operator features in scope where no patent bars them. Engine claims are from reading the tree at f6aa8eba on main. Hardware claims marked as recollection were not read from a source in that session. Nothing here is built, measured or listened to.

Why a second FM engine

The FM pair is one carrier and up to two modulators per layer, with the carrier an additive spectrum of up to 512 harmonics crossfaded through a table (dsp/spectrum.h, plugin/program.h:71, :97). That is what makes it the resynthesis engine and the Synclavier's, and it is also why a DX7 voice reaches it only through dx7/decompose.h, which splits an algorithm into pair-shaped stacks and refuses what does not split (dx7/decompose.h:54-66): feedback spanning two operators (algorithms 4 and 6), a chain deeper than three operators, three or more parallel modulators, a modulator fed by more than one operator, a modulator shared between two carriers. The importer also drops level scaling and rate scaling per operator (dx7/translate.cc:680-687), refuses a fixed-frequency operator (:659-662, #126), and bakes feedback into a static table because the pair has no loop (:871-878; dsp/fm_pair_layer.h:636-646 argues series routing replaces it for the pair's purposes).

A traditional engine has none of that complexity and all of those features: N operators, each a sine, each with its own envelope, level scaling, rate scaling, velocity sensitivity and frequency mode, wired by an algorithm table, with feedback on an operator the algorithm names.

What it covers

  • DX7: six operators, thirty-two algorithms, one feedback loop; rate-and-level envelopes; keyboard level scaling with a break point and a curve per side; rate scaling; fixed or ratio frequency with detune; one LFO with pitch and amplitude depth and per-operator amplitude sensitivity; a pitch envelope; oscillator key sync. dx7/vced.h holds the parameter block already, and the importer's envelope tracing against Dexed's env.cc carries over.
  • DX1 and DX5: two such generators per voice, layered or split (recollection).
  • FM-X (Montage, MODX): eight operators and 88 algorithms; per-operator spectral forms beyond the sine (sine, all-harmonic and odd-harmonic forms, resonant forms) with skirt and resonance controls that shape each operator's own spectrum; feedback available on more than one operator (recollection throughout). Before any of it goes in, check whether the spectral forms, skirt and resonance are under a live patent; the TX81Z's eight operator waveforms and the SY77's AFM waveforms are the earlier forms of the same idea, which is a fact about history and not a legal opinion. Adopt what is free; name nothing after a trademark.
  • The 4-operator family (DX21, TX81Z): eight waveforms per operator; a subset of the above once operator waveforms exist.

What shapes it

  • Phase modulation at the tick, as the DX7 does, with the pair's kPhase law; the kFrequency law is the pair's and can stay there.
  • Aliasing: the pair derives its oversampling from its tables' harmonic content (#24, #67, #68). A sine operator's bandwidth follows from its index and ratio (Carson's rule), so a derived ratio per patch is the same shape of decision with a simpler input.
  • Fabric cost per operator per tick: one sine lookup and a multiply-add, plus the envelope. Six operators at 128 voices is the figure to price before the shape is fixed; //plugin:instrument_bench is where it gets a scenario.
  • A new LayerKind, appended (plugin/program.h:1120); every switch over it is a registration site under -Werror=switch, and patchdiff/ needs a walker or its fields report as unaccounted.
  • The importer becomes a translation rather than a decomposition: every algorithm, no refusals, with the loss report shrinking to the envelope-tracing notes.
  • #126 (fixed-frequency operator) and #65 (keytrack on the pair's deviation) stay the pair's tickets; this engine takes both features natively.
  • The pair keeps its place: a spectrum moving at audio rate against its own fundamental is the thing an operator cannot stand in for.
bcox asked on 2026-10-05 for this ticket, to cover the DX7 algorithms the importer refuses and the operator features the pair has no place for, with Yamaha's later operator features in scope where no patent bars them. Engine claims are from reading the tree at `f6aa8eba` on `main`. Hardware claims marked as recollection were not read from a source in that session. **Nothing here is built, measured or listened to.** ## Why a second FM engine The FM pair is one carrier and up to two modulators per layer, with the carrier an additive spectrum of up to 512 harmonics crossfaded through a table (`dsp/spectrum.h`, `plugin/program.h:71`, `:97`). That is what makes it the resynthesis engine and the Synclavier's, and it is also why a DX7 voice reaches it only through `dx7/decompose.h`, which splits an algorithm into pair-shaped stacks and refuses what does not split (`dx7/decompose.h:54-66`): feedback spanning two operators (algorithms 4 and 6), a chain deeper than three operators, three or more parallel modulators, a modulator fed by more than one operator, a modulator shared between two carriers. The importer also drops level scaling and rate scaling per operator (`dx7/translate.cc:680-687`), refuses a fixed-frequency operator (`:659-662`, #126), and bakes feedback into a static table because the pair has no loop (`:871-878`; `dsp/fm_pair_layer.h:636-646` argues series routing replaces it for the pair's purposes). A traditional engine has none of that complexity and all of those features: N operators, each a sine, each with its own envelope, level scaling, rate scaling, velocity sensitivity and frequency mode, wired by an algorithm table, with feedback on an operator the algorithm names. ## What it covers - **DX7**: six operators, thirty-two algorithms, one feedback loop; rate-and-level envelopes; keyboard level scaling with a break point and a curve per side; rate scaling; fixed or ratio frequency with detune; one LFO with pitch and amplitude depth and per-operator amplitude sensitivity; a pitch envelope; oscillator key sync. `dx7/vced.h` holds the parameter block already, and the importer's envelope tracing against Dexed's `env.cc` carries over. - **DX1 and DX5**: two such generators per voice, layered or split (recollection). - **FM-X** (Montage, MODX): eight operators and 88 algorithms; per-operator spectral forms beyond the sine (sine, all-harmonic and odd-harmonic forms, resonant forms) with skirt and resonance controls that shape each operator's own spectrum; feedback available on more than one operator (recollection throughout). Before any of it goes in, check whether the spectral forms, skirt and resonance are under a live patent; the TX81Z's eight operator waveforms and the SY77's AFM waveforms are the earlier forms of the same idea, which is a fact about history and not a legal opinion. Adopt what is free; name nothing after a trademark. - **The 4-operator family** (DX21, TX81Z): eight waveforms per operator; a subset of the above once operator waveforms exist. ## What shapes it - Phase modulation at the tick, as the DX7 does, with the pair's `kPhase` law; the `kFrequency` law is the pair's and can stay there. - Aliasing: the pair derives its oversampling from its tables' harmonic content (#24, #67, #68). A sine operator's bandwidth follows from its index and ratio (Carson's rule), so a derived ratio per patch is the same shape of decision with a simpler input. - Fabric cost per operator per tick: one sine lookup and a multiply-add, plus the envelope. Six operators at 128 voices is the figure to price before the shape is fixed; `//plugin:instrument_bench` is where it gets a scenario. - A new `LayerKind`, appended (`plugin/program.h:1120`); every switch over it is a registration site under `-Werror=switch`, and `patchdiff/` needs a walker or its fields report as unaccounted. - The importer becomes a translation rather than a decomposition: every algorithm, no refusals, with the loss report shrinking to the envelope-tracing notes. ## Related - #126 (fixed-frequency operator) and #65 (keytrack on the pair's deviation) stay the pair's tickets; this engine takes both features natively. - The pair keeps its place: a spectrum moving at audio rate against its own fundamental is the thing an operator cannot stand in for.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal#138
No description provided.