Introducing Binding Expressions

Hi Clint,

By current tempo via CC from Cantabile how does that pass tempo to Abelton? Tempo is available as a source but to pass the 5 to 300 numbers in it’s range you would need to use CCFine like this

Dave

2 Likes

Thanks @dave_dore!

I have Cantabile MIDI output port [Able1STC Mout] connected to a Bome virtual port that passes MIDI to Live 11 on an input port that uses the Selected Track Control (STC) Remote Script (http://stc.wiffbi.com/) which performs all sorts of useful actions on MIDI commands. I’ve set up STC to work on Ch 15. STC responds to CC 20 and sets Ableton’s tempo to ((CC 20 value) + 60).

So my first (misguided) attempt was a binding that fires on Trigger 1002. This trigger is fired on Song Load, as well as when I hit my [F5] key, so that I can perform an On Song Load reinitialization in the middle of a song, if needed).

My first attempt used the binding shown below. My song tempo in this case is 132, so I’m sending the expression 132-60:

I was trying to figure out how to replace 132-60 with Tempo-60 or $(Tempo)-60, to make this binding less hard-coded (and maybe put it in a linked rack).

Based on your example, I now have this second attempt binding:

… which works at all times, including On Song Load and whenever the C4 metronome tempo changes …

Triple-Plus-YAY!! Thank you so much …

2 Likes

Hi to all.

Over the holidays I had fun setting up some buttons in the Controller Bar taking advantage of some of the new expressions made available by @Brad.

I have always thought about the possibility of displaying chords in Cantabile, instead of using dedicated vst’s that are commercially available and also intrusive in the screens in Cantabile.

I had also discussed this with @Dave_Dore some time ago, who, though possibilistic had expressed concerns to me given a certain complexity of implementation.

I had therefore asked Brad for advice if he thought he would envisage something about it in the future, and recently he has, as it were, granted this wish of mine. From here on, Dave’s help was crucial!

As mentioned, I set up buttons using two of his new expressions.

I use two keyboards, so it seemed useful to think about associating one button each, which, for my convenience, I named Upper Individual Notes and Lower Chords.

But you can also use the buttons with only one keyboard by splitting it. In my case, during my tests, I set the buttons by means of the expression “any_notes_held,” where in the left part of the keyboard (Lower, for me) I display chords and in the right part (Upper) I display individual notes.

In the expressions provided for recognizing chords by Brad, it is possible to use both the notes and the numbers of the held notes: I use for convenience preferably the “numbers” of the notes instead of the “name” of the notes.

For use with the two keyboards I set the expression “is_pitch_class_held”: this expression makes the work much easier than the previous expression. The “Lower” button is associated with the MIDI2 channel and Upper with MIDI1. My OB3 Square is set to MIDI2 and the Korg Pa80 to MIDI1 channel.

A variation for this setting is to have set the single note button for the Korg.

The strings are indeed a bit long to set up but, once written or copied and stored down the fear passes!

Then, importantly, they do not compromise the CPU as far as memory used.

It is a gadget, an extra utility, you name it. If you like it, you can simply use it.

The file is… in color! I preferred it this way because it is more understandable and interpretable. This way you can see the notes, the midi channel and the 0 and 1 (condition return) highlighted.

The setting is not perfect because in some cases two chords might be displayed together. This occurs because the chords to be displayed, many, sometimes coincide. The 0 and 1 conditions that Brad inserted for the expressions are meant to limit these coincidences, some succeeded and some still do not. If only the main notes were present the system is perfect, unfortunately there are the “Sus4, Sus4 le aug, etc.” to complicate things.

I’m trying to fix that. But even so the system works!

I hope it is helpful!

Sergio

Chords.zip (30.6 KB)

C Individual Note

C Major

I was wondering if there is a variable similar to “input” giving the current value of the target? For some settings I have different sources for changing it, e.g. the rotary speed.

1 Like

ooooh, that would be very nice indeed…

1 Like

Currently there isn’t, but it should be possible to add some support for it. There are cases where it’s just not available (typically MIDI targets) where the value is sent and can’t be called back. It can be done though for most other things.

Logged.

1 Like

Getting greedy, then. Would it also be possible to get access to the “previous” value as well, i.e. the previous input value, which - as I understand it - is used for jump prevention? I am trying to replace as many ReaJS scripts as possible with the binding expressions (while waiting for the scripting language), and if I could use the “previous” value then I could rebuild my absolute2relative encoder script.

PreviousInput parameter is already supported:

1 Like

Wauw, worked like a charm, just having result = 64 + Input - PreviousInput and firing on the condition that Previousinput between 0 - 127. Voila, all my absolute encoders can now also substiture as relative. Just use another binding set to Relative Value Encoder and using Offset as encoding.

3 Likes

I’m just starting to look into this new super power. I’m wondering if it is possible to do math on two seperate inputs. The specific use case for me would be two souces of pitch bend. Let’s say that I am applying vibrato manually with aftertouch or ring controller. Not increasing modulation amount, but actually doing small pitch bends. Now i want to add some larger bend with pitch wheel, pedal, etc. Wherever the small bend was at the time now jumps back to zero and then follows the pitch wheel. And, even worse, if I slightly jar the ring or aftertouch with the wheel up or down, pitch jumps back to zero and follows the ring. If I could add the two bend values, the problem would be solved.

Hi Ray,

Interesting case. Are the aftertouch and pitch bench wheel spring loaded as in normal pitch wheels and channel pressure or are they just regular continuous controllers? Also, by ring controller do you mean a midi ring (you put on your finger) controller interface?

Cheers,

Dave

Yup. Normal PB and AT (NI S61 mk2) and Neova ring. Thanks for Following up. I was able to do this easily on my Kurzweil PC4 as it had a secondary PB CC which added to the normal PB. But my hardware synths are all gone.

I came up with these 3 bindings that seem to check your boxes. In the pictures I used the Onscreen keyboard sent to a mini moog sim VST for testing. The 1st binding takes the aftertouch input (* or + a value of your choice to set the range) and adds it the center detente value of the pitch wheel.

The second binding watches the pitch wheel and if it moves above or below the detente it sets the aftertouch back to 0.

The third binding watches the aftertouch and if jogged either way it sets the pitch wheel to 8192 (center detente).

I wasn’t sure on this one because the logic told me it would be at zero because one of the other bindings set it to that when the pitch wheel took over. In that case you would only need this binding to do the reset of the pitch wheel to center detente.

I hope this gives an idea of how it could be done using the new “super power” expression feature.

Cheers,

Dave

2 Likes

I haven’t tried this, and it’s a hack but one way to add two inputs might be to use an Onscreen Keyboard fine cc as a variable to hold one input value. Then in a binding from the other input read back the fine cc and add it.

1 Like

Yep, it works, of course in this case it would add the aftertouch value to the finecc value you stored in the onscreen keyboard buffer. So it creates a new zero point for the aftertouch pitch bends based on the position of the pitch wheel.

The previous bindings I showed assumed that return to 0 meant 8192.

1 Like

Dave and Brad,

Thanks for the input.

Dave - I think you misunderstood my intent. The behavior I was describing is what happens normally. And what I DIDN’T want to happen.

Brad’s hack looks promising. Not sure I will get a chance to try it for a few days. It looks like Dave already tried it for me. Thanks.

1 Like

I’m currently trying to use binding expressions to make my CPU load controller bar button flash red when the load is above some threshold. I’m using the following expression:

Load > 90 ? 1 : 0

Weirdly, this works only for values below 100%. When the load exceeds 100% the color goes back to normal. I’ve already tried to convert to int first but I couldn’t really get this working.

As a side note for Brad: I’ve tried to debug my expression by routing the result to the button caption. At some point this froze the expression system and when I tried to restart the application Cantabile couldn’t parse the configuration file anymore. Turns out that the binding expression set the caption value to null. Maybe you could add some sort of save guard that prevents rogue bindings from corrupting the config.

EDIT: int(substr(Load, 0, strstr(Load, “,”))) > 90 ? 1 : 0 works :slight_smile:

Thanks for reporting this.

I’ll fix the issue with the null string, but in the meantime, this binding works in the latest version:

1 Like