Relative-mode bindings with curves?

I recently started using a device with rotary encoders and was disappointed to find that I cannot use binding curves in Cantabile for relative mode encoders like I could with absolute mode encoders (the binding dialog box says “for reverse binding only” next to the curve option). Since @Brad is currently re-engineering bindings, I wonder whether this might be an opportune time to recommend a way to add support for it? I think maybe it could be done without too much hassle as follows:

When a relative mode binding receives a delta Δ to be applied to a target parameter value y, I suggest the new parameter value could be set to f(g(y) + sΔ) where f is the curve function, g is its inverse, and s is the relative scaling factor. I don’t know what function f Cantabile uses for curves, but based on the pictures it draws I suspect inverse g is perhaps just f with the “curve amount” parameter negated, which would hopefully make it quite easy to compute.

This way relative encoders with curves would feel just like absolute encoders with the same curves (i.e., moving an absolute encoder by Δ would change y the same amount as moving a relative encoder by Δ). And dynamically computing inverse g would hopefully avoid storing or tracking any settings or parameter attributes that Cantabile doesn’t already store. (But maybe there are other code complexities that I’ve not considered?)

I’ll keep this in mind when I get back to the bindings work. I can’t remember the exact reason curves aren’t support on relative encoders off hand, but I seem to remember something blocking it.

Thanks for the reply and for considering the idea!

My intuition was that maybe what blocked it for you was that at first blush it seems like knowing what curve-adjustment to apply to a relative-bound target would require separately storing an x-value for every parameter to remember where on the curve it currently is. Maintaining that x alongside the parameter’s actual value y (or only storing x and computing y=f(x) everywhere dynamically) would probably be a mess.

But since curve functions are invertible (by negating the curve amount), I then realized that this mess might be avoided by continuing to store only y, but compute x=f -1(y) wherever x is needed (which is presumably exactly and only the places in the code where the binding’s scaling multiplier is applied, making for a much cleaner implementation).

This is all just blind speculation, but I write it out in case it might be helpful if you get to thinking about it at some point. :slight_smile: