Feature Request: Prevent Sound Cut-Off When Changing Songs – Delayed Song Unload & Global Kill Action

@brad

Current behaviour
When switching songs in a set list, Cantabile immediately unloads the previous song. Any active instruments or media players are stopped instantly, causing sustained notes, effect tails, and backing media to be cut off.

Proposed change
Add an optional set-list level setting that prevents sound cut-off when changing songs by delaying the unload of the previous song until all currently playing audio has finished naturally.

  • On song change:
    • The newly selected song becomes active immediately
    • All new MIDI input is routed only to the newly selected song
    • The previous song remains loaded solely to allow existing sound and media playback to complete
    • Once all audio from the previous song has finished, it is automatically unloaded

New action: “Terminate All Sound”
Introduce a new Cantabile action that can be assigned to a MIDI controller or key command:

  • Immediately stops all sound and media playback
  • Affects the current song and any previously switched-away songs that are still playing
  • Acts as a global “panic / hard stop” for live performance

Live performance benefit
This prevents abrupt audio cut-offs during gigs, allowing pads, reverb tails, delays, and backing tracks to finish cleanly while still enabling immediate control of the next song. An optional global kill ensures the performer retains full control at all times.

1 Like

Hi Peter,

Thanks for suggesting this.

This is a deceptively complex problem that I wish I had a better solution for. Right now the best way to do this is to use linked racks that connect directly to the environment level ports. These ports shouldn’t be disconnected when switching between two songs that both use the rack and should allow seamless transition.

While keeping the song alive during the transition may seem like a simple solution it gets complicated if two songs are using the same linked rack.

That said… right now, I’m reworking Cantabile’s “route manager” - this is the part of the audio engine that manages route connections. This work is to address some other issues but one of it’s jobs is managing zombie midi connections when a route is disabled or changed. It’s the low level part of what’s required to implement what you’re asking and I’ll keep this in mind as I do this work.

TL;DR: this is a complex problem that I’d like to solve but don’t have an ideal solution for right now.

Brad

Thanks for the detailed reply — that makes a lot of sense, and I appreciate you taking the time to explain the underlying complexity. I can see how shared racks, in particular, make this far from trivial.

Here’s a couple conceptual ideas - these are very much “thinking out loud” rather than concrete proposals:

  1. On-demand duplicate shared racks

If switching from Song A to Song B where both reference the same shared rack, and the rack used by Song A is still actively producing audio, Cantabile could spin up a second instance of that shared rack on demand for Song B.

  • Song A continues using the original rack until its sound naturally finishes

  • Song B immediately uses the newly created instance

  • The original instance is unloaded once its audio is silent

This might be particularly viable for shared racks with fast-loading plugins and could potentially be an optional mode.

  1. Shared rack instance pool

An alternative could be a configurable pool of shared-rack instances, defined either globally or per set list.

For example:

  • A setting such as Max Shared Rack Instances = 2

  • When the set list loads, Cantabile pre-creates two instances of each shared rack

  • On song change, if the currently used instance is still active, the next song uses the next available instance.

  • Once audio from the previous instance completes, it becomes available again

If all instances are still active when switching songs, the oldest instance could be re-used (and therefore cut off), which would at least make the behaviour predictable and configurable. In practice, I suspect a pool size of 2 would cover most live use cases, with larger values available for more powerful systems.

I hope these ideas are useful, thanks again for the insight, and best of luck with the route manager work!

Cheers

Pete

This is discussed in detail, with some workarounds, here: Does Cantabile support sustained sound transitions (aka SST/SSS)? - #37 by JimboKeys

I love Cantabile, but am going to try to move to Ableton Live (both to learn it and use one app for both DAW and live performances). Apparently, this isn’t an issue in Ableton Live, as well as some other similar apps like Mainstage and Gig Performer.

I’ve tried some of the workarounds in the discussion above and found them very clumsy and difficult to manage. The “best” one I found was to create an audio file of a pad for 10 seconds in each key, and use song states such that at the end of Song 1, once I move to State 2 of that song it enables and triggers the pad audio file in the key of Song 2. Then in Song 2 that same audio file is enabled, so it will keep playing in Song 2, State 1.

That’s still a bit awkward for a number of reasons (i.e., maybe the actual pads in Song 1 sounded different, had different cut-off, etc.), including having to modify 2 songs minimum each service if say, we were switching from Song 1 in D to Song 2 in G instead of A like last time.

I’ve moved far away from using linked racks because I’d rather have specific tweaks for each song instead of changing parameters in a linked rack and not realizing it when I re-use that rack in another song, amongst other reasons. I use Unify (the VST to rule and tame all VSTs) instead, creating my own custom patches (same as “racks”) that I can use in any DAW, standalone Unify, or in Cantabile so they’re far more useful than investing a ton of time into custom racks that only work in Cantabile.

The audio file transition workaround happens to work for me, sort of, but I realize that can be even more work if you need some other sound rather than pads to carry you through between songs.

All that said, I’m working with ChatGPT to help me understand how to build a dual engine system in Cantabile so songs become racks, and only one “song” is used with 2 song racks you cross-fade between, and load the next song into the previous rack. This might be similar to what some have suggested in the thread above, though it sounds a bit different. Not sure if it will work, but I might give it a go. It will involve converting every song I have into its own rack.

I’ve created over 1000 song-overlaps with SST-like behavior in Cantabile, so I feel like I should comment on this thread even though my opinion will probably be unpopular:

To be honest, if @brad were to add SST support for song playlists, I don’t think I would use it (even though that’s my main Cantabile use-case) because I can’t think of any better solution than what Cantabile already offers in the form of song-states and racks. Here’s why:

I create every “song” as a linked rack that can be loaded into a master Cantabile-song that I reuse/customize as my “song set”. This master song has one song-state per “song”. Cantabile’s state control features allow me to dictate exactly which plugins persist during song transitions, which get deactivated or unloaded, which routes get rewired during transitions, which effects get turned off or bypassed during transitions, etc. It’s all fully customizable because song-states are awesome.

This level of customization is critical for making transitions sound clean, and I don’t see how it would be possible with an SST-like feature for song sets. For example, I have a rack that controls my MIDI control surface, and I need that rack to stay operational and blink lights, slide faders, etc., during transitions. I have it coded so that I can gracefully “back out” of a transition (e.g., un-transition back to the previous song mid-transition to cope with unexpected events).

Addressing @Lowell’s two main concerns about this approach:

Linked racks can be loaded as embedded racks. This allows you to have a separate song-specific copy of each linked rack with song-specific tweaks.

I too use Unify, but I find it very inadequate as a replacement for Cantabile racks. It doesn’t have Cantabile’s binding system, its route filters are too primitive, it doesn’t allow complex wiring flows, etc. Only my very simplest songs can be represented entirely in Unify.

From my experience, there’s really one major Cantabile limitation that prevents perfectly clean transitions: Cantabile does not support polytempo+polymeter. When consecutive songs have tempo-sync’ed arps/fx/LFOs, transitions must somehow simultaneously run multiple racks with different tempos and transport positions. I get around this by running such plugins inside Unify and using its “Don’t Follow Host” transport option. But it’s hard to keep Unify and Cantabile synchronized when I do that, so I wish Cantabile had built-in support for polytempo+polymeter. There are also issues with external clock sync, which I’ve raised in a separate thread.

–Kevin

2 Likes

It’s good you’ve found something that works for you. I have tempo-mapped MIDI tracks on each of my songs, driving automated patch changes (using states), and also tempo-sync’d arps on a few of the tracks. I’m not a big fan of State, and try to use it as little as possible. I find it really complex & confusing, and I frequently make mistakes where I have the wrong state selected when making a change or I forget to duplicate a change across all states. It is a cool feature and I’m glad it’s there when I really need it, but I try to avoid it and keep things as simple as possible. The solution(s) I’ve proposed should maintain that simplicity, because you’re still working with a Cantabile song “per song” and letting Cantabile deal with all the complexity of managing shared-rack-instances, without me having to make things more complicated for myself.

I wonder then whether you might want to request improved UI visualization of state features. For example, I’ve sometimes wished Cantabile had a matrix view that summarized all state-dependent settings across all states (instead of requiring me to switch to each state to see whether the feature is activated). Maybe this would make states easier for you to use.

Because I expect that any SST feature added to Cantabile would be enormously complex—much more complex than states—since it would have to have options for exactly how every element of a song (plugins, routes, route-filters, bindings, …) operates during a transition. (Does it stay active? Does it go into bypass mode? Which audio routes should be considered when deciding when the transition ends? What min gain threshold per route constitutes transition-end? Should the transition settings be song-pair-dependent? … So many checkboxes…)

1 Like

Good point about the min-gain threshold for “silence” to trigger unloading a song, because you do get plugins that have at least some level of constant noise, e.g. a distortion plugin… But a simple noise-gate at the end of your audio chain should address this. You could also have a “silence-threshold” setting (global/set-list/song) where you can set the desired min silence threshold. Only final audio outs need to be considered - not every component/route. You could add a checkbox option to exclude a given audio out, but probably overkill given a noise-gate will achieve the same.

Alternatively, a simple keep-alive-seconds setting (global/setlist/song) that keeps the song alive for max-x-seconds before unloading would be an ever easier way to address most use-cases.

For my purposes, I only want the previous song reverb/note tails to continue for maybe 10-15 seconds after I’ve actually stopped playing, so that I can transition to the new song and press play, start the count-in in the monitors, and have a more seamless/gapless transition.

I want to use this feature for a 90s clubland dance band, so being able to switch to the next song, and leave the previous one fading-out is what I want to achieve.

Incidentally, I got this idea from my Nord Stage keyboard that provides this feature i.e. switching patches doesn’t cut off the audio of the previous patch, and I can play sound on the new patch whilst audio tails from the previous patch are fading away.

What about multiple outs? My audio card has 32 outs, some of which should be “counted” (e.g., pads line, keys line, vocals line) and others not (e.g., click, talk-back). And some of those must persist (e.g., talk-back shouldn’t deactivate after song-transition). Racks and states let me easily choose what stays active across which songs, but I don’t see how to do it without component- and route-level options for what gets loaded/unloaded under what conditions.

That’s exactly what I do with states. It’s easy to create a delayed binding that unloads the previous song after x seconds when the “song” is a rack. But that allows critical midi handling that I don’t see how to achieve with a setlist-level solution. Here’s an example:

During a transition it’s very natural to hold the sustain pedal down, then switch to the next song, then play some notes with the pedal still down. But if no part of the next song has loaded at the time the sustain pedal was pressed, then the new song’s plugins don’t know that the pedal is down, and the notes don’t sustain properly. I guess the proposed SST solution would need to remember certain past CC events and replay them to newly loaded songs. But which events, and on which ports? Previous mod-wheel and pitch-bend should probably “count” when a new song loads, but some plugins react in non-standard ways to those. I guess it would all need to be customizable.

With states and racks I can easily do this because bindings and routes can target not-yet-loaded song components (which exist in the wiring diagram as deactivated racks). I don’t know how to do it in a system where future song components don’t exist until the song is loaded.

I use that on my Nord too. But I think the critical difference is that all Nord patches use a common processing chain, which the wonderful folks at Nord have customized with all the SST considerations we’ve been discussing. In contrast, Cantabile users have arbitrary plugins wired in arbitrary ways, which means all that customization must be performed by each user. Maybe there’s a way to avoid all these complexities, but I don’t know how. States seem so much easier.

Thanks for detailing that! I think this sounds much like what ChatGPT is helping me set up. Each song is a rack.

As to Unify usage, I definitely don’t use it to store a “song” stack. I used to use Cantabile racks to build out essentially patches (layers of VSTs with FX, etc.) Unify, IMO, does this much better, especially since I can create and use these anywhere else, not just in Cantabile, so I’m not re-working racks (patches) I’ve set up in Cantabile to reuse. Plus, having the library capability (i.e., creating my own ultimate favorites, tagging/categorizing, favoriting) is another place where Unify shines, cross-application as well as standalone.

So still, within Cantabile I’d use Unify for the actual patches (including any FX I’ve deemed best for those) that include multiple VSTs, but convert all my Cantabile songs into racks to accomplish SST capabilities.

1 Like

Multiple outs: I would add a checkbox to indicate which ones matter from a silence perspective (have all-checked by default).

Sustain Pedal: I can live with having to press the sustain pedal again on the new song. You could add a system later to have it “re-press” automatically (probably on a setting) - achievable and wonderful, but easy to manually work around to start with.

Mod wheels: Again, I would do nothing special until they are manually moved again. An optional enhancement to make it work as you suggest, on a setting.

I guess that reaffirms why I would never use this feature. My negative experiences with simplified transition approaches that lack reliable pedal support, or that make a screeching sound the first time I move the mod wheel after a new song loads, or that lack any means of customizing what stays loaded, are what led me to adopt racks+states as a superior approach. Just my (perhaps unpopular) opinion.

So another perspective to consider is that of new/casual/Solo users.

Cantabile very much steers these users into the paradigm of songs being represent as “songs”… in a “set-list”. So for new/casual users, or a users that have the Cantabile Solo version, a simple/quick way of enabling gapless song transitions would be fantastic.

Further, that feature would also support song timelines, tempo-synced arps, other capabilities only available at the song level.

A time may come when these users find that there are scenarios that out-of-the-box transitions don’t support, and at that point the routes/states/racks approach, as described above, is totally available (albeit with time and learning) to enable those complex or more edge-case scenarios.

So, I think there’s certainly value in both capabilities, and they can comfortably and usefully exist side-by-side.

1 Like

Agreed. My takeaway is that setlist-SST would be for casual users who don’t care whether everything works quite right, and who don’t anticipate ever needing to fine-tune or fix such issues (since there’s no easy migration path from setlists to racks+states).

But on that note, this makes me wonder about an alternative idea: I wonder how feasible it would be to have “Save Song As Rack” and “Save Setlist As Song” features. If those existed, users who create setlists and later decide that they want SST-style transitions could instantly get a song that does all that, plus the ability to fine-tune and fix all transition details if desired, and I’m guessing it would be far, far easier to implement than SST. In fact, since songs and setlists are just text files, I bet someone could even create stand-alone song-to-rack and setlist-to-song converter scripts. Casual users wouldn’t have to understand how the resulting songs and their states work.

1 Like

Ooh, I love that idea! As I’m about to embark on converting songs to racks, and have almost 200 songs, that might be sweet. I will also ask ChatGPT about this; there may be a way to do that en masse using scripting. For example, and I know this is simple, but when I changed controllers recently I realized that most of my songs were mapped to the previous controller by name instead of using “Main Keyboard” as the “alias” and just changing globally which controller was represented by that virtual controller.

ChatGPT helped me change all songs in like, 5 seconds by replacing text in the JSON song files.

1 Like

Almost all of my songs share racks, and each song has song-specific tweaks for all sounds. All I do is use rack states to hold song-specific variations for the plugins. So when setting up a song I’ll typically add a rack, find an existing rack state from another song that’s close to what I want, copy the state, give the state the name of the song, and apply my song-specific tweaks. That way I never have to worry about overwriting settings used in other songs.

So for example, I have a a VB3 organ rack, and it has 50-60 different rack states, one for each song or song part, with all the variations of the organ sounds I use. The rack state can be linked to song state, so as I step through the states of a song, the rack state changes, and thus the sound changes accordingly. I so this with all of my racks, and it works superbly, regardless of the complexity of the song (some of my songs have upwards of 40 song states!).

2 Likes

I guess for many situations, the main thing is to avoid chopping off envelope and reverb tails when switching songs. I wonder if a very cheap and cheerful solution to this might be that when you select a different song, Cantabile loops a sample of the last, say, half second of audio going to the outputs and decays it away over the transition? That way plugins can be unloaded, states changed, routing modified etc. without affecting the sound, and you’d get some approximation to the sound naturally dying out. There could be a song-level setting for it, to enable/disable it, set the time over which the sample is looped/faded etc, allowing it to be tweaked a little depending on the sounds.

It might not sound perfect for certain sounds, and it wouldn’t solve the situation where you want to hold down notes across a song transition. But it might be a useful approach for some scenarios, to at least resolve the problem of sudden cuts of release/reverb tails.

I’ve read through all the suggestions and ideas in this thread with a lot of interest; unfortunately, the “simpler” solutions like making a song a rack state won’t really cut it in my reality - my songs are too complex for that; and I rely too much on song states and complex routing for this to work.

What could be promising to me would be a re-visit of a discussion we had with @brad about creating additional background racks - an “input” and an “output” rack that stay the same across all songs (unless you explicitly change their states) and that allow routing from the input rack into the song, and then from the song to the output rack WITHIN the audio thread, without incurring additional latency.

This would allow us to have some “master instruments” and “master effects” in the output rack that could remain active across song changes. That way, at a minimum, we could have effect tails spilling over into the next song easily.

Keeping instrument sounds alive across song transition would be easy regarding the audio part (just keep the output rack routed and active permanently, change the song behind it), but there could be a danger of stuck notes, so we’d need a benign mechanism to eliminate those (maybe an explicit binding to close held notes from the previous song?). That way, those of us who want certain instruments to sound across song transitions could have a set of such instruments in their “output background rack” and feed them via routes from their songs. If you don’t need such instruments or effects, there would be no additional complexity or load on the system; far better in my opinion than having full songs load in parallel, causing additional system load.

I guess this could be implemented with reasonable effort - at least a lot easier than having a whole “shadow parallel loading” mechanism for having two full songs active, IMHO

And having an “input” and an “output” background rack would help me clean up a lot of the overhead from my current song files, where a significant part is currently just managing and abstracting input, as well as processing and routing output.

I would still keep the current background rack mostly for managing global bindings, so we’d have three background racks after that architecture change.

@brad: what do you think?

I think having universal input and output racks would be beneficial for all sorts of things, beyond cleaner song transitions. @Torsten, like you, I have lots of stuff duplicated in all songs, which would be much cleaner to have in a persistent input or output rack. I have an output rack within each song that handles some general audio out processing, but also shows plugin UIs for multichannel metering that I keep visible. It would be great to have that all tucked away in a universal output rack. Presumably it would also speed up song transitions a little too, with that overhead now removed from songs.

1 Like

Really silly question time: is that a use case for the background rack - or a linked rack across all songs?