FM kFrequency: the modulator's own a1 scales the deviation a patch needs, and nothing shows it #66

Open
opened 2026-09-05 23:17:49 +00:00 by bcox · 0 comments
Owner

Under Patch::IndexLaw::kFrequency the depth lane is a peak deviation in hertz
and the index is d / fm. What that hides is that the deviation actually
delivered to the carrier is scaled by the modulator's fundamental amplitude.

Measured on branch fm-followups:

  • A sine modulator has a1 = 1.0, the cheapest a modulator can be.
  • patches/chowning_horn.h's flat four-partial table has a1 = 0.45, so the same
    index costs it 2.2x the deviation.

An author who reads a1 as if it were 1 underestimates what the lane owes them by
that factor. max_deviation_hz knows nothing about it, and the editor never shows
it -- the depth slider reads in hertz, and that number is not the hertz the carrier
sees.

This is not a defect in the derivation. RequiredBandwidthRatio already weights
each modulator partial by its own amplitude and applies the integrator's 1/m
correctly. It is a usability gap between what the lane says and what the sound
does.

Options, none obviously right:

  1. Show the effective index in the editor's FM page, computed at the current note.
    Honest, and it makes the whole law legible rather than just this one factor.
  2. Normalize the modulator table's a1 to 1 at load and fold the difference into
    the depth lane. Makes the number mean what it says, but changes what an authored
    table means and would move existing patches.
  3. Document it and leave it. Cheapest, and the trap stays set.

Option 1 is probably right, and pairs naturally with whatever comes of the keytrack
issue.

Related trap, already recorded in patches/chowning_horn.h's header: under this law
a modulator table shaped like 1/m arrives at the carrier as 1/m^2, so the rolloff
a brass spectrum wants is authored by not authoring one.

Under `Patch::IndexLaw::kFrequency` the depth lane is a peak deviation in hertz and the index is `d / fm`. What that hides is that the deviation actually delivered to the carrier is scaled by the modulator's *fundamental amplitude*. Measured on branch `fm-followups`: - A sine modulator has `a1 = 1.0`, the cheapest a modulator can be. - `patches/chowning_horn.h`'s flat four-partial table has `a1 = 0.45`, so the same index costs it **2.2x** the deviation. An author who reads `a1` as if it were 1 underestimates what the lane owes them by that factor. `max_deviation_hz` knows nothing about it, and the editor never shows it -- the depth slider reads in hertz, and that number is not the hertz the carrier sees. This is not a defect in the derivation. `RequiredBandwidthRatio` already weights each modulator partial by its own amplitude and applies the integrator's `1/m` correctly. It is a **usability** gap between what the lane says and what the sound does. Options, none obviously right: 1. Show the effective index in the editor's FM page, computed at the current note. Honest, and it makes the whole law legible rather than just this one factor. 2. Normalize the modulator table's `a1` to 1 at load and fold the difference into the depth lane. Makes the number mean what it says, but changes what an authored table means and would move existing patches. 3. Document it and leave it. Cheapest, and the trap stays set. Option 1 is probably right, and pairs naturally with whatever comes of the keytrack issue. Related trap, already recorded in `patches/chowning_horn.h`'s header: under this law a modulator table shaped like `1/m` arrives at the carrier as `1/m^2`, so the rolloff a brass spectrum wants is authored by *not* authoring one.
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#66
No description provided.