Binding expressions are a new, advanced way to create mappings between source and target binding points. The let you use mathematical and logical expressions to control not only the value sent to the target, but also under what conditions it's sent.
I’ve started exercising these new features and have some questions about results I’m seeing. I began by testing and experimenting as in the video using the Master In and out sliders and the Expression option in mapping. All worked as expected. It also worked with any sliders using 0.000 to 1.000 scaling like rack and plugin sliders.
Next I tried binding a pop up slider from the Controller Bar which sent a MIDI continuous value (0~127) as the Source in the binding. I bound it to the Master input slider which uses 0.000 to 1.000. This gave a wild result. When I moved the controller bar slider from value 0 to value 1 the Master input slider I bound to jumped from minimum gain to 0db and went i moved it to value 2 it sent the master input slider to +6db. After that the value displayed by the slider jumps of the scale and starts gradually increasing from +9.5db to +42.1db.
I tried using Input / 127 * 2, which gives me “correct” values for 0 = -oo and 64 == 0dB, but moving the slider to 127 just gave me +6 dB. I had to drive up the multiplier to 8 instead of 2, in order to reach maximum level, but then the 0 dB level drifts down to cc values around 19 or so, which is unusable.
When using tha standard “Automatic (Range)” Mapping, I get correct mapping of CC values to volume, from 0 to (max). Looks like something is broken when feeding the output slider my calculated values, which ought to be 0…2. The mapping from calculated values to the output sliders seems off. I checked by using the formula Input / 1000 + 2 - this reliably ended up around +6 dB instead at (max). So: what is the numerical equivalent to (max) and how can I get Cantabile to map my values according to the MIDI control curve, as the Automatic mapping seems to do?
Next, I tried the reverse: used Output Gain as the source of the binding and tried to generate MIDI data from it:
This didn’t generate any MIDI data at all when moving the output gain slider. But when changing the Mapping to “Automatic (Range)”, I got wonderful MIDI data for CC11 from 0 to 127 when moving the output slider.
Next, a super-simple MIDI mapping: get input CC 11 from a pedal and output a simple mathematical calculation: Input / 2 - no output at all.
Sounds like you’re getting tripped up on dB vs gain multiplier.
Cantabile’s gain sliders display dB values which go from -oo to +7ish. But that’s just how they’re displayed. Internally they’re stored as a gain multiplier where -oo is 0 and 0dB is 1 and it’s these gain multipliers you need to use when using expression bindings.
If you’re trying to manipulate gain values with expression bindings, you might find the toDb and fromDb functions helpful. See here.
Also, don’t forget the sliders use a control curve that varies things. Perhaps I should expose these curves as functions as well? Let me know if that would be helpful.
Yes, in order to convert gain or dB values to MIDI or vice-versa, we’ll definitely need the control curves. Re-building that logic within an expression “by hand” would be a bit of overkill.
Just re-capping: in order to convert from a MIDI CC value to a correct gain value (control gain via pedal), we’d need to use
control curve to get from MIDI value (0…127) to a dB value
some fancy processing at dB level to do what we want
from dB to get a correct gain value
Is that correct? Or does the control curve work output gain values directly, so we’d only need the “control curve” function to get from MIDI to gain - and do our processing in the “gain values” domain?
Next question: how would we get MIDI output from binding expressions? So far, I haven’t found a way to use the output of an expression to generate MIDI CC values.
OK, quick addendum - had a look at the custom control curves section of the guides. It appears that control curves convert directly between “gain” and “position” values. Positions range from 0…1, so a position should be the result of Input/127 for MIDI CCs.
I fiddled with the formula from the control curve file, but didn’t really get anywhere. I eliminated the issue of a log(0) crashing Cantabile by using Input/127+0.00001 (didn’t want to complicate further by having to use Input=0? : ) ; and in theory the formula should work:
At least, translated to Excel, this calculation provides values between (close to) 0 and 7.8 (which is correct for max gain in this curve), with 64 calculating roughly 1 equalling 0 dB, also correct.
But using this formula in Cantabile simply makes the slider position marker disappear at +oo, so there must be something wrong with the formula - I just can’t find the mistake (yet). Someone needs to check the math…
Still - all too complicated to be useful - so we definitely need the “control curve” function…
Checked the math and came up with this… not sure if it helps explain but does work.
This worked for mating a controller bar pop up MIDI slider (0~127) to a logarithmic Cantabile slider on a rack and it observes the control curve. It gives the basis for other conditional fun. Note that your rig would use 64 instead of 96 for the 0 position.
Well, I looked at the documentation and it didn’t explicitly say that. It did associate “x” with the 2 functions (scalar and position) but didn’t specify the range of “x”. I assumed that since zeroDbPos was defined as a portion of 127 below in the script that it must expect a 0 to 127 variable for the “x” in the first part of the equation.
The document could better define “x” IMO.
On the log value of 0 I’m not sure why that doesn’t crater the app but my theory is that your equation attempted to divide zero by 127 and possibly that operation didn’t digest well. Again, just a theory.
Yes, in addition to what you described I like to see how to do a MIDI value > MIDI value binding that uses the Expression and actually produces a MIDI out. I tried this simple style of binding to do it and while it recieves the source input it doesn’t produce messages to the target.