FM: the capped rich-carrier corner aliases at -23 dB, and oversampling cannot fix it #67

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

FmPairLayer::RequiredBandwidthRatio now charges for the carrier's own harmonic
index (branch fm-followups): the carrier is an AdditiveOscillator, and Render
adds the modulation before harmonic scaling, so carrier partial k carries k
times the deviation and spreads k times as far.

Charging that term honestly exposes a corner the rule cannot serve. k runs up to
the output Nyquist over fc -- 91 partials at C4 -- so a deep, bright patch on a
square carrier asks for roughly ninety times the bandwidth the same settings need on
a sine carrier. That is not one rung past kMaxOversampleRatio; it is out of reach
of any decimator family. The walk runs out of rungs, the note lands on the ceiling,
and it aliases.

FmAlias.TheCappedRichCarrierCornerStillAliases measures about -23 dB on such a
note against the -60 dB kAliasFloorDb bar.

The rung is still worth having -- the same note reads +2.9 dB at 1x -- and
quieter patches on the same carrier are now served properly rather than capped: the
grid's C4 square cell derived 1x and measured -18.9 dB before this term existed, and
derives 16x and measures -94.1 dB now.

Oversampling is the wrong lever, and nothing should try to grow the family. What
actually fits that note into the band is rendering fewer carrier partials --
kHarmonicLimit, lowered until what survives has room to spread. That changes the
sound rather than only the cost, so it belongs to the graceful-degradation ladder and
to whoever owns the decision about how a patch is allowed to degrade.

Recorded beside kMaxOversampleRatio in dsp/fm_pair_layer.h and in the test above.
Filed so the ladder work has this waiting for it.

`FmPairLayer::RequiredBandwidthRatio` now charges for the carrier's own harmonic index (branch `fm-followups`): the carrier is an `AdditiveOscillator`, and `Render` adds the modulation before harmonic scaling, so carrier partial `k` carries `k` times the deviation and spreads `k` times as far. Charging that term honestly exposes a corner the rule cannot serve. `k` runs up to the output Nyquist over `fc` -- 91 partials at C4 -- so a deep, bright patch on a square carrier asks for roughly ninety times the bandwidth the same settings need on a sine carrier. That is not one rung past `kMaxOversampleRatio`; it is out of reach of any decimator family. The walk runs out of rungs, the note lands on the ceiling, and it aliases. `FmAlias.TheCappedRichCarrierCornerStillAliases` measures about **-23 dB** on such a note against the -60 dB `kAliasFloorDb` bar. The rung is still worth having -- the same note reads **+2.9 dB** at 1x -- and quieter patches on the same carrier are now served properly rather than capped: the grid's C4 square cell derived 1x and measured -18.9 dB before this term existed, and derives 16x and measures -94.1 dB now. **Oversampling is the wrong lever, and nothing should try to grow the family.** What actually fits that note into the band is rendering fewer carrier partials -- `kHarmonicLimit`, lowered until what survives has room to spread. That changes the sound rather than only the cost, so it belongs to the graceful-degradation ladder and to whoever owns the decision about how a patch is allowed to degrade. Recorded beside `kMaxOversampleRatio` in `dsp/fm_pair_layer.h` and in the test above. Filed so the ladder work has this waiting for it.
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#67
No description provided.