Introducing Binding Expressions

Fascinating functionality - as long as it doesn’t hurt overall performance when you DON’T use it…

Personally, I don’t need automatic chord recognition - if I don’t know what chord I’m playing at the moment, I will start worrying about my skills as a keyboardist…

I don’t know what the performance impact of tracking the keys sent to the onscreen keyboard is - I hope it isn’t significant - @brad, can you elaborate?

I would actually prefer no such tracking to be happening if it has a performance impact - rather have those users who want to identify their chords use dedicated plugins for that purpose and route MIDI to them - SongKey from HoRNet Plugins or Simple Chord Detection come to mind. That way, no performance impact for users not needing held note tracking and chord identification…

Just my 0.02 EUR…

Cheers,

Torsten

1 Like

In regard to performance:

  • this will only have an impact if you’re using the functions. The impact comes from the fact that when used in a string expression, there needs to be watch monitors setup for any referenced notes and when anything changes the expression will be re-evaluated.

  • if you’re using these functions in binding expressions they’ll only be evaluated when the binding source triggers so very little overhead there.

  • these expressions are evaluated on the UI thread, so shouldn’t interfere with audio processing even if they did have an overall impact on CPU load

  • these functions are only available on the on-screen keyboard so tracking the held notes is only done for that MIDI device and no others (if you don’t have your main keyboard routed to the onscreen keyboard, there’s even less impact).

  • I have optimized these functions and their underlying classes as much as possible (since I realized they might be used for some extreme skull duggery).

TL;DR: if you’re not using the functions, no impact on performance.

2 Likes

Next build will have a new function to check if a pitch class is held.

is_pitch_class_held(pitchClass[, midiChannel])

eg:

  • is_pitch_class_held(0) will return 1 if any “C” note is held
  • is_pitch_class_held(1) will return 1 if any “C#” note is held
  • is_pitch_class_held(2) will return 1 if any “D” note is held
  • etc…

You can also pass an array

eg:

  • is_pitch_class_held([0, 4, 7]) will return 1 if a C, E and G are held anywhere on the keyboard

You can also pass strings

eg:

  • is_pitch_class_held("C") is equivalent to is_pitch_class_held(0)
  • is_pitch_class_held("CEG") is equivalent to is_pitch_class_held([0,4,7])

When using strings:

  • The pitch class names must be in upper case “CEG” not “ceg”
  • Accidentals are indicated with # or b suffixes. eg: “DF#A” or “CEbG”

This should let you abbreviate your expression somewhat.

2 Likes

Thanks @brad , it sure will. And if it optimizes the decision making process even better.

I didn’t set out to do this as a Cantabile option for me but when Sergio asked me about it he said he had tried the VST type solution and preferred it was embedded in the controller bar as an indicator so this project stemmed from that dialog along with my curiosity. Good to know it won’t affect those who don’t use it, I was worried about that but didn’t think it would if they never employed it.

Your generosity is much appreciated,

Dave

1 Like

Thanks @dave_dore for taking time to provide a comprehensive explanation. I am interested in it around the possibility of triggering events if I hit certain chords and notes.

So that gives me something to chew on. Thanks again. :slight_smile:

1 Like

This is the most suitable solution, it certainly shortens the expression.
I had mentioned a similar solution to Dave, the possibility of reducing it to a simple expression that acted anywhere on the keyboard. An Array or strings like the latter proposed would be an excellent solution.
Hey Brad, Hey Dave, no one can stop you!!

:thinking:

Hmmm

Hey Corky, just “interesting :thinking:”?
I like your feedback… complete, exhaustive…

Who would dare such mischief? :rofl: :rofl:

3 Likes

Build 4156 is now up with the new is_pitch_class_held function.

5 Likes

Hi,

I have just done my first experiment with binding expressions, so thought I would post the use case, which is quite simple, but this new feature is amazing and makes things simpler, and opens up a lot of possibilities, and I thought sharing examples will help others get to grips with it.

I am building a new visual show for my next Spectral Streams solo gig in March. Videos using Imaginando Visual Synthesiser (more on that some other time) are now done, and I am now doing my DMX lights using my trusty old DMXIS controller. In Welsh Floyd, the light show was driven entirely via a linear MIDI track, playing along with the click and backing audio, but in Spectral Streams I am using loops, so need to rethink how I do certain things.

In the case of one song, I will have several DMX cues driven from the MulLabs looper and a MIDI track of cues when I am playing the song, similar to what I did in Welsh Floyd (but now with looping scenes), with MuLabs scenes selected from scene buttons on my Yamaha Montage, but I may also want to select scenes/cues based on what else I am doing, such as using an expression pedal to fade out the music at the end of the song, and where I may not have any hands free, and this is where binding expressions come in.

DMXIS selects cues based on note value, and I wanted to select a specific Cue when I start fading out using EXP1 of my trusty old FC300 MIDI foot controller. So, the start condition is of course I had faded in the song in the first place and the EXP1 pedal is fully “toe down”.

The binding expression shown in the picture below is listening to the MIDI CC of the expression pedal, and triggers a note to my DMXIS rack when the EXP1 CC value drops below 90, but it has to have been above or equal to 90 in the first place.

I can probably also use similar bindings to change scenes in Mulab and on my Montage to keep things in sync.

Thanks, @brad! :slight_smile:

Cheers
Derek

2 Likes

For the record, you should get the same behaviour with slightly simpler:

Condition: Input < 90
Fire: When Condition Becomes True

1 Like

Not sure if this correct or not but when testing Input as a condition it is 1 less than what is sent for a result.

For example this:

if the rack state index is 1, the condition will be true and a 1 is sent to midi…

Hey Derek.

Thanks for the visual. I am just starting with MuLabs after reading @brad’s excellent instructions concerning integration into Cantabile. Seeing how you use this with binding expressions is really opening my eyes. The visual makes it much easier.

Corky

1 Like

One based values like program numbers are a display attribute only and are internally stored zero based and passed through binding expressions as zero based.

@Derek

Sorry…Just realized this was your work, not @brad’s. Still excellent work!

1 Like

@brad

Thanks, it is of course a new learning curve. I will try that later.

Hey @Corky

No issues, and I am just glad somebody is finding it useful! :slight_smile:

I think Cantabile and MuLabs plug in make an excellent combination if you have more of a MIDI looping scenario, like I do these days. :slight_smile:

1 Like

Just hit this bug … upgraded v4153 => v4156 and this bug is fixed … and …

Just replaced 64 individual bindings in my Background Rack with one Expression-based binding … Wheeeee!

2 Likes

I am trying to send the current Cantabile song Tempo via CC to Ableton using a binding expression. Not sure how to access the tempo. Using Tempo or $(Tempo) in a binding expression do not work.

Is there a reference for the variables that are available for Binding Expressions? It does not seem to be this list: https://www.cantabilesoftware.com/guides/variables.