MiniDexed icon indicating copy to clipboard operation
MiniDexed copied to clipboard

Assign/"learn" MIDI CCs

Open probonopd opened this issue 3 years ago • 20 comments

Update: See this post below for a concise user story and a rough idea of how to implement this.


It would be nice if we could assign/"learn" MIDI CCs (knobs and sliders on MIDI hardware controllers) to manipulate Dexed voice parameters.

E.g., these guys:

image

(Example shows the Nektar Impact LX61+.)

The sliders and knobs all send CCs with values from 0 to 127, and the buttons toggle between 0 and 127: B0 xx 00 ... B0 xx 7F with xx being different for each slider/knob/button. For xx = 07 it is volume, which is already implemented.

You would select, via the LCD, a voice, then select "Edit params", then scroll through the available Dexed parameters using the rotary encoder, and while one is selected, move a slider/knob/button on the MIDI controller, which would make MiniDexed react to this slider/knob/button (=MIDI CC). Then you would rotate the roraty encoder to go to another parameter, again wiggle another slider/knob/button ont the MIDI congroller, and so on. (The assignment should be written to an INI file in order to survive a reboot.)

Imagine that. A "DX7 with more than one Data Entry slider". Isn't that what people would have wanted already back in the day? ;-)

For those without a fancy MIDI controller with many siders and knobs, you could select a Dexed parameter on the LCD UI, then click the rotary encoder button, and then rotate the rotary encoder to manipulate the value of the selected Dexed parameter that way. (Edit: @rsta2 has implemented this in https://github.com/probonopd/MiniDexed/pull/61)]

probonopd avatar Mar 31 '22 17:03 probonopd

We'd also need a scaling of 0-127 to whatever each voice parameter has as an acceptable range. E.g., when the physical slider/knob/button says 127 but the parameter only goes up to 99, the value to be used should be 99 even though the slider is set to 127:

http://www.tonmeister.ca/personal/geoff/emusic/dx7iisysex.html lists the acceptable ranges in the last column.

probonopd avatar Mar 31 '22 18:03 probonopd

Thanks to the awesome work of @rsta2 most of this is implemented. :1st_place_medal:

Highlight an aspect of the idea bold in the original ticket above. @rsta2 do you think this would be doable?

probonopd avatar Apr 03 '22 17:04 probonopd

Thanks! :) I will think about, how this can be done.

rsta2 avatar Apr 03 '22 18:04 rsta2

Similarly, it would be nice if we could manipulate voice parameters using MIDI SYSEX sent over serial/USB.

probonopd avatar Apr 03 '22 18:04 probonopd

OK, one after another. I will keep this in mind.

rsta2 avatar Apr 03 '22 19:04 rsta2

I would like to implement both inside Synth_Dexed because both is also needed for MicroDexed. But currently I cannot do everything at the same time 😀.

dcoredump avatar Apr 05 '22 09:04 dcoredump

OK, no problem. Let me know, if you need support for an interface to the UI (info about the currently selected parameter).

rsta2 avatar Apr 05 '22 11:04 rsta2

Continuing from https://github.com/probonopd/MiniDexed/issues/62:

Also, it would be nice to be able to assign/"learn" Midi CCs

That's also on my task list for MicroDexed. I would try to implement it also in Synth_Dexed later...

Because this effects the UI menu, where the parameter must be selected, which should be assigned to the MIDI CC, for which a message is received, there arises the question, should this be implemented in MiniDexed or Synth_Dexed?

I think the ideal UX would be: You go to the respective parameter in the UI, and then instead of rotating the knob of the rotary encoder, you just wiggle the control you want to assign on the MIDI controller. MiniDexed then knows which CC message to use (from the messages that came from the MIDI controller) and knows which parameter to edit (the one currently on screen). Learning done! Should be written to a file on the SD card in, e.g., mapping.ini so as to survive reboots.

If we agree that we want to do it that way, my question is: Can this even be done in Synth_Dexed (or which portion of it)? or does it need to be done in MiniDexed (because only it has the menu structure and SD writing capabilities)?

probonopd avatar Apr 05 '22 18:04 probonopd

Worth seeing! https://www.youtube.com/watch?v=GIE3WfrEEX0

probonopd avatar Apr 10 '22 15:04 probonopd

For example, a Korg nanoKONTROL 2 could be (ab)used to set the level (volume) of each operator with the slider, and the frequency (ratio) with the knob. Something like that.

image

Kinda like the Korg Opsix does it: https://www.youtube.com/watch?v=CKBr9HjdJr4

Makes this whole FM thing a lot more accessible imho.

probonopd avatar Apr 17 '22 12:04 probonopd

Very cool project!

I was wondering if you would consider adding support for something like the Akai Fire: image

For not much more than the price of a small midi keyboard controller plus the existing electronics parts list (lcd,encoder, breadboard,etc) you get a 128x64 OLED, rotary+push button encoder, 4 capacitive touch encoders, multitude of buttons most of which are red/yellow or green leds and full RGB leds pads. And all of it is controllable via Midi Sysex (midi implementation already rev eng'd: https://blog.segger.com/decoding-the-akai-fire-part-1/) so all a user would need to do is plug it into a RPI along with a DAC.

I think this would need to be a bit more "baked in" than just usual DAW-style midi mapping to get the benefit of using the OLED, LED colors feedback etc.

I've already done midi implementations for the Fire in Dart and TS so there are already existing code bases for reference.

I would be happy to collaborate on this if its something you would be interested in doing in MiniDexed.

maks avatar Apr 18 '22 00:04 maks

Hello @maks, interesting device. If this ticket gets implemented, knobs and faders could be easily assigned to MiniDexed parameters. We are looking for a solution that works with any MIDI controller that has knobs and/or sliders. Which imho would already be a huge usability improvement over the original DX7.

We don't want to hardcode MiniDexed for certain MIDI controllers. Besides, without having that piece of hardware the effort is futile. So unless we find a solution purely using configuration files and/or scripts (and someone is willing to implement them) it is unlikely that there will be special support for the Akai Fire.

probonopd avatar Apr 18 '22 08:04 probonopd

@probonopd yes, very fair point and I think you are right about avoiding hardcoding support for specific midi controllers. I opened a separate issue for scripting support that I realised after I made the comment here would be the better way to approach this so I'll follow up on that issue.

maks avatar Apr 18 '22 22:04 maks

User Story:

"As a user, I would like to assign a "random" knob on my MIDI controller (that happens to send CC 127 with values 0...127) to edit the Freq Coarse parameter. To assign ("learn") the knob, while the display is showing image I would turn the knob in question. Assigned! From that point on, whenever I turned that knob, it would change the Freq Coarse parameter."


The way I imagine this to work is roughly as follows:

We need a global data structure (a map?) that can hold, for each CC number, (the pointer to) a parameter. Optionally (later), this data structure could be loaded from cc.ini and it should be possbile to save it there.

Something like this (just for illustration filled with some values; initially it would be empty):

cc_map = {{1, DEXED_OP_FREQ_COARSE,},
  {2, DEXED_OP_FREQ_FINE,},
  {3, DEXED_OP_FREQ_FINE,}};

Somewhere around the code that is reposible for showing the parameter edit screen, possibly

https://github.com/probonopd/MiniDexed/blob/9c5dea76b078ed7ef69d99e7d65eab9498030929/src/userinterface.cpp#L114-L119

we should listen for incoming CC messages. Whenever a CC message comes in, we would update the entry in cc_map for that CC to contain the parameter that is currently being edited.

For example, if while the display is showing image we turn a knob that results in a MIDI message with CC 127 coming in, then we would update cc_map to contain {127, DEXED_OP_FREQ_COARSE,}.

Learning complete!

Somewhere around

https://github.com/probonopd/MiniDexed/blob/d6025f194319fea7a205621a2aa81bd29ca0fd2f/src/mididevice.cpp#L192-L193

we would go though cc_map to see if it has an entry for the cc_number that has been played. If yes, we would retrieve its param and use it:

We would then scale the incmoing value which is in the range 0-127 with scaled_value = constrain(incoming_cc_value, param.Minimum, param.Maximum) to the range allowable by the respective parameter. (#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) is the definition used by Arduino for constrain().)

Finally, we would call SetParameter (parameter, scaled_value);.

In the example, whenever we turn the knob, we would change Freq Coarse. Mission accomplished!

@dcoredump @rsta2 wdyt, does this make sense? If yes, then wouldn't this have to be implemented in MiniDexed rather than in Synth_Dexed? Or is there an entirely different way to achieve this behavior?

probonopd avatar Apr 19 '22 08:04 probonopd

As I understand it, @dcoredump wants to implement most of the functionality in Synth_Dexed. I don't want to interfere with that, but already offered my help, e.g. for determining the current parameter in the UI, when a MIDI CC message comes in.

rsta2 avatar Apr 19 '22 09:04 rsta2

My thought of implementing this was:

I wanted to give the Dexed class methods for processing SYSEX and MIDI-CC. The MIDI-CC methods should internally get a mapping from the CC number to any function (so also for changing sound parameters) and a scaling (e.g. CC-7 0..127 -> Parameter[42] 95..43 (so also allow a flip of the values)). The target could be any method to change the sound, but also existing CC values.

The biggest problem is that I can't keep up with the fast development of MiniDexed. In this respect: If someone has desire to implement this: Ideally then in Synth_Dexed, otherwise just directly in MiniDexed. I will definitely implement this in Synth_Dexed, but currently I can't say when.

dcoredump avatar Apr 19 '22 09:04 dcoredump

If we want to load and save those assignments in .ini files, wouldn't we need to do at least parts of the logic in MiniDexed anyways?

I know it's a big ask, but I see this one as the last remaining "killer" feature that I'd love to see implemented while @rsta2 still has some time.

probonopd avatar Apr 19 '22 18:04 probonopd

Yes, there is still some time. Accessing the MIDI CC assignments in an .ini file can be done similar to performance.ini.

rsta2 avatar Apr 20 '22 18:04 rsta2

Imagine this together with the ROLI Seaboard Block: https://twitter.com/littlescale/status/1532954508015202304

Would allow us to do things like https://www.youtube.com/watch?v=6SCug5kUsBs

probonopd avatar Jun 05 '22 12:06 probonopd

Continuing from #62:

Also, it would be nice to be able to assign/"learn" Midi CCs

That's also on my task list for MicroDexed. I would try to implement it also in Synth_Dexed later...

Because this effects the UI menu, where the parameter must be selected, which should be assigned to the MIDI CC, for which a message is received, there arises the question, should this be implemented in MiniDexed or Synth_Dexed?

I think the ideal UX would be: You go to the respective parameter in the UI, and then instead of rotating the knob of the rotary encoder, you just wiggle the control you want to assign on the MIDI controller. MiniDexed then knows which CC message to use (from the messages that came from the MIDI controller) and knows which parameter to edit (the one currently on screen). Learning done! Should be written to a file on the SD card in, e.g., mapping.ini so as to survive reboots.

If we agree that we want to do it that way, my question is: Can this even be done in Synth_Dexed (or which portion of it)? or does it need to be done in MiniDexed (because only it has the menu structure and SD writing capabilities)?

I really like the idea of adding additional sliders. However, I think this would be extremely voice dependent, as to which parameters would be modulated. I think the tone generator section of a performance would be a good section to store the midi mappings.

For example, if you load Dexed into a Daw like Reaper then learn some mappings. It's pretty difficult to find a parameter that you would want to tweak live. As compared to other FM VST synths like Exact or FM8. I think it is because with Dexed, the emphasis is on automated envelopes, where as VSTs use more of the DAW support.

I also like the idea of a ribbon controller, the other issue with mapping midi controllers is that they often times are not precise enough. For example, if you map a controller 1...127 to a frequency, unless you do something to map those frequencies to musical notes, its going to be out of tune most the time ratios can also suffer from this. Even, things like delay times or envelope attack times. How do you go from a scale of fractions of millisecond to seconds in any precise manner.

The point is it will take some thought to come up with units and mappings that make musical sense. One that is especially important is the amplitude of the modulating operators, those really need to be tuned precisely.

RK11111111111 avatar Jan 04 '24 03:01 RK11111111111