fluidsynth icon indicating copy to clipboard operation
fluidsynth copied to clipboard

Add autoconnect to winmidi driver

Open jjceresa opened this issue 2 years ago • 14 comments

This PR is an alternative to commit d031d4b of PR https://github.com/FluidSynth/fluidsynth/pull/1023

When midi.autoconnect is set to true it works as commit d031d4b of PR https://github.com/FluidSynth/fluidsynth/pull/1023. When midi.autoconnect is false it works as actual.

jjceresa avatar Jan 15 '22 15:01 jjceresa

I have to admit it's hard for me to comprehend your different views / use-cases and understand the differences. Which makes it hard to make a decission here. AFAIU, your change keeps backward compatibility with your original use-case?

It would make things easier if @pedrolcl could comment on this proposal as well.

Well, I've explained in https://github.com/FluidSynth/fluidsynth/issues/414#issuecomment-1011215646 why I think that "The synth.midi-channels winmidi independence of #677 was an important design choice." creates a nasty bug. For instance: https://lists.nongnu.org/archive/html/fluid-dev/2021-11/msg00000.html . I am not sure if @es20490446e is using Windows or something else, but his problem is exactly the bug in winmidi that I tried to fix in #1023, no matter if autoconnect is enabled or not.

In this comment https://github.com/FluidSynth/fluidsynth/issues/414#issuecomment-1011523369 the argumentation is that MIDI channels collision is also a bug, but in my view it is a problem of the MIDI protocol, which has been affecting every MIDI installation for the last 30 years if the users don't understand MIDI 1.0 and its limitations. The solution proposed for the winmidi bug, that users should use the midi router of the command line fluidsynth program to map the incoming event channels by hand, is preposterous, when there is a much more easy, universal and sensible solution for the user: to increase the value for the setting 'synth.midi-channels', which every MIDI driver should respect, whether autoconnect is enabled or disabled.

pedrolcl avatar Jan 16 '22 15:01 pedrolcl

I'm on Linux.

es20490446e avatar Jan 16 '22 15:01 es20490446e

I'm on Linux.

Then, please open a new issue at https://github.com/FluidSynth/fluidsynth/issues with details. Thanks!

pedrolcl avatar Jan 16 '22 15:01 pedrolcl

Well, I've explained in #414 (comment) why I think that "The synth.midi-channels winmidi independence of #677 was an important design choice." creates a nasty bug

You have explained, that some channels will be ignored by the synth, yes. Might be not nice, but I wouldn't call it nasty bug either, as it can be fixed by simply increasing synth.midi-channels.

I also understand JJC's point of view, that a hardcoded modulo operation of the channel_map is a bad idea.

From what I see, the ALSA driver limits it's destination ports, but it doesn't do a modulo operation either.

For instance: https://lists.nongnu.org/archive/html/fluid-dev/2021-11/msg00000.html .

There already was an issue #999. It's related to Systemd, not MIDI.

My proposal to handle the "insufficient number of midi channels" situation would be to either print a warning, or fail with an error during driver creation.

derselbst avatar Jan 16 '22 15:01 derselbst

You have explained, that some channels will be ignored by the synth, yes. Might be not nice, but I wouldn't call it nasty bug either, as it can be fixed by simply increasing synth.midi-channels.

The user will only observe that fluidsynth is ignoring the events received from some MIDI controllers, and he won't know what to do about it. Your proposal is to return a warning message, or fail to start the driver. Well, that's better. Somewhat rude, though.

Let's summarize the problem with an example, including a simple (but common) use case.

The user runs Windows + FS with the default settings. He connects his USB MIDI keyboard, which uses the output MIDI channel 1 to the computer, and changes the setting midi.winmidi.device to match his device id. He plays the piano keys and FS produces sound. Now, his friend brings another USB MIDI keyboard, adjusting the output MIDI channel to 2, and connects it to the same computer. The user changes the setting midi.winmidi.device again to be "0;1" (assuming that this is the correct setting value) restarting the synth. Now, playing both MIDI controllers at once only the first one produces sound. And there is nothing explaining why. The channel mappings applied by winmidi are not exposed at all, neither are evident or expected. Why should the user know that increasing the number of MIDI channels of the synth to 32 solves his problem?

Because the typical use case is that each MIDI controller sends events on one MIDI channel only. Using the default value of "synth.midi-channels" is enough for 16 MIDI controllers playing together with the same FS instance, using each one a different MIDI program. There is no need for channel mappings in this use case. Only basic knowledge of the MIDI standards.

pedrolcl avatar Jan 16 '22 16:01 pedrolcl

Why should the user know that increasing the number of MIDI channels of the synth to 32 solves his problem?

Ok, I get your point. This makes me think that we should do the channel modulo wrapping as Pedro suggested. And I would also tend to say that a possible risk of "MIDI channels collision" is an inherent problem of the MIDI standard, or better of the two friends playing with two instruments on the same MIDI channel.

derselbst avatar Jan 16 '22 17:01 derselbst

AFAIU, your change keeps backward compatibility with your original use-case?

Right. The original use case is to have a driver behaviour that makes a straightforward aggregation of the MIDI in devices on predictible separate MIDI channels to ensure no MIDI channels conflicts. I will explain why in next comments.

Of course having an "autoconnect" behaviour for the reason explained by Pedro is nice. Obviously, "autoconnect" needs to take account of synth.midi-channels and magically map any devices MIDI channel confined to synth.midi-channels.

I don't like this to be initialized to magic 16.

Oh yes. That will be fixed

jjceresa avatar Jan 16 '22 21:01 jjceresa

You leave a comment in the source code, but this won't help the users.

The comments are for developers not for end-users.

Then the user plays both controllers in the same MIDI channel. This may produce event collisions, of course, because that is how MIDI works. Each MIDI controller should use a different MIDI channel.

In a perfect world each MIDI controller should use a different MIDI channel but there case were this is not true. Please see my comment below.

jjceresa avatar Jan 17 '22 04:01 jjceresa

One of my friend user is using multiples MIDI controllers (2 keyboards), and several custom MIDI cc controllers). One constraint is that the custom MIDI cc transmit all on the same MIDI channel (and this cannot be changed). At the output he is often using 2 synths (1 fluid synth + hardware synth).

To map any MIDI input controllers (Keyboard layers+ CCs) to any synths (fluid synth or/and hardware synths) this user prefers to use a central matrix (MIDI channel mapping/key split/ and routing) situated between the MIDI driver and the synths. With the help of the fluidsynth library architecture it is possible to have a MIDI driver connected to a custom application and the output of this application connected to fluid synth + other synths. The application allows a direct and fast access to the central matrix which is opaque to the human user through a user interface. Also the user never need to enter in MIDI controllers menu to change the MIDI channels setup.

In this case that means that the MIDI driver behaviour must be constant and predicitible. The MIDI driver should not do a magic device channel mapping merging dependent of synth.midi-channels. This is the reason of the actual winmidi driver behaviour.

jjceresa avatar Jan 17 '22 04:01 jjceresa

I have added a "midi.winmidi.mergebox" setting toggle setting. With this setting set to 1 (the default) the driver behaves like d031d4b of PR #1023. With this setting set to 0 the driver behaves like actual.

jjceresa avatar Jan 17 '22 04:01 jjceresa

One of my friend user is using multiples MIDI controllers (2 keyboards), and several custom MIDI cc controllers). One constraint is that the custom MIDI cc transmit all on the same MIDI channel (and this cannot be changed). At the output he is often using 2 synths (1 fluid synth + hardware synth).

To map any MIDI input controllers (Keyboard layers+ CCs) to any synths (fluid synth or/and hardware synths) this user prefers to use a central matrix (MIDI channel mapping/key split/ and routing) situated between the MIDI driver and the synths. With the help of the fluidsynth library architecture it is possible to have a MIDI driver connected to a custom application and the output of this application connected to fluid synth + other synths. The application allows a direct and fast access to the central matrix which is opaque to the human user through a user interface. Also the user never need to enter in MIDI controllers menu to change the MIDI channels setup.

In this case that means that the MIDI driver behaviour must be constant and predicitible. The MIDI driver should not do a magic device channel mapping merging dependent of synth.midi-channels. This is the reason of the actual winmidi driver behaviour.

For the particular case of a custom application used only by your friend, you can provide him with a custom FS library, fine tuned as you see fit. Instead, you are forcing everyone to follow your particular policy. That is unfair. I am talking here as the packager of Qsynth for Windows, not only as a FS user.

pedrolcl avatar Jan 17 '22 12:01 pedrolcl

I have added a "midi.winmidi.mergebox" setting toggle setting. With this setting set to 1 (the default) the driver behaves like d031d4b of PR #1023. With this setting set to 0 the driver behaves like actual.

So, you think that it is fine to add and obey a new user setting in the winmidi driver, but you insist on ignoring in some cases the setting "synth.midi-channels"?

Why not change "synth.midi-channels" to the maximum value of 256 channels in your friend's custom application instead, and always fulfill this setting?

pedrolcl avatar Jan 17 '22 12:01 pedrolcl

I would do the least surprising thing for the most general case. While not enforcing any particular policy, but making the most common the default.

es20490446e avatar Jan 17 '22 14:01 es20490446e

you are forcing everyone to follow your particular policy....That is unfair. I am talking here as the packager of Qsynth for Windows. So, you think that it is fine to add and obey a new user setting in the winmidi driver...

With the help of midi.winmidi.mergebox setting everyone aren't forced to follow my particular policy. The default value of this setting is 1 and in this case the driver behave as a merging box that is the policy of PR #1023 who is making a silent magic MIDI channel mapping (for ALSA seq also if understood well).

Note that the MIDI driver merging box policy nature makes the use of fluid router or custom router impossible because the MIDI channel mapping at the router input isn't easily predictable.

With the midi.winmidi.mergebox setting presence it is now more clear how the driver behaves.

Why not change "synth.midi-channels" to the maximum value of 256 channels in your friend's custom application instead, and always fulfill this setting?

This excessive and sensible solution is a workaround, because if "synth.midi-channels" is accidentally changed for any reason than MIDI channel mapping at the MIDI driver output becomes unpredictable again. The MIDI driver output is connected to MIDI input of this custom application. So the important point is to keep all the MIDI in configuration routing independent of the synths MIDI channels capabilities. This user use a fluid synth + others synth.

Please, as the packager of Qsynth for Windows why midi.winmidi.mergebox setting presence is a problem ?

jjceresa avatar Jan 17 '22 14:01 jjceresa

Superseded by #1023

derselbst avatar Sep 11 '22 15:09 derselbst