Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

filter cutoff and Q NRPNs don't behave correctly #1473

Open
mrbumpy409 opened this issue Jan 21, 2025 · 0 comments
Open

filter cutoff and Q NRPNs don't behave correctly #1473

mrbumpy409 opened this issue Jan 21, 2025 · 0 comments
Labels

Comments

@mrbumpy409
Copy link
Contributor

mrbumpy409 commented Jan 21, 2025

FluidSynth version

2.4.2

Details

Control of filter cutoff and resonance (Q) via NRPNs was introduced with the AWE32 and continued to be supported in all later Sound Blaster cards containing a hardware SoundFont synth, as far as I am aware. Recent versions of FluidSynth now support these NRPNs, but its behavior is not correct when compared to my Sound Blaster Audigy2 ZS, and likely not accurate to the original AWE32 either.

As for defining the "correct" behavior of these NRPNs, one must decide which of Creative's sound cards to model. I believe FluidSynth should model the behavior of the later, SoundFont 2.01–2.04 devices such as the Audigy for the following reasons:

  1. FluidSynth's SoundFont implementation is already based on the 2.01 and 2.04 spec, and the Audigy's NRPN implementation is aligned with the behavioral characteristics of this spec.
  2. I have a Sound Blaster Audigy2 ZS that can be used for testing and comparing the behavior with FluidSynth, but no access to an AWE32/64 or Live!.
  3. The Audigy's NRPN behavior can be recreated easily using modulators, so no need for lookup tables, etc. of the AWE32.

Test Results

I have created a filter NRPN test. It contains a recordings folder in which you can compare recordings of the test run on FluidSynth 2.4.2 and Audigy2 ZS. Through this, we can see several differences between the two synthesizers.

I will list each test from the accompanying README, along with my notes on the results of both FluidSynth and Audigy2 ZS. The tests are arranged into pairs, with the first of each pair testing NRPN behavior and the second emulating that behavior using a modulator.

Tests #⁠1 & #⁠2

Test #⁠1: If the AWE32 FC NRPN is implemented, you should hear a filter sweep from 100 to 8000 Hz and then back down to 100 Hz.
Test #⁠2: You will hear a filter sweep that emulates the AWE32 FC NRPN filter curve via CC1 modulator.

Here is a spectrogram view of tests #⁠1 (left) and #⁠2 (right) between Audigy2 (top) and FluidSynth (bottom):
Image

  • Audigy2 result: Both the NRPN sweep (left) and the emulated NRPN sweep via modulator (right) are identical.
  • FluidSynth result: The emulated NRPN sweep (right) is correct, but the actual NRPN sweep (left) is incorrect for two reasons:
    1. The filter Q specified in the test preset is being overridden to 0, though no filter Q NRPNs have been sent (see Use of AWE32 filter cutoff NRPN overrides both cutoff and emphasis #1452).
    2. It's hard to tell with the filter Q being overridden, but the NRPN to filter cutoff curve is the wrong shape.

Tests #⁠3 & #⁠4

Test #⁠3: You should hear a sustained white noise wave while the filter switches every two seconds through the following values: 0 (100 Hz), 13 (157 Hz), 25 (237 Hz), 38 (371 Hz), 51 (581 Hz), 64 (910 Hz), 76 (1377 Hz), 89 (2156 Hz), 102 (3376 Hz), 114 (5108 Hz), 127 (8000 Hz). Each jump in the filter should sound roughly like the interval of a fifth.
Test #⁠4: The same as the above test, but with the AWE32 FC NRPN filter curve emulated via CC1 modulator.

Here is a spectrogram view of tests #⁠3 (left) and #⁠4 (right) between Audigy2 (top) and FluidSynth (bottom):
Image

  • Results: The same scenario as tests #⁠1 and #⁠2 above.

Tests #⁠5 & #⁠6

Test #⁠5: You should hear a series of filter sweeps, each with progressively higher filter Q: 0 (0 dB), 13 (2.03 dB), 25 (3.91 dB), 38 (5.94 dB), 51 (7.97 dB), 64 (10 dB), 76 (11.88 dB), 89 (13.91 dB), 102 (15.94 dB), 114 (17.81 dB), 127 (19.84 dB)
Test #⁠6: The same as the above test, but with the AWE32 filter Q NRPN emulated via CC2 modulator.

Here is a spectrogram view of test #⁠5 between Audigy2 (top) and FluidSynth (bottom):
Image

  • Audigy2 result: You can see the filter Q amount increasing with each sweep.
  • FluidSynth result: FluidSynth does not appear to be responding to the filter Q NRPN messages. Each sweep instead appears to be using the 24 dB filter Q set in the preset, but the filter Q NRPN should be overriding that value.

Here is a spectrogram view of test #⁠6 between Audigy2 (top) and FluidSynth (bottom):
Image

  • Audigy2 result: The emulated filter Q NRPN via CC1 modulator perfectly matches the actual NRPN behavior from test #⁠5 above.
  • FluidSynth result: The emulated filter Q NRPN looks correct on FluidSynth. The keen-eyed might notice a bit of extra filter Q in the Audigy 2 examples at low frequencies, even when it should be at 0. This is one of the quirks of the Sound Blaster filter, but I don't believe that FluidSynth should be trying to emulate Creative's filter quirks (which also include being fully open at 8,000 Hz, limited to 100 Hz at low end, etc.).

Solution

As you can see from the tests results above, the Audigy's filter NRPN implementation can be easily emulated using modulators. This should provide a convenient mechanism for correcting the NRPN behavior in FluidSynth.

To emulate the Audigy's filter cutoff NRPN for a voice:

  1. Override the voice's filter cutoff, setting it to: 100 Hz
  2. Set the filter cutoff NRPN to modulate filter cutoff based on the following modulator:
    • Curve: unipolar linear positive
    • Amount: 7646 (timecents)
    • Destination: filter cutoff

To emulate the Audigy's filter Q NRPN for a voice:

  1. Override the voice's filter Q, setting it to: 0 dB
  2. Set the filter Q NRPN to modulate filter Q based on the following modulator:
    • Curve: unipolar linear positive
    • Amount: 200 (20 dB)
    • Destination: filter Q

In addition to getting the curves right, the filter cutoff and filter Q NRPNs should act independently. Activating the filter cutoff NRPN should have no affect on filter Q, and vice versa, but currently FluidSynth (A) overrides filter Q whenever the filter cutoff NRPN is used, and (B) doesn't respond to the filter Q NRPN independently of the filter cutoff NRPN—at least in these tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant