New VST: Smooth Fades for Cantabile

Hi All,

I made some additions and hopefully improvements to the Smoothie rack. First a summary of operation covered in the video.

  • CC 90~97 act as inputs to the fader array. There are 8 separate fader events available.

  • the 3 custom buttons on the rack are shortcuts that open the rack to either the function setting (1st button), the target bindings area (2nd button) or the GUI for the Smoothie VST where you set the duration of the various fades.

  • Setting the function the SLIDER the input expects a variable CC input and provides a smoother to faders and expression pedals. Where ever you stop the travel of the slider or pedal the fade will go to that point.

  • Setting the function the SWITCH the input expects a Momentary Edge sensitive button. Upon reception of the 1st button message the output is an auto fade up. Upon reception of the second press of the same switch the output is an auto fade down. This function is suited to using the same switch to auto fade up and then later on in the song auto fade down.

The following contains some additions and changes to the rack.

  • The ONE SHOT function is one area where I made an addition. The old behavior is still the same, when it receives an input switch (momentary) it fades up. I added a new CC input that allows you to fade down using a different input. For example, I use CC90 SWT to trigger a One Shot fade up to start a song that uses either a switch or a note from the keyboard for the Source. Later in the song I want to fade out so I have a different switch, state change or PG change that sends a CC100 momentary switch to the Smoothie rack to trigger the down fade. The speed of up and down would be the same for the same fader in the array.

  • I added Reset buttons to the individual Fade racks to help when auditioning ONE SHOT fades.

  • I added a Speed Control slider to each OUTPUT rack using a dummy audio output route. Access it by expanding the embedded OUTPUT rack you want to adjust.

  • Another thing I added was CC outputs for external MIDI devices. The CC out number matches the input number. So CC90 input produces CC 90 output. It applies to all the operating functions. You just route the output of the rack to the desired target.

If you have any questions just post here.

Enjoy! :slight_smile:

SMOOTHIE_Version 2.zip (50.2 KB)

Dave

5 Likes

Thanks, Dave

Those changes are (in the words of The Cars) “just what I needed”.

This (and the embedded Smoothie VST) is a really useful rack.

1 Like

Finally got around to downloading and testing the Smoothie plugin - great addition to the arsenal - thanx @Hamlen!

I thought about how to best use this for simple and smooth level automation within a song, and my current approach is this:

  • I created a Smoothie rack (actually multiple copies of it) that uses the rack’s gain fader as input for Smoothie and provides the smoothed output at its output gain parameter (the one inside the rack, not the displayed gain)

  • Now for every instrument rack I want to have automated levels for, I insert a Smoothie rack and create a binding that ties the Smoothie rack’s (inner) output gain to the instrument rack’s outer output gain. Now the gain slider of my instrument rack smoothly follows the gain slider of the Smoothie rack.

  • Set “output Gain” State Behavior of the Smoothie rack to “on” - now I can easily set the target level of the respective instrument by using the gain slider of the Smoothie rack. And I can hear the result in real time, since the instrument rack’s gain will follow automatically, so it’s easy to set my target levels “by ear”

  • The Smoothie rack has different rack states as “speed presets” → 0.3 sec, 0.5 sec, 1 sec, 2 secs, … By setting state behavior for “Selected Rack State”, I can have different ramping speeds for every song state change → have a slow volume ramp-up at the beginning of the song, then faster smoothed volume changes between states.

  • The usage of this rack isn’t limited to changing rack volumes - I can easily use it to send smooth expression pedal moves with a different binding or any other smooth change that I’ll need during a song

Here is the rack, in case someone wants to try it:
Smoothie 1.zip (3.2 KB)

BTW: there is a "Song->OnLoad Song->OnUnload binding in there that sets the input value to something you typically wouldn’t set it to in a song. This is to make sure that the first “real” value the rack receives from the first state change in a song actually is a change, so Cantabile tells the binding to fire. A bit of a brute-force approach, but should work. I’ll have to test it for some time…

And this is what the bindings look like in a song:


(I just created the second binding to test if Smoothie can also create nice MIDI fades - seems to work nicely as well)

The Smoothie rack doesn’t need to be routed in any way - all you need is the binding:

Cheers,

Torsten

2 Likes

OK, did some more testing - looks like the “brute force” approach of initializing doesn’t really work - the rack doesn’t seem to receive the initial state-specific output gain level after the Song-OnLoad binding, so the first state value doesn’t “stick” - will have to do some more experimenting here… For the time being, I’ve updated the binding to a “Song->OnUnload” binding, which seems to work better.

It seems that the event sequence in Cantabile isn’t 100% strict - I had expected the sequence to be Song->OnLoad, then all the State load state behavior loading, but in this case, it looks like the state load for the first state doesn’t come after the rack’s Song->OnLoad.

@brad: is there a way that I could force a specific binding to update its output on song load even though the input value hasn’t changed? This would be extremely helpful for all kinds of initialization bindings. Currently, I need to use different kinds of brute-force approaches to make sure that my automation racks catch the first state of a song correctly…

Happy to consider some thing like this, but not exactly sure where it fits. Do you mean a per-binding option “Resend on Song Load” and/or “Resent on State Load”.

Also don’t forget there’s a “Resend Bound Values” target binding point on songs and racks. Does that help?

Oh, I wasn’t aware of that target point - looks interesting! Not yet 100% sure if this will do it, but let me explain:

My key use case for this with automation racks - used to create smooth transitions between song states. These racks all have internal values within a plugin (e.g. Smoothy or ReaJS); these get changed via State Behaviors; then the plugin will create a smooth transition. This will be sent to one or more receiving plugins to steer levels or parameters, via MIDI routes or direct bindings.

The key issue with this is that for these racks to notice something has changed, they need to receive a value via the State Behavior. Since Cantabile’s State Behavior doesn’t send the plugin a new value unless there is a difference between the current parameter within the rack and the target value in State Behavior, there may be cases that after loading a new song, the automation rack doesn’t change its state, but the controlled plugins/racks are in a different state → not good…

To be sure that everything is initialized, I would like to have a mechanism to force the plugin within the automation rack to initialize and send the correct target value on the first state of a song - of course AFTER the saved State Behavior value within the song has been loaded.

So the sequence of events is important; what happens in what sequence?

  • Song->OnLoad bindings
  • Loading of State Behavior values for the first state

My initial idea was to use Song->OnLoad to set the rack state to something that will definitely be changed by the first State Behavior value, but that didn’t seem to work. The Song->OnLoad does trigger the ramp mechanism within the plugin to the target set in Song->OnLoad, but then the ramp towards the StateBehavior of the first state doesn’t happen. So it looks like Song->OnLoad comes after the internal Rack State Load? @brad, can you clarify this?

Currently, I’m using Song->OnUnload to set the rack to a “dirty” value that will be changed by the first state of the next song, so the ramping mechanism will be triggered. Works, but a bit clumsy…

The problem with “Resend Bound Values” is that it will only trigger the “outbound” bindings of a rack that depend on exposed plugin parameters; this will work with the “Smoothy” rack, since that contains the actual output value as a plugin parameter. But with my ReaJS based MIDI automation, this wouldn’t work: it will only send MIDI data when its sliders (plugin parameters) are updated via State Load - the sliders are VST parameters, but they aren’t used in output bindings; the output is sent solely via MIDI routes.

So to be 100% sure, I would need a mechanism that allows me to force State Behaviors to send value updates to plugins contained in the rack on Song Load, to force the plugins to “do their thing” at the beginning of a song to make sure that all “dependent” racks get initialized…

The most immediate question to go the next step: when are “Song->OnLoad” bindings triggered within racks? Before or after the State Behavior values get loaded (I assumed this is “State->OnLoad”)? Unless this is 100% clear, I’m struggling to put the right mechanism in place (can I use a Song->OnLoad to initialize the first state?).

Hope this all makes some kind of sense - sorry for the convoluted explanation; still trying to understand in detail how the sequence of song and state loading works with State Behaviors …

Cheers,

Torsten

Hey @Torsten,

This is definitely a complex area. Let’s summarise the current way things work:

For a single triggering event, the order bindings are invoked is defined here but is basically:

  1. song
  2. the songs racks (in song order)
  3. any nest embedded racks in the song’s rack (in undefined order)
  4. the background rack.

Remember, this is for a single event. ie: events that are broadcast across songs and racks (eg: a Song Load event) will trigger the bindings in the above order.

On top of this is the order of the events, which for song and state load events is:

  1. Rack Load
  2. Rack State Load
  3. Above repeated for all racks
  4. Song Load
  5. Song State Load

Combining all the above, for a song with 2 racks you get this order: (object <= event)

  1. Rack 1 <= Rack Load
  2. Rack 1 <= Rack State Load
  3. Rack 2 <= Rack Load
  4. Rack 2 <= Rack State Load
  5. Song <= Song Load
  6. Rack 1 <= Song Load
  7. Rack 2 <= Song Load
  8. Song <= Song State Load
  9. Rack 1 <= Song State Load
  10. Rack 2 <= Song State Load

Now consider the case where the same two racks are used in two songs and in both songs, both racks use the same states:

  1. Song <= Song Load
  2. Rack 1 <= Song Load
  3. Rack 2 <= Song Load
  4. Song <= Song State Load
  5. Rack 1 <= Song State Load
  6. Rack 2 <= Song State Load

If the racks however use different states, you’ll get this: (same as initial load, but without the rack load events - because the racks are already loaded).

  1. Rack 1 <= Rack State Load
  2. Rack 2 <= Rack State Load
  3. Song <= Song Load
  4. Rack 1 <= Song Load
  5. Rack 2 <= Song Load
  6. Song <= Song State Load
  7. Rack 1 <= Song State Load
  8. Rack 2 <= Song State Load

Now let’s look at where state behaviour parameters fit into things. Lets assume Rack 1 has a state behaviour controlled plugin parameter. When the parent songs both use the rack with the same state, nothing happens and everything is the same as before:

  1. Song <= Song Load
  2. Rack 1 <= Song Load
  3. Rack 2 <= Song Load
  4. Song <= Song State Load
  5. Rack 1 <= Song State Load
  6. Rack 2 <= Song State Load

If however, the songs have a different states for Rack 1, then the order is:

  1. Parameter is assigned
  2. Rack 1 <= Rack State Load
  3. Song <= Song Load
  4. Rack 1 <= Song Load
  5. Rack 2 <= Song Load
  6. Song <= Song State Load
  7. Rack 1 <= Song State Load
  8. Rack 2 <= Song State Load

As another example, if the song has two states, each loading different state on the rack, then when switching states:

  1. Parameter is assigned
  2. Rack 1 <= Rack State Load
  3. Song <= Song State Load
  4. Rack 1 <= Song State Load
  5. Rack 2 <= Song State Load

Finally, if the plugin parameter is not just state behaviour controlled, but exported to the parent song then the same thing happens:

  1. Parameter is assigned
  2. Rack 1 <= Rack State Load
  3. Song <= Song State Load
  4. Rack 1 <= Song State Load
  5. Rack 2 <= Song State Load

The only difference with the last example, is that even if the song doesn’t change the rack’s state and only affects it through exported state behaviours, the rack state load event still fires (since internally it does a state load to apply the exported state behaviour).

Regarding this:

Unless there’s some edge case I’m not aware of, state controlled plugin parameters are always applied regardless of the plugin’s current value. ie: in the above explanations “Parameter is assigned” is unconditional - it always happens.

I hope this clarifies the current way things work but not sure it helps solve your issue. Let me know if there’s something I can add that will let you solve it.


Note: In writing all this, I found one small bug relating to the order events are fired across racks but I don’t think this affects your scenario. Bug will be fixed in 4139.

1 Like

Wow - great summary! Definitely a keeper for my “Cantabile secrets” book!

OK, then it seems to be more an issue of the “smoothing” plugins - these won’t send output values unless an input parameter changes (makes sense).

One question: the “Re-send bound values” doesn’t seem to work on MIDI output bindings: This binding


doesn’t seem to fire when I force the “Smoothie 1” rack to re-send its bound values with “Output Gain” being the bound value.

My expectation was for the “re-send bound values” to re-send the value of OutParam1 to Rack-Output Gain, and thus for the binding above to send a new MIDI value. But this doesn’t happen - no new MIDI messages appear.

Am I getting this binding wrong?

I had a look at this and the Resend Bound Values binding is working fine and the Rack’s Output Gain is reapplied. The problem is, if the Output Gain value doesn’t actually change, then the binding from it to the MIDI point doesn’t get triggered.

This is not an easy thing to change in Cantabile - there’s lots of places where redundant value assignments are suppressed.

Two suggestions:

  1. Instead of Output Gain, use a MIDI event
  2. Trigger the Resend Bound Values binding on the rack with the MIDI binding - not the rack with the param to output gain binding.

yes, that looks like the elegant solution - make the Smoothie rack output both smoothed output gain AND ramped Midi CC output. In that case, resend bound values should work.

I’ll test this tomorrow…

Quick note: In case anyone is still using the original version of the Smoothie VST, I recommend updating to the latest one (currently v1.2), which is downloadable from the github link in the first post of this thread.

Great to hear that folks are finding it useful!

4 Likes

OK, did some testing with this - looks very good! It seems that during the setup of a song, Cantabile will will actively refresh the bound plugin parameters, so re-sending bound values isn’t necessary.

I created a binding from Smoothie’s output value to the rack’s MIDI output, and it did send the correct MIDI output value at the start of the song without any change to the input parameter, so that’s good - no unpredictable starting of songs…

Actually, Cantabile seems to refresh the current value of the output a couple of times on loading - I’m getting six MIDI messages with the same value when loading a song (without any Song-OnLoad initialization binding). Doesn’t hurt for this use case, but may be interesting for @brad

I used Cantabile’s binding mechanism of converting the output value to MIDI instead of using Smoothie’s built-in MIDI output, in order to be sure that Cantabile would actually read and output the current Smoothie output value without the input parameter changing. I guess Smoothie wouldn’t output any MIDI if the input doesn’t change, so using Cantabile bindings seems to be the better choice to make sure initialization of my song works.

Here is the latest version of my Smoothie rack for anyone who’d like to try it:
Smoothie 1.zip (3.3 KB)

Cheers,

Torsten

1 Like

Hi Kevin,

I love the seconds readout on the slowness, very helpful!! Thanks for the update. :slight_smile:

Dave

2 Likes

I guess Smoothie wouldn’t output any MIDI if the input doesn’t change

Correct – VST3 plugins only receive parameter change info from the host, so SmoothieVST can’t initiate any CC outputs until a parameter actually changes. (It doesn’t have any visibility into song or rack states/loads, etc., which are the province of the host.)

1 Like

I wonder how much it would take to convince @brad to build Smoothie-like behaviour into Cantabile, so a plugin wasn’t needed. So values modified by state changes, such as faders, can have a rate of change parameter. I wonder if this would fit cleanly into Cantabile’s architecture?

Neil

3 Likes

I would love to see that. And there are a few songs where cross fading between states would solve a lot of problems.
Tom

1 Like

Great feature request.

1 Like

Yes - one of the highest priorities on my Cantabile wishlist - @brad has hinted that the new bindings architecture may enable something like this in the future…

2 Likes

I nearly mentioned something about this in one of my previous replies here, but decided not to because I didn’t want to prematurely get people’s hopes up. It’s definitely high on my list and might tackle it after this next batch of smaller changes.

3 Likes

The discussion here has inspired me to share some of my other creations with the community. Maybe some of these are also worthy of feature addition consideration if they prove popular.

Happy holidays!

2 Likes