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

Bank select seems to be ignored #1378

Open
spessasus opened this issue Sep 9, 2024 · 16 comments
Open

Bank select seems to be ignored #1378

spessasus opened this issue Sep 9, 2024 · 16 comments
Labels

Comments

@spessasus
Copy link
Contributor

spessasus commented Sep 9, 2024

FluidSynth version

Execute fluidsynth --version and provide the output.

FluidSynth runtime version 2.3.6
Copyright (C) 2000-2024 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of Creative Technology Ltd.

Describe the bug

Provide a clear and concise description of the current situation, e.g. how the bug manifests.
Fluidsynth does not use the correct patches. In the provided example, channel 3 should use patch 001:000 "Fluid Grand Piano" but it uses path 000:000 "Concert Grand".

The MIDI system is XG so the bank select shouldn't be ignored.

Here's the event viewer:
image
But it uses bank 0.

Expected behavior

Provide a clear and concise description of what you expected to happen.

  • channel 3 should use patch "Fluid Grand Piano",
  • channel 11 should use patch "Pulse 25%" instead of "Square Wave"
  • channel 13 should use patch "Roland Saw Lead" instead of "Saw Wave"

Steps to reproduce

Please explain the steps required to duplicate the issue, esp. if you are able to provide a sample application. E.g. how to start fluidsynth, what shell commands to enter, what midi events to send, etc.

Archive.zip

fluidsynth GMGS_ISSUE.sf3 -o synth.gain=1 -o synth.device-id=16 Ancient\ Temple\ from\ 東方萃夢想.mid

Compare the results to falcosoft MIDI player or spessasynth.

Additional context

None

@spessasus spessasus added the bug label Sep 9, 2024
@spessasus spessasus changed the title Bank select should not change the patch Bank select seems to be ignored Sep 9, 2024
@spessasus
Copy link
Contributor Author

One more thing: without synth.device-id=16 the bank selection works fine. Since GS bank select is the default and the MIDI uses XG on, it seems like XG mode ignores bank for some reason????

@derselbst
Copy link
Member

Yes. The MSB Bank event is indeed ignored on this code path:

chan->channel_type = (120 == bankmsb || 126 == bankmsb || 127 == bankmsb) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;

This is on purpose. In XG Mode, Bank MSB is only used to decide whether it's a melodic or drum channel. This behavior seems to exist since @pedrolcl's commit 14 years ago: 713021b5a3dedc0d29c9a267f1eb8cc9a3359a14

This behavior is correctly documented here: https://www.fluidsynth.org/api/fluidsettings.xml#synth.midi-bank-select

But, after digging through the XG Spec (section "3.1.6.1. Bank Select MSB / LSB") I am not so sure anymore that fluidsynth's behavior is correct here. By setting BankMSB=1 you pick the "Model-exclusive area". Note 4 says:

If a Bank Select MSB value of 01H–77H or 7AH–7EH (model-exclusive area, SFX voice, or
XG extension voice) is received and the tone generator does not have a voice corresponding to
the last received LSB and Program Change, the tone generator shall produce no sound [...]

Applying that to fluidsynth: Fluidsynth does indeed have a valid program on 001:000, hence it should produce that sound.

This might also be what @hikari-no-yume was pointing to in this comment.

I'd welcome a few thoughts on what's the correct behavior here.


PS: By omitting synth.device-id=16 you prevent fluidsynth from successfully processing the XG SysEx reset message, and therefore fluidsynth will stay in GS mode.

@spessasus
Copy link
Contributor Author

spessasus commented Sep 17, 2024

I'd welcome a few thoughts on what's the correct behavior here.

Well, there isn't one.

Soundfont doesn't have bank LSB, making it pretty much incompatible with XG from the ground up.

However, in my opinion, this behavior should be changed to accept bank MSB regularly. (Or LSB for that matter) because currently, an XG MIDI can only use the GM sound set. So even playing it with an XG soundfont (which obviously has to use the wBank field for variations) results in all the additional presets being unused.

So here's my proposed new behavior:
On bank select MSB:
If the value is one of the drum toggles, set the channel to drums and bank to 128 (since sfont drums are bank 128)
Otherwise set to melodic and apply bank normally. No idea if this is correct with the XG spec at all, but that behavior fixes the provided MIDI and BASS also uses it.

@hikari-no-yume
Copy link

Sorry if I'm missing something, but isn't that proposed new behaviour more or less what FluidSynth already does?

@spessasus
Copy link
Contributor Author

Sorry if I'm missing something, but isn't that proposed new behaviour more or less what FluidSynth already does?

As stated by derselbst, fluid currently ignores bank MSB in XG mode. My proposed behavior is for it to mimic the GS bank select, except for the drum toggle numbers (like 127)

@hikari-no-yume
Copy link

That doesn't seem appropriate to me, because no real XG implementation does that (that I'm aware of), and XG uses LSB for extension instruments, not MSB like GS.

@spessasus
Copy link
Contributor Author

spessasus commented Sep 17, 2024

That doesn't seem appropriate to me, because no real XG implementation does that (that I'm aware of), and XG uses LSB for extension instruments, not MSB like GS.

There are two:

  • Falcosoft MidiPlayer which uses BASSMIDI for playback. Playing the provided MIDI there results in patch 001:000 Fluid Grand Piano being used instead of 000:000 Concert Grand
  • SpessaSynth which I created. I copied the behavior from BASSMIDI, so it also uses bank select.

Edit: there's a possibility that FSMP6 uses it's own bank select implementation rather than relying on BASSMIDI, but I can't test that since BM is a library, not a standalone app.

@hikari-no-yume
Copy link

Those examples are both third-party softsynths though. I'm pretty sure Yamaha's own XG implementations don't do this, and they are what XG MIDIs are written for. If you don't have a hardware device, Yamaha's S-YX50 is easy to obtain and is a full XG softsynth.

To put this in context: XG devices can have extra banks accessible with the MSB, but I think those are quite rarely used by comparison to the LSB, especially because they're all GM2, model-specific or expansion card-specific. If you look at XG MIDIs in the wild, I would wager that the overwhelming majority use the MSB only for selecting between drums/sfx and melodic instruments, and the LSB is used for selecting everything else. If you set MSB=1 on a real XG device, I think you'd just get no sound at all in most cases.

@hikari-no-yume
Copy link

hikari-no-yume commented Sep 17, 2024

Actually, I tested on a low-spec XG device I have, and it just ignored MSB = 1 (same sound as MSB = 0). I guess that matches the fallback behaviour derselbst quoted above.

@spessasus
Copy link
Contributor Author

Those examples are both third-party softsynths though. I'm pretty sure Yamaha's own XG implementations don't do this, and they are what XG MIDIs are written for. If you don't have a hardware device, Yamaha's S-YX50 is easy to obtain and is a full XG softsynth.

To put this in context: XG devices can have extra banks accessible with the MSB, but I think those are quite rarely used by comparison to the LSB, especially because they're all GM2, model-specific or expansion card-specific. If you look at XG MIDIs in the wild, I would wager that the overwhelming majority use the MSB only for selecting between drums/sfx and melodic instruments, and the LSB is used for selecting everything else. If you set MSB=1 on a real XG device, I think you'd just get no sound at all in most cases.

Well, I was quoting the XG supported sf2 synths' behavior. SF2 does not have LSB, so we can't ever replicate the actual XG behavior. (Unless #1234 will get added to all major sf2 synths and editors, which would be amazing but I don't think It'll happen any time soon).

So it's up to the debate whether we want to ignore MSB or not. My proposed solution is like this:

  • Bank select MSB received. If 120, 126 or 127, set to drum bank. Otherwise set channel's bank num to the value.
  • Bank select LSB received. Set channel's bank num to the value, overwriting the MSB value if set.

This way we get both: MSB and LSB support with what we have (only MSB in the soundfont).

But maybe I'm wrong and the MIDI i've provided is incorrect...

@hikari-no-yume
Copy link

Well, your proposed behaviour for the MSB would improve compatibility with MIDI files that claim to be for XG but are relying on strange behaviours of unofficial softsynths, but worsen compatibility with MIDI files that are actually written for XG. That seems straightforwardly bad to me because the latter type must be far more common, and the former type are probably created by mistake.

@spessasus
Copy link
Contributor Author

Well, your proposed behaviour for the MSB would improve compatibility with MIDI files that claim to be for XG but are relying on strange behaviours of unofficial softsynths, but worsen compatibility with MIDI files that are actually written for XG. That seems straightforwardly bad to me because the latter type must be far more common, and the former type are probably created by mistake.

Sorry if I missed something, but how would that hurt the actual XG MIDIs? According to your comment derselbst linked earlier, the MSB is used for some sort of "groups" of programs, like "XG Normal" "XG PCM" or "GM2 Sound"

So let's imagine an XG MIDI:

  1. Bank select MSB. It sets it to 8 ("XG PCM"). My solution then changes bankNum to 8
  2. Bank select LSB. It sets the variation to 1. My solution then overrides bankNum with the said 1.
  3. The used bank (variation) is 1, like the MIDI intended.

The only other solution (actually the perfect one) I can think of is the beforementioned #1234 (btw, @derselbst would you be willing to implement that? It would close all the XG behavior debates and allow 1:1 behavior!)

Did I miss something? If so, let me know!

@hikari-no-yume
Copy link

If it didn't set the variation, it would end up on the wrong sound. That's the issue.

@hikari-no-yume
Copy link

I'm assuming here, by the way, that the lack of LSB support in SF2 means an “XG-compatible” SF2 would use the MSB both for drums and for non-GM instruments, and then expects the synth to map LSB -> MSB for non-drum parts. That's the only way to get anything approximating XG compatibility without having support for both LSB and MSB in the SF2 format. But I don't actually know if real-world soundfonts do this.

@hikari-no-yume
Copy link

Oh, the other issue is that your solution is order-dependent. I don't think you can assume MSB and LSB always come in a certain order, or that both are always present.

@pedrolcl
Copy link
Contributor

This is on purpose. In XG Mode, Bank MSB is only used to decide whether it's a melodic or drum channel. This behavior seems to exist since @pedrolcl's commit 14 years ago

To be frank: I had very little idea about XG then, and after all these years I know exactly the same. I've never had a Yamaha device and my interest for it is zero, as always. Someone else provided the algorithm.

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

4 participants