The modulators are band-limited to the output Nyquist, so FM silently vanishes above G6 at ratio 16 #32
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
bcox/tymbal#32
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Both modulators in
dsp/fm_pair_layer.hare band-limited to the outputNyquist, the same limit the carrier gets. A modulator is never heard directly
-- only its sidebands are -- so that limit costs the pair its modulation
entirely once the modulator frequency crosses 24 kHz, and it does so at pitches
that are inside the playable range.
Found alongside #24 and split out from it. It is not an oversampling problem:
deriving a higher ratio for the note does not bring the modulator back, for the
reason below.
The defect
harmonic_limit_is set atdsp/fm_pair_layer.h:1168:Dividing the internal Nyquist increment by the ratio gives the increment that
corresponds to 24 kHz at any ratio, so this is the output Nyquist expressed
in the internal domain. That is right for the carrier, and
kHarmonicLimit'scomment says so outright: "Harmonics stop at the output rate's Nyquist. The
extra bandwidth exists for the modulation sidebands, not to widen the
instrument itself."
The same member is then handed to both modulators:
dsp/fm_pair_layer.h:1821-- modulator 1dsp/fm_pair_layer.h:1947-- modulator 2AdditiveOscillator::Renderkeeps harmonickonly whilek * increment < limit, so a modulator whose fundamental is already at or above the limitrenders zero harmonics and outputs silence. Zero modulator is zero deviation,
and the pair degenerates to its carrier.
Because the limit tracks the output rate rather than the internal one,
ratio_cancels out of it. A note that derives 16x has exactly the same modulator
bandwidth as one that derives 1x.
Where it bites
The last modulator partial goes when
ratio * fc >= 24000(at 48 kHz), whichis key
69 + 12*log2(24000 / (440 * ratio)):At ratio 16 the cliff is at G6. That is not the top of the keyboard; it is in
the middle of it, and a patch held at ratio 16 stops responding to its depth
lane partway up a scale.
Measured for #24 at C7 with ratio 16: moving depth from zero to maximum changes
nothing at all, with total energy and carrier level both holding at -6.0 dBFS.
fmis 33.5 kHz there, which is the first row of the table applied to a notewell past its threshold.
A modulator spectrum with more than one partial thins progressively before it
cliffs -- the higher partials cross the limit first -- so the audible result is
a modulator that loses its brightness as pitch rises and then vanishes, rather
than a single clean discontinuity. Only the last partial's departure is abrupt.
Why it is not #24
#24 makes the ratio follow the patch and the note so the sidebands have room to
exist. This issue is upstream of that: the sidebands are never generated,
because the thing that would generate them was band-limited away first. The two
touch the same corner of the parameter space and have opposite signs -- #24's
corner is where there is too much modulator bandwidth to represent at 8x, and
this one is where there is none at all.
Proposal
Limit the modulators to the internal Nyquist and leave the carrier on the
output Nyquist. Concretely, a second member alongside
harmonic_limit_--kNyquistIncrementunmodified, since the internal Nyquist is what aPhaseIncrementis natively against -- passed at the two modulator call siteswhile the three carrier sites keep the existing one.
That is band-limiting doing what it should for a signal that is not audio: the
modulator has to be representable at the rate it is computed at, and nothing
more. Whatever sidebands it then produces above the output Nyquist are the
decimator's problem, which is what the decimator is for, and #24's derivation is
what will size it.
What it costs
This changes what the instrument sounds like, not how accurately it renders
what it already sounds like, and the blast radius is the reason it is filed
separately rather than folded into #24:
always been discarded start contributing.
plugin/render_golden_test.ccandplugin/wave_position_golden_test.ccboth.pitch. Nobody has heard the difference yet, so there is no expectation to
break, but it is a real timbral change and not a bug fix in the narrow sense.
modulator that now has partials where it had none needs the bandwidth to
carry their sidebands, so #24's rule will derive higher ratios for exactly
the notes this fixes. Landing #24 first means its measurements are taken
against the modulator bandwidth this issue changes, so the derivation's
validation grid will need re-running afterwards rather than merely extending.
Landing after #24, deliberately, so that a golden that moves can be attributed
to one of the two rather than to both at once.