FluidSynth / fluidsynth

Software synthesizer based on the SoundFont 2 specifications
https://www.fluidsynth.org
GNU Lesser General Public License v2.1
1.87k stars 261 forks source link

[Feature Request] Add Bank Select LSB Support via other byte of wBank #1234

Open stgiga opened 1 year ago

stgiga commented 1 year ago

Related discussion

Here is a link to the thread.

https://github.com/FluidSynth/fluidsynth/discussions/1218

Is your feature request related to a problem?

As it stands, proper Yamaha XG (among other synthesizer maps, and DLS conversions) is not supported in FluidSynth due to a lack of Bank Select LSB (CC32), but since the wBank value used to store banks is 16-bit, it means that via the other byte, Bank Select LSB and Yamaha XG (as well as other maps and DLS files) support can work.

Describe the solution you'd like

I want FluidSynth (among other SF2-related software who I am also in contact with) to use the unused byte of wBank to store CC32 Bank Select LSB in order to properly support Yamaha XG, DLS conversions, and other synthesizer maps.

Additional context

So, according to the SoundFont standard, the value (known as wBank) normally used to store Controller Change 0 (Bank Select MSB) is actually a 16-bit value. If we use the OTHER byte to store the Controller Change 32 (Bank Select LSB) value, we can support Bank Se]ect LSB in SF2, thus proper Yamaha XG SoundFonts, and proper DLS-to-SF2 conversions can be made, among other synthesizer maps. The spec says to preserve (but not play) these values should the other byte than MSB be used. Also, the second percussion toggle is a bit that OpenMPT 1.30 will respond to as a percussion toggle. I have a test-of-LSB SF2 here: https://drive.google.com/file/d/1JuhW46fbt3y8kD7UqeIFwmMb_Mg3R2-L/view?usp=sharing as well as an attached diagram of the bits for wBank with LSB support. There have been some reworks to this.

The test SF2 was made by my collaborator via hex editing the wBank values in some XG-mapped patches to put them on their LSBs (Yamaha XG uses Bank Select LSB for its patch variations outside General MIDI rather than Bank Select MSB as is done in Roland GS) as is proper, while following the attached bit diagram of wBank.

LSB_on_SoundFont

This whole proposal has been in the works for months.

I know that it might seem a bit wild to do this, but having Bank Select LSB also opens the doors to more SoundFonts of other synthesizers, because a no-LSB beyond-GM synth outside Roland SoundCanvas lines in native mode is extremely rare.

Furthermore, I have pitched the proposal to other people in the SoundFont player and editor community, such as Polyphone on Github, and also on Un4seen. The gist of this proposal is that wBank LSB use is what we find to be of current most importance, but we have additional plans for later.

Here's something that is important to note:

For this to work right, SF2s doing 16-bit wBank must have the lsb=0 patches first.

To elaborate:

As mentioned in the SF 2.04 specification, if the wPreset and wBank are identical, the player should play the first preset found in the PHDR.

The legacy AWE player will read the low byte of the wBank (as MSB), but will ignore the high byte.

Therefore, if you have multiple presets with the same low byte of wBank (MSB value), you need to put the preset which you want to fall back to first. This may be LSB=0, LSB=3 (for stereo XG sounds), or any arbitrary LSB value.

This is the internal order, and not the displayed order. The displayed order depends on which program you opened the SF2 file in anyway. It could be alphabetical, internal or something else entirely.

Therefore, editors should allow the selection of the preferred fallback preset, and also respect the internal order of presets in the file.

hikari-no-yume commented 1 month ago

If this is implemented, it would be wise to have the SF2 explicitly opt into this via some flag. Otherwise, existing SF2 that rely on LSB->MSB mapping (if this is a thing) might break?

spessasus commented 1 month ago

If this is implemented, it would be wise to have the SF2 explicitly opt into this via some flag. Otherwise, existing SF2 that rely on LSB->MSB mapping (if this is a thing) might break?

@hikari-no-yume, how about we use the dwLibrary field? For example if the dwLibrary is equal to exactly 1, then this behavior is enabled

stgiga commented 1 month ago

If this is implemented, it would be wise to have the SF2 explicitly opt into this via some flag. Otherwise, existing SF2 that rely on LSB->MSB mapping (if this is a thing) might break?

I don't think it's done, and the only way I found out about 16bit wBank was opening Yamaha XG DLS files in certain editors, and then years later I remembered it and read the standard. This is very rare.

16bit wBank files will work on hardware SF2 SB cards by sending the full word as a bank select value. At least the word status is respected. Just know that the tagging bits aren't strictly necessary because we're directly cloning the method of the only soundbanks that did this.

The SFe spec leaves one of the unused sections open so I recommend you read it.

I'm on mobile right now and sick so sorry for the response delay.

stgiga commented 1 month ago

If this is implemented, it would be wise to have the SF2 explicitly opt into this via some flag. Otherwise, existing SF2 that rely on LSB->MSB mapping (if this is a thing) might break?

@hikari-no-yume, how about we use the dwLibrary field? For example if the dwLibrary is equal to exactly 1, then this behavior is enabled

https://github.com/SFe-Team-was-taken/SFe/blob/main/format-specification/section7.md

We've already proposed using it. Spessasus's ideas are interesting, and we should try to factor them in. OH and SFe64 lifts many limits in SF2 and SFe32 by the way.