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

AWE32 NRPN Compatibility Layer #1342

Closed
derselbst opened this issue Jun 26, 2024 · 9 comments · Fixed by #1346
Closed

AWE32 NRPN Compatibility Layer #1342

derselbst opened this issue Jun 26, 2024 · 9 comments · Fixed by #1346
Milestone

Comments

@derselbst
Copy link
Member

derselbst commented Jun 26, 2024

Related discussion

As discussed in #1290, a compatibility layer for supporting AWE32-style NRPNs shall be attempted.

Is your feature request related to a problem?

Mimic the behavior of AWE32 Midis in fluidsynth.

Describe the solution you'd like

Fluidsynth being able to understand AWE32 NRPNs and produce similar output.

Describe alternatives you've considered

There are projects that emulate the Emu8000 chip that should be used for more accurate reproduction, found e.g. here.

Additional context

Implementation details of AWE32 NRPNs:

Example MIDIs: https://ftp.lysator.liu.se/pub/awe32/songs/

Example MIDI Renderings on the AWE32 SB Live! using GeneralUser GS v1.471:

NRPN MIDIs Github.7z.001.zip
NRPN MIDIs Github.7z.002.zip
NRPN MIDIs Github.7z.003.zip

(The .zip extension is for Github to accept these files - remove it - it's a multi-part 7z archive)

@klerg
Copy link

klerg commented Jun 27, 2024

Nice to see this and I know it is confirmed as an issue that will be resolved at some point. One thing to note, the example renderings were on a SB Live! and not an AWE32.

@derselbst
Copy link
Member Author

Actually, this was quite interesting. Here is what I have so far

awe32-nrpn_.zip

There are a few implementation details that I'm not sure about:

1. Where and when to apply the AWE32 NRPNs?

In SF2 the effect of NRPN is additive to a generator. For the AWE32, the NRPN seems to override the value of a generator, i.e. it's absolute. For now, I have decided to apply the AWE32 NRPN in fluid_defpreset_noteon() after all generators have been populated by instrument AND preset zones. In that sense, the NRPN may override generators that have been modified on preset level. This behavior appears correct to me and also sounds quite ok.

This can be audibly observed: "The Nervous Filter.mid" uses AWE32 NRPN to disable reverb. But it doesn't do that right at the beginning. Hence, the first 2 seconds or so there is reverb, then it's cancelled. But again, this way proves IMO that AWE32 NRPN is indeed intended to overrule any influence from a preset zone. Because applying NRPN before preset zones would first cancel the reverb generator as dictated by AWE32 NRPN, and then increment the reverb generator via preset zone, which however doesn't seem correct.

2. Filter Resonance

The filter of the AWE32 / EMU8000 chip seems to be much more resonant than fluidsynth's filter. I'm afraid there's no way to fix this. Fluidsynth's filter is implemented according to SF2 spec, and it's not our goal to mimick or emulate the EMU8000 filter.

3. Filter Q

The AWE32 dev docs specify a resonance table with a high and low Q. I'm not entirely sure what's meant by that, but it seems to suggest a varying-Q filter design. Indeed, when listening to ALTITUDE.MID rendered on the SB Live one can hear that the filter becomes much more resonant the lower the cutoff frequency (fc) gets. This suggests that if the fc is lowest, low Q should be used. At highest fc, high Q should be used. But what to use for fc in between? I have implemented a linear interpolation for now. Could be changed to logarithmic interpolation.

4. "* To filter cutoff"-NPRNs

I have disabled what AWE32 calls "NRPN LSB 23 (LFO1 to Filter Cutoff)" and "NRPN LSB 24 (Envelope 1 to Filter Cutoff)". When reading the title it suggests that it's compatible to GEN_MODLFOTOFILTERFC and GEN_MODENVTOFILTERFC in the SF2 world, which both modulate the cutoff frequency of the filter. But when reading the description it says we should modulate the filter's "phase" instead. The description also suggests a fixed amount of modulation, hence the value of that generator is only evaluated for its signedness, but not for it's value. That's strange. When I map these two NRPNs onto the SF2 generators, "The Nervous Filter" starts with a very high cutoff frequency, such that the effect of the filter cannot be heard after a few seconds of playtime. This doesn't sound correct to me. And since fluidsynth doesn't support to modulate the "phase" of the filter and I don't know how to implement it, I have disabled these two NRPNs.

@derselbst derselbst linked a pull request Jun 29, 2024 that will close this issue
@derselbst derselbst added this to the 2.4 milestone Jun 29, 2024
@derselbst
Copy link
Member Author

@mrbumpy409 FYI

@klerg
Copy link

klerg commented Jun 29, 2024

Yes, very nice to see you have something already here

I hope none of this is major and maybe can help out in some way.

  1. This is a very good thing to ask and to try and find out

Ok I take it by this you mean it adds something to a generator. And that is going to mean it replaces the value a generator has then. Well, I bet that is the right place to put the AWE32 NRPN. Or if the AWE32 NRPN came before then the instrument and preset zone will override that and not work at all. Yes, if the NRPN goes over the generators in the instrument and preset zones, then it can be heard. Sure that seems to be the right way and sounds like it too.

I could barely tell that the "The Nervous Filter.mid" uses AWE32 NRPN to turn off reverb. But it is there. And just like you said it is not at start of that but comes later on. I'm totally with you on this that AWE32 NRPN is meant to take over or replace any settings that are in the instrument or preset zones. True, if the reverb NRPN is put in prior to any of the zones than it will get rid of the AWE32 NRPN, and instead edit the reverb in one of the zones, amd that does not make sense at all.

I see and hope this will not be that big of a deal at the end of the day. Sure that is fine no worries here. Yes, and the filter on SB Live! and Audigy/2 is based on SF2, and tries to match the EMU8000.

I did see this resonance table in the AWE32 dev docs as well, but cannot make anything out of it. Sure, it has to say something on how the filter works. That Altitude.mid has the most clipping of all the ten AWE32 MIDI's. Yes that is what gives this MIDI its signature sound, it gets more resonant as the cutoff frequency is lowered. I can tell how at lowest fc, it needs a low Q, and highest fc, it needs a high Q. That is a good thing to ask for sure. Well, Altitude.mid sounds the least closest to SB Live! so maybe a logarithmic interpolation then.

4

I do see both of these NRPNs as the last two that are mentioned in the list of supported NRPNs in the FAQ and AWE32 dev docs. Yes, based on that name GEN_MODLFOTOFILTERFC and GEN_MODENVTOFILTERFC seem to match NRPN 23 and 24. And they must modulate cutoff frequency of the filter. True, and I have no clue what "phase" even means in this case. Well, if the amount of modulation is fixed that makes sense, but I have no idea what "signedness" means and hope someone can help out here. Yes even stranger to me. This is where things start to sound off if the cutoff frequency is too high than it will be like nothing is going on with the filter for a short time at least. Yes that will not sound right. Well, I wonder if the SB Live! or Audigy/2 can modulate "phase" of a filter too. I really hope someone can help you out with this or it may prove to hinder the compatibility a bit then . By the way, I listened to the samples, and are you using GeneralUser GS v1.471 if so how come The Nervous Filter.mid has a square and not saw wave sound ?

@mrbumpy409
Copy link

I noticed that those NRPN MIDI files aren't being rendered using their included SoundFonts. I was able to convert Altitude.sbk to SF2 and replace the ROM samples with RAM copies. Here is Altitude with both versions of the SoundFont as well as a recording of the song played on my Sound Blaster Audigy2 ZS with Altitude.sf2 loaded to bank 1:
Altitude-converted.zip

I can try and convert the whole archive, if you guys would find it helpful.

Regarding point #2 above, I agree that FluidSynth shouldn't be trying to emulate the quirks of the EMU8000 filter.

@mrbumpy409
Copy link

BTW, I couldn't find any way to load Altitude.sf2 to bank 1 using FluidSynth command line. Does anybody know if this is possible? I was able to do it using QSynth, but then it was impossible to access the bank 1 drum kit on channel 10. It shows as available on bank 129 in QSynth, but it cannot be selected, either in the GUI or via the MIDI file's controllers.

@klerg
Copy link

klerg commented Oct 26, 2024

Yes that is a great point that you brought up and not sure why this is the case and
something we can fix. Appreciate it, and does take some time to replace the ROM samples with the RAM ones for sure. Nice that you put both Altitude versions of the soundfont also even when the .sbk file cannot be opened almost anywhere and it sounds very nice on the Audigy 2 ZS as well

Sure, that will be very helpful if you can convert the whole archive

For the most part, I also agree with point #2, that Fluidsynth does not need to mimic every aspect of the EMU8000 filter as most of it is unknown.

I have no clue how to load any soundfont into bank 1 using the Fluidsynth command line, and not surprised you were able to pull this off using Qsynth, as that has a nice GUI to make sense of things. I'm having an issue where after I load bank 1 in AudioHQ on Windows XP, it some how gets erased when loading Cakewalk, and will look into this and see if someone knows of a solution but it seems Cakewalk is behind this problem

@derselbst
Copy link
Member Author

@mrbumpy409 Thanks for the conversion! I don't think additional ones are required. I'll merge the PR soon.
Loading it into bank 1 should be possible with the bankoffset of the load command from fluidsynth's shell:

load file [reset] [bankofs] Loads SoundFont (reset=0|1, def 1; bankofs=n, def 0)

BTW, if you're in the mood, you may have a look into why the IIR filter is producing clicks: #1415


@klerg The "noises" that you kept complaining about to me privately are most likely caused by #1405 and #1415 and will be addressed separately.

@klerg
Copy link

klerg commented Nov 1, 2024

Yes nice to hear the SFX too! Well, most of the MIDIs sound much better with the included soundfonts. I see it looks like that is done then.

I'm bit lost on this command to load in bank 1, do we need to type out everything in the brackets and parentheses as well ?

I'm looking at this topic and most of it does not make sense to me, I hope comment on it soon when I get it.

Well, I would not call that complaining but more like pointing out the issue but I did not expect #1405 to have much to do with this problem of clicks and cracks.

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

Successfully merging a pull request may close this issue.

3 participants