Subject: Controlling Hardware from a MIDI Controller
I am struggling with what I feel (after 3+ years with Cantabile) should be straightforward: how to reliably control hardware parameters from a MIDI controller.
I’ve been using a system (now in close to 1000 Cantabile song files) that works 95% of the time, but when it doesn’t, I can get (as happened yesterday) a BIG jump in the parameter (it was Volume yesterday) and the results (as happened yesterday) can be unpleasent.
Hoping someone might suggest a more robust approach …
Here’s my current strategy:
-
I’m controlling a Yamaha VL70-m from a FaderFox EC4 with endless, 2’s complement rotary encoders.
-
The VL70 takes parameter changes as 0-127 MIDI absolute values in CC’s or SysEx commands.
-
The MIDI stream is one-way - from Cantabile to the VL70.
-
I issue patch changes from Cantabile which changes the HW values (and I know those values).
-
I show (what I believe to be) the current state of the HW parameter on the Controller Bar.
My long-standing approach has been to:
- Create a Named Route (that goes nowhere important) for each parameter I want to control. Here are the 10 Named Routes I currently have for the VL70, between do-nothing embedded racks ZZ-A and ZZ-B:
-
Use the Gain value associated with the Named Route to hold the values of the associated parameter.
-
Have a binding that accepts internal CC’s with 0-127 absolute values for the parameter, converts them to Gain values, and writes them to the Gain of the Named Route.
-
Have another binding that accepts input from a 2’s complement rotary encoder, and updates the Gain value of the Named Route using a Relative Value Encoder mapping.
-
Have a binding that triggers on changes in the Gain of the Named Route and informs the Controller Bar on a CC.
-
Have another binding that also triggers on changes in the Gain of the Name Route and sends the appropriate CC or SysEx to the VL70. (The SysEx commands can be gnarly, since the conversion must be done as an expression … for example: 0xF0 0x43 0x10 0x57 0x02 0x01 0x56 clamp( ((log(value,10)*20>=-6) ? ((log(value,10)20 + 26.8235294118) * 31.1666666641) : (826-Sqrt(-34869-220660log(value,10)))) / 8.05511811024, 0, 127) 0xF7)
Typical bindings for #3 to #6 above look like this:
This system works well in most cases. Parameters get written to the VL70 reliably and the encoder controls the hardware parameter and Controller Bar display appropriately
However, the crux of the issue seems to be that Bindings from #5 and #6 above do not fire unless that Gain value has changed.
One failure scenario is when I issue a patch change:
- The VL70 loads a “PATCH” value for my parameter.
- If I want a different “INITIAL” value from the “PATCH” value, I can trigger it using the CC for absolute values (Binding #3 above).
- However, if my “INITIAL” value happens to be the same value as was last set for the prior patch, Bindings #5 and #6 will not fire. My INITIAL value is never sent to the hardware.
- When I start playing and later turn the EC4 encoder, the VL70 hardware value jumps from its PATCH value (set by the patch change) to something near my INITIAL value (saved in the Gain value of the Named Route), which can be a BIG jump.
Things I have tried:
-
Conditionally sending CC’s. In other words, setting a flag in a CC that says “Don’t send CCs”. However, I have no way to conditionally send CC from bindings.
-
Temporarily Disabling the bindings that send CC’s, so that I can issue the Patch as well as the Initial values in pairs of bindings without overloading the VL70 hardware. However, I have no way to disable and enable bindings from other bindings.
(Both of these restrictions have been discussed elsewhere on this forum).
I hesitate to set everything to an “absurd” value, then back to “real” values because:
-
The CCs are rather slow to execute on the hardware, and I need delays all over the place to get all the 10 parameters to be set just one time.
-
There really is no parameter in the 0-127 range that is “absurd” for all parameters on the VL70.
Is there a better approach?? Any thoughts, advice, commiseration, rants, etc. are welcome …