MIDI control change input isn't mapped in a useful way to controls that have a very wide range of values
Environment/Versions
- GIMP version: 2.10.36
- Package: installed from Manjaro Linux packages
- Operating System: Manjaro Linux
Description of the bug
Context
(skip this section if you know MIDI)
Gimp has support for MIDI input controllers, and the user can set any Note event (Note on, Note off) and any CC event (Control Change) to any Gimp action. That's great!
The MIDI protocol is quite simple to understand. There are two main kinds of events that a MIDI controller (such as MIDI keyboards) can generate: Note events, and CC events. Whenever a piano-like key is pressed, a Note On event is generated (with an associated "velocity", i.e. how hard the musician pressed the key). When the key is released, a Note Off event is generated (also with a "velocity", although support of velocity on Note Off is extremely rare). Additionally, MIDI controllers can have knobs or sliders, which are usually implemented as potentiometers in hardware. Whenever the user interacts with a knob or slider, the new value of the potentiomenter is sent as a Controller Change event.
These three kinds of events (Note On, Note Off, Control Change), are sent as a 3-byte message. The first byte defines the kind of the event, and the channel (there are 16 channels, from 0 to 15). The second byte defines which note was pressed, or which control was changed. The third value defines the note velocity, or the new control value. The second and third bytes are actually limited to 7 bits, i.e. the range is limited from 0 to 127.
In summary: there are 128 possible notes, which can be on or off with 128 possible velocities; and there are 128 controls that can have 128 possible values.
The bug
When mapping a MIDI input to a Gimp control that has a very wide range, the mapping is done in a very… huh… unhelpful way.
Specifically, mapping a CC event to tools-size-set
tries to linearly map 128 values to a range of 10000 brush sizes. This means we have a brush size granularity of about 70. In other words, when changing the MIDI control, we jump from size 1 to size 71 to size 151, and that happens by barely touching the MIDI knob. Setting the control to half-way leads to a gigantic brush size of 5000.
This bug does not affect all of the GIMP controls. For instance, tools-opacity-set
has range of 100%, which is mapped nicely to the MIDI CC range of 128 values.
As a quick test, here's a list of a few GIMP controls:
- tools-size: range from 1 to 10000, unusable.
- tools-spacing: range from 1 to 5000, unusable.
- tools-aspect: range from -20 to +20, works fine, but we can't reach the exact 0.0 value.
- tools-angle: range from -180 to +180, works fine, but we can't reach the exact 0.0 angle.
- tools-opacity: range from 0 to 100, works fine.
- tools-hardness: range from 0 to 100, works fine.
- …and more! There are many others that I haven't tested.
Reproduction
Is the bug reproducible? Always.
Confused? Look at the screenshots below, and the short video screencast after all the screenshots.
Reproduction steps:
- Plug in your hardware MIDI controller. Don't have one? No problem, run a virtual MIDI controller. Try using Mamba, as it provides a few knobs just above the virtual piano keys.
- Open GIMP.
- Edit → Preferences → Input Controllers.
- Select MIDI, and press the arrow button to add it to the Active Controllers. Alternatively, if you already have an Active MIDI controller, double-click on it to edit it.
- At the "Device" box, type
alsa
. Alternatively, if you know the exact device path, type it in there.- Bonus bug: that box should be auto-filled with
alsa
. Even better if it was a combo-box or drop-down with the list of available devices.
- Bonus bug: that box should be auto-filled with
- Since Gimp didn't connect automatically to the MIDI device, we have to do it ourselves. Open qpwgraph or Helvum and connect the Mamba MIDI out to the GIMP MIDI input.
- Back to GIMP, click on the "Grab event" button.
- On your MIDI controller, interact with any knob or slider. In case of Mamba, try changing the
Attack
orRelease
knobs (or almost any other knob). - Back to GIMP, the appropriate entry will be selected.
Controller 072
for the Release knob,Controller 073
for the Attack knob, or any other controller for other knobs.- If you have a velocity-sensitive MIDI input, you can also press any (piano-like) key, and the appropriate
Note On
entry will be selected.
- If you have a velocity-sensitive MIDI input, you can also press any (piano-like) key, and the appropriate
- Double-click on that entry to associate it to a GIMP action.
- Use the search bar to find some interesting action. You can search for
: Set
. - Associate with the actions you want to try. I'd suggest
tools-size-set
andtools-opacity-set
; but anyset
action should work.- When attached to CC events, those actions will set the value according to the knob/slider value (converting from the 0-127 range).
- When attached to Note On and Note Off events, those actions will set the value according to the velocity of the note (i.e. how hard it was pressed) (also converting from the 0-127 range).
- After everything is set up, feel free to interact with your MIDI controller knobs and sliders and observe the results in the GIMP window.
- For your convenience, you can leave the "Configure Input Controller" window open. It is not a modal window, you can continue using GIMP normally even with that window open.
Actual results:
- All controls are linearly interpolated from 0-127 range to whatever is the GIMP control range, leading to poor UX.
Expected results:
- For the brush size, I expected to be able to have fine-grained control of the brush size. I expected to go through values 1, 2, 3, 4, 5 of brush sizes. Maybe one-by-one up to 8 or 10. Afterwards, I'd be fine if it started skipping some values. In other words, instead of interpolating linearly, it could use some other formula (log? exp? square?), so that small ranges are still possible (input 0-9 to be mapped to output 1-10), but the bigger the brush size, the higher the increment. This would make it possible to have precise small sizes, while also having access to sizes greater than 100. After all, a brush size change from 2 to 3 is very significant (50% increase), but from 200 to 201 isn't noticeable (0.5% increase).
- For Aspect Ratio, Angle, and any others that have a neutral value at the middle, I expected to be able to reach the exact neutral value (0.0) while using the MIDI controller. This means we can't blindly interpolate the values, we must adjust the formula so that the neutral value is achievable by setting the MIDI control to the position 63 or 64. (Or maybe both, making it slightly easier to snap to the middle value.)