Today I started on the design work for a major refactoring of bindings and triggers. The main goal of this is to support binding “anything” to “anything”.
Currently the binding mechanism only supports “MIDI” to “Object”. The plan is to extend this by merging triggers into bindings and providing the following binding source/targets:
- MIDI controller events
- Internal events (aka: trigger events, eg: song load, state load etc…) with optional delay
- Object parameter changes (eg: a plugin parameter or rack setting)
- MIDI controllers (eg: send outgoing MIDI)
- Object parameters (eg: plugin parameter)
- Object commands (eg: Load Next Song)
- External Scripts (as per current trigger support)
- Source to target value mapping
- Explicit values
Each row in the bindings table will essentially look like this:
Source | Event | Target | Action | Value | Notes
and would let you do things like:
- MIDI Binding: incoming CC -> plugin parameter
- MIDI Reflection: plugin parameter -> outgoing CC
- MIDI Mapping: incoming CC -> outgoing CC
- Object Mapping: parameter -> parameter
- Parameter initialization: song state load -> set parameter to explicit value
- External MIDI initialization: song state load -> outgoing PR Change
Most of the work in this is building the infrastructure to support a wide range of binding sources and targets, but down the track this might also allow things like:
- Binding sources for PC keys
- Binding sources for transport position events
- Rack or song user parameters as both binding source and targets
- Direct on-screen control binding.
The intent is to not take away any functionality that’s already there and to accurately upgrade the existing bindings and triggers into the new format.
I’m guessing this will be a solid couple of weeks work (maybe more) and I’m not promising anything yet but interested in thoughts/comments/feedback before I dive in.
I was recently trying to bind a slider on my keyboard to a route gain of a microphone input but couldn’t see where it was possible. I went down the route it to a rack and bind to the rack gain path.
It’d be great if route gains could be targets.
I’m really looking forward to this functionality, and I think it’ll clean up quite a lot of situations where you end up with a trigger, custom event and a binding.
Also if I understand correctly, it would unify the current bindings and triggers tabs into one, which I really like - it would make it easier to get an overview of the “control” aspects of a song.
Neil (the other Neil)
I am also looking forward to this. It will take a lot of confusion and frustration out of the process for me at least.
This is already supported, but there’s a trick to it. It’s documented here.
Yep, that’s the plan. I’m a little concerned it might make the whole thing too wide, but I think it’s manageable.
Love the idea! This would help me do a massive clean-up of my input routings: currently, I have tons of “one-controller-only” routes to let my assign pedals, faders, etc to my racks individually. With MIDI-to-MIDI-bindings, I could simply bind my mod wheel to CC11 on my hammond rack to control the volume pedal with a simple binding instead of routings with MIDI filters, as I currently need to do.
Looking forward to it!!!
Absolutely. This seems like the logical conclusion for bindings functionality.
Wanted to send sustain CC from Keyboard 1 pedal to both the associated (destination) VST plugin and to Keyboard 2’s hardware (so’s not to have to operate two sustain pedals.) Seemed like bindings would be the place to handle this but currently only way I see to do this is a third MIDI route within a Song with a filter suppressing “notes”.
Looking forward to it.
Cheers for the heads up on that, Brad. It works a treat.
Just reading through the comments here one thing I should make clear is that bindings are “stateless” and don’t have the same smarts that MIDI routes do to prevent stuck notes.
In practice, this means you can’t using bindings to route notes (this will be explicitly prevented) or stateful controllers like the sustain pedal (which won’t be prevented). In other words if you bind a controller to the sustain pedal CC of a plugin then you might well end up with a stuck sustain pedal (and corresponding held notes).
Also, I’ve started work on this and have made good progress on the editing side of things. Hoping to have editing finished this week and spend next week on actually implementing the actual binding mechanisms.
Another quick update on this.
Getting the design for this right took longer than expected because of the many different ways things can now be bound together. I’ve now got all the binding editing working and triggers are now automatically migrated to bindings.
Here’s how it looks:
This week I’ll be working on making the new binding architecture actually work.
One small caveat - with the existing triggers you can use states to switch the event that invokes the trigger. eg: the one trigger might respond to song start in one state and transport play in another.
This doesn’t translate to the new bindings because the source of a binding isn’t state controllable. This is a deliberate restriction imposed because a) it’s not that useful and b) it makes bindings harder to understand if you’re overloading the binding source.
All this is to say if you’re using the Event state behaviour on any triggers these won’t convert over correctly and you’ll get an warning message when you open the file.
ie: don’t use this:
And if you have, I’d suggest splitting these triggers into separate triggers and use the enabled flag to mimick the same behaviour.
To be honest I’d be surprised if anyone is actually using this which is why I’ve decided not to complicate the binding framework by supporting it.
I’ve been quiet lately, but also busy. I underestimated how much work was involved in this, but it’s finally starting to come together - and I’ve included more than I originally planned.
I’ve now got the entire binding framework pretty much in place and most of the binding event sources completed, so I can now do things like binding MIDI to MIDI, MIDI to object (like before), Triggers to MIDI, Triggers to Object value, Object values to MIDI (eg: reflect a plugin parameter to an external MIDI controller for LED ring/motorized fader control) etc…
Mostly what’s left is finishing off the bindings for some objects (mainly media players and routes), initial binding value broadcast (ie: sending the initial value of a parameter when the binding is created rather than waiting until it actually changes), a bunch of rough edges to be cleaned up and then testing…
I agree! It will be more intuitive, perfect!
Sorry Brad, will you let to binding CC to Note? It shoud be great like a midi pedal to simulate, in my case, parts of a drums like buss drum, close hi-hat.
Naturally, the event sent in output should be a “togglable” note so One Event Note ON and after One Event Note Off.
It would be possible? Am i wrong?
I can certainly add something like this, but it’s not going to be in the initial build of this.
The problem here is that depending on the source CC there’s a couple of ways this might be mapped to a note. The trick is that notes have velocity as well as on/off. So you might want to map a CC’s value to a note number with a fixed velocity, you might want to use the CC value as a velocity for a fixed note, you might want to toggle note on/off (like you suggest) etc…
ie: I have questions about the exact requirements so initially I’ll just be including the same functionality as the old triggering a note.
Build 3182 has a first pass, experimental, for eval purposes only version of all this new binding stuff. See blog post for details.
Let me know if you find any issues (likely)
Nice work @brad!! I haven’t found any issues so far, but there’s one feature omission I miss straight away, and that’s the ability to manually force a trigger to occur. Useful for testing.
I spoke too soon - one possible bug I’ve found is that my songs had triggers to send a program change to my external gear. Previously it was sending bank.program values like 8.40, 8.2 etc (all bank 8 of my target device). Now it’s appearing in the new binding as 14.40, 14.2 etc.
Fixed now in 3183 put back the play button (but it’s only enabled on command sources - not on CC value sources for example).
Hmmm, in 3183, if I trigger one of my imported bindings that sends a bank.program change such as 7.40 to external gear, eg I get the following MIDI sent:
CC0 value 127
CC32 value 127
Prog change 127
I get those 127s regardless of what actual bank / program change I have set. Note that straight program change (i.e. not banked) works. Interestingly I just switched to straight program change, then back to banked program change, and whatever value I put for bank.program, I now get zeros instead of the 127s above. Puzzling!
Furthermore if I set a banked program change binding target bank.program to something sensible, eg 7.40, then switch to non-banked, the program field is 128. Then if I switch back to banked, the field shows 32767.128.
PS: Thanks for bringing back the play button on bindings, this makes me happy!
Another observation - I can’t get “Absolute with jump prevention” working at all. I’m using bindings from MIDI controllers to Cantabile fader “Gain”, and if I manually change that gain fader, then adjust my MIDI controller, the gain always jumps. The same binding worked fine with jump prevention before upgrading to the new bindings, so this appears to be a regression.