Issues when changing or adding racks in existing songs

Hi @Torsten,

I’ll take a look at this in the morning.

Brad

Hey @Torsten,

I had a look at this and it seems to be working fine. Check this video and let me know if I’m doing something different to you.

Brad

FWIW I also have a similar “current state carrying over” issue in C3, and have for some time. I fix them exactly as ukm did. Yet, it only seems to occur on complex songs where I’ve been doing a lot of editing. For example, one song was edited and working great for several days. 2 days ago I opened it and the 2nd rack state was the same as the first, although it was supposed to be different. And I know it was previously saved and locked. So on each song state I selected another rack state, then the correct one, and saved. That seems to be the fix every time. Not a big deal for me since I test new songs several days before gigging, and it is only on very complex songs so it’s somewhat rare. But it does seem like the song file gets corrupted or something like that. I know that’s not the case but it does seem odd.
Tom
Tom

That has been my experience as well in some cases - simply using “update state” didn’t help - I needed to explicitly select a different state and back to make Cantabile register the correct rack state to save.

You’re definitely doing different things: what you are doing is editing states WITHIN the Smoothie rack.

What I am doing is happening at SONG level: the Output gain parameter that I mean is the “Outer” output gain; and “Update All States” also is at SONG level, not within the rack.

I am using the Smoothie rack to create smooth volume transitions for one or more other racks in my songs - when I set a state-specific (outer) output gain of the Smoothie rack, it will create a smooth transition internally and provide it to song-level bindings at its (internal) output gain, used for song-level bindings that control the gain level of other plugins.

Now say an existing song has 14 states (not so rare for me, since I also use states to switch lights). I load Smoothie 1 into this song, set its (outer) output gain state behavior and also its “selected rack state” state behavior to on.

Next I will create a first “default” configuration of the Smoothie rack, with the level set to 0 dB and the selected rack state set to 0.3. After clicking “Update All states” for both parameters, I would expect all 14 song states to be initialized with these values.

Now I’ll go to state 7 and set the level to -3 dB and the rack state to “2” for 2 seconds smooth time. Update state - should be fine, shouldn’t I. So I’d expect all other states to have 0 dB and 0.3 seconds stored and ready to run. So this is what things should look like:

state 1: 0 - 0.3 sec
state 2: 0 - 0.3 sec
state 3: 0 - 0.3 sec
state 4: 0 - 0.3 sec
state 5: 0 - 0.3 sec
state 6: 0 - 0.3 sec
state 7: -3 - 2 sec
state 8: 0 - 0.3 sec
...

But on going from state 7 to state 4 (just to pick one), I see that the -3 dB and the 2 seconds have carried over, so it seems that no song-specific state information has been stored with the other states, aside from state 1 (that I used to create the initial “default” configuration. I would expect for state 4 to have the information 0 dB, 0.3 seconds stored and recalled when I change from state 7 to state 4.

Next, I try this the hard way: I go to state 1, set the values back to 0 dB and rack state 0.3 and step through states 1 to 6, pressing CTRL-U to save the information in the rack state. But after hitting preset 7 (with the correct information stored and recalled, I go back to state 6 (which has been updated with the values set for state 1 and carried through) only to find that the rack state stays at “2” for 2 seconds. So I need to change the rack state of the Smoothie rack from 2 to .3 and update state 6 again - then it will stick for state 6. TBH, not sure if the same applies for the output gain, but this definitely happens for the “selected rack state”.

So next step: go from state 6 to state 5 (which is also to be set to 0dB and 0.3) - all is fine, since we come from state 6 which is set to the same values. Press CTRL-U to be sure… But now we go to state 7 (-3 dB, 2 seconds) and go directly to state 5 from there - and the rack state stays at 2 seconds instead of switching to 0.3.

So to be sure that the correct rack state is saved with every song state, whilst having a sequence of identical settings, I seem to need to go through all song states, select a different rack state from the pre-existing correct one, then select the correct one again - only then, the setting will “stick”, and I will get the correct value when I switch from state 7 to state 5.

So my speculation is as follows:

  • when inserting a new rack into a song and activating state behavior for some of its parameters, the current values for these parameters aren’t immedially written to all other states - so the values stay “undefined” for all states
  • when hitting CTRL-U or selecting “Update State …”, Cantabile should write these values to the respective state for all relevant parameters, but appears to only do so for as-yet “undefined” values if these actually have been manually changed from their previous values (so Cantabile recognizes them as “dirty”.
  • But if a state-specific value is currently “undefined”, and the current values are carried over from switching from a previous state, Cantabile will not know that it needs to save them, since they apparently haven’t been marked as needing to be saved. Looks like on “update state” Cantabile doesn’t go exhaustively through all parameters marked as song-specific and creates values if they haven’t been defined yet, as long as these haven’t been touched.

To be sure, this is just my speculation what might cause this, but maybe worth exploring

  • The “update all states” doesn’t seem to reliably create and initialize the values for “Selected Rack State” for all song states.
  • I’m not sure if the same applies for the Output Gain parameter - will have to test this again to be sure, but it is definitely the case for the selected rack state.

Hope this clarifies!

Cheers,

Torsten

Hi @Torsten,

Ah ok… this is a much trickier problem because in this case “update all states” effectively means update all states in all songs that use this rack and I don’t want to have to go find all the songs that use it.

I need to think very carefully about this so give me a couple of days while I sort out a bunch of other random issues and can then focus on fixing it properly.

Brad

Not sure why this needs to go through all songs??? State behavior of rack parameters is song-specific.

I am only expecting “update all states” to go through all states of the currently loaded song, create a state behavior value in every state where there isn’t one yet and set it to the current value of this parameter. No need at all to touch any other songs.

Just to be sure: I am NOT changing anything in the Smoothie Rack; I am simply inserting this rack into an existing song and then (at song level) setting the State Behavior of two parameters of this rack (Output Gain and selected State) to “On”. The problem then is that then saving these song-specific state parameters via “update all states” or “Update State …” doesn’t stick.

Other songs shouldn’t be affected at all - I believe this problem is completely local to one song.

I have a diagnostic idea to follow up on - will see if this works and get back to you :wink:

OK, did some experimentation - sorry, this will be a long post…

Inserted the rack Smoothie 1, set its parameters “Output Gain” and “Selected Rack State” to be controlled by song states. Initialized the first state with default values (gain 1, selected state “0.3”). Saved the song file - the rack section looks like this:

	{
		"kind": "RackHost",
		"embeddedRack": null,
		"RackFile": "C:\\Cantabile\\Racks\\Smoothie 1.cantabileRack",
		"gain": 1,
		"rackState": "0.3",
		"exportedRackState": null,
		"RackFileRelative": "..\\..\\Racks\\Smoothie 1.cantabileRack",
		"userNotes": null,
		"primaryView": false,
		"resetRackState": false,
		"runMode": "Running",
		"stateManager": 
		{
			"behaviour": 6,
			"indexedBehaviour": null,
			"externalBehaviour": 0,
			"externalIndexedBehaviour": null,
			"nonLinkedBehaviour": 0,
			"nonLinkedIndexedBehaviour": null,
			"resetBehaviour": 0,
			"resetIndexedBehaviour": null,
			"states": 
			{
				"22": 
				{
					"runMode": "Running",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": true,
					"savedBehaviour": 1023
				}
			},
			"resetState": null
		},
		"solo": false,
		"soloControl": true,
		"wiringPositionX": 0,
		"wiringPositionY": 0,
		"nextUniqueID": 1,
		"uniqueId": 86,
		"routes": [],
		"name": "Smoothie 1",
		"sendBalance": 0,
		"displayExpanded": true,
		"slotColor": "Default"
	}

So, as expected only one state defined, rest “undefined”.

Now did an “update all states” on the two parameters and then changed the values for one specific state (State “13”) to gain 0, rack state “2”. Saved the song.

This is what it looks like now:

	{
		"kind": "RackHost",
		"embeddedRack": null,
		"RackFile": "C:\\Cantabile\\Racks\\Smoothie 1.cantabileRack",
		"gain": 0,
		"rackState": "2",
		"exportedRackState": null,
		"RackFileRelative": "..\\..\\Racks\\Smoothie 1.cantabileRack",
		"userNotes": null,
		"primaryView": false,
		"resetRackState": false,
		"runMode": "Running",
		"stateManager": 
		{
			"behaviour": 6,
			"indexedBehaviour": null,
			"externalBehaviour": 0,
			"externalIndexedBehaviour": null,
			"nonLinkedBehaviour": 0,
			"nonLinkedIndexedBehaviour": null,
			"resetBehaviour": 0,
			"resetIndexedBehaviour": null,
			"states": 
			{
				"22": 
				{
					"runMode": "Running",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": true,
					"savedBehaviour": 1023
				},
				"1": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"5": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"23": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"13": 
				{
					"runMode": "Running",
					"sendBalance": 0,
					"selectedState": "2",
					"resetRackState": false,
					"outputGain": 0,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": true,
					"savedBehaviour": 1023
				},
				"14": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"15": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"19": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"16": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"2": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"20": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"17": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"18": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				},
				"21": 
				{
					"runMode": "Unloaded",
					"sendBalance": 0,
					"selectedState": "0.3",
					"resetRackState": false,
					"outputGain": 1,
					"exportedState": null,
					"userNotes": null,
					"slotColor": "Default",
					"solo": false,
					"soloControl": false,
					"savedBehaviour": 0
				}
			},
			"resetState": null
		},
		"solo": false,
		"soloControl": true,
		"wiringPositionX": 0,
		"wiringPositionY": 0,
		"nextUniqueID": 1,
		"uniqueId": 86,
		"routes": [],
		"name": "Smoothie 1",
		"sendBalance": 0,
		"displayExpanded": true,
		"slotColor": "Default"
	}

So it looks that song state information was created for the rack for all song states, so no “undefined” values.

Now when I jump between states “13” and “22”, the parameters of the Smoothie rack get applied correctly, but when I jump from state “13” to state “1” or “5”, the values from “22” carry over.

Looking at the state parameters in the song file in detail, I notice two key differences between states “13” and “22” and the rest:

  • runMode of all other states is (incorrectly) set to “Unloaded”
  • savedBehaviour is set to 0 instead of 1023

So I just did some manual patching of the song file and used “revert song” to re-load. Just changing runMode to “Running” didn’t help, but as soon as I also set “savedBehavior” to 1023 for all rack states, things changed for the better - now all rack states load correctly, no values carried over from previous states.

Now changing values via “Update State” properly sticks for this rack for all states.

Summary:

  • when using “Update All States” for a newly created rack, Cantabile does create new song state information for the rack, but incorrectly sets their runMode and savedBehavior values
  • this makes these parameters not load correctly for the un-edited song states for the rack in this song - rack parameters will be carried over from the previously loaded song state
  • setting savedBehavior to 1023 manually and reloading the song fixes that problem - the song state information now loads correctly with changing song states - no more carry over

So to fix this, I guess, you’ll need to teach Cantabile to set the “savedBehavior” to 1023 (and runMode to “Running”) when creating new song state information for a rack via Update All States.

Makes sense?

Cheers,

Torsten

Oh, BTW: just saw that also the “soloControl” was set differently for all state information created by “update all states”. Not relevant in this case, but for consistency, I think the best way for “Update All States” to work would be: if there is no current state information for the rack, then copy the currently set values - not create some default values, which has the potential to mess up things royally…

Hi Torsten,

You’re right of course I was thinking too conceptually and not practically.

I had a quick look at this today and updating a single behaviour for exported states isn’t trivial because of the way they’re managed. Not impossible, but it’ll take some time to implement.

I was hoping to get more time on this today, but I’ve been distracted by a couple of long-standing quirks in bindings that I’m trying to improve.

Brad

Hey @brad - I think we are still talking about two different things. I am NOT talking about making changes inside a rack and propagating them to containing songs somehow, which seems to be what you are discussing.

My main problem is an apparent malfunction of the “Update All States” functionality at SONG level when applied to a newly inserted rack - nothing to do at all with making ANY changes WITHIN the rack.

Trying to reduce this down to the core:

  • I add an existing rack to an existing song that already has a number of song states
  • I make some EXTERNAL attributes of that rack (selected rack state, output gain) dependent on SONG states
  • I use “Update All States” for the selected parameters of the new rack at SONG level to initialize all song states for the new rack to something useful
  • the song state information created for the new rack host by “Update All States” is simply wrong, which causes it not to be loaded when loading a state
  • specifically, it seems to be the parameter "savedBehavior", set to 0 for the newly created state information, that prevents the song state infornation from being loaded.
  • But there are also some other state parameter (running mode, solo control) that are initialized incorrectly by “Update All States”
  • the problem can clearly be seen in the song file (see my post above)
  • patching the song file manually and re-loading the song immediately fixes the issue

So the solution seems to be simple: there is a bug in the “Update All States” function, causing it to create the wrong song state information for “rackHosts” when there isn’t any existing state information. Once the “Update All States” function is fixed, the problem should be gone.

Again, nothing to do with “updating a single behaviour for exported states” - we are talking about a simple malfunction of “Update All States” at song level.

Hope this clarifies?

Cheers,

Torsten

Just a quick update on this. I tried to find a workaround to this problem (short of manually editing the song file every time I add a rack): what does seem be a valid workaround is:

  • add the new rack to an existing song
  • set the correct song state behavior, but DO NOT use “update all states”
  • step through the song one state at a time and use “update state” to save the current configuration - this creates correct state information for the new rack
  • using keyboard shortcuts, this is just a sequence of “P - CTRL-U”

Now the song state information for the new rack is initialized correctly. Tedious, but safe…

You’ll need to do this every time you insert a new rack into an existing song

Do NOT use “Update All States” before having done this - “Update All States” will create incorrect song state information in this situation, which will create difficulties with editing.

After having gone through the above procedure, you can now safely use “Update All States” to make changes, since the state information is now initialized correctly.

@twaw, @ukm - maybe give this procedure a try - should address the “state carrying over” issue - until @brad can fix the “update all states” functionality

Thanks for your info.
In addition to the procedure I described above I use “verify” on my setlist(s) where problematic songs/song states are marked red so that I can see what has to be corrected before I run into a “live dilemma”.

Some more comprehensive thinking about this, so @brad, maybe read this before you dig into my other posts

This whole complication is created because of the way Cantabile creates and stores state-specific information. For simplicity, I’ll be talking about “states”, but in this context I mean “song states”.

  • state specific information is stored in the song with the individual component - rack, plugin, route. At least that’s what things look like in the song files; I assume this reflects the internal data structure of Cantabile. So every rack, plugin or route in a song has a structure attached to it that stores its configuration for individual song states
  • state information is created when (1) creating a new state or (2) updating a state that has no existing state information
  • whenever Cantabile loads a state that has no stored state information for any component (rack, plugin, route), it will simply skip over the loading - the component will stay as it is, which is determined by the previously loaded state or any changes the user has made since loading a state

This isn’t so bad when creating a song from scratch - new song states are created one by one, so every component gets their song state specific information then.

But when inserting a new component (in my case, mostly racks and routes) into an existing song with multiple song states, you get to an increasingly complicated situation: the new component does not have any stored state specific information when it is inserted. This information is only created (one state at a time) whenever you explicitly use the “update state” command. For all other states (that you haven’t updated yet), the state information for this rack stays “undefined”, and the rack parameters will stay at where they were previously.

So if I have a song with 12 states, insert a new rack and I only update states 1 and 5, the rack’s configuration for e.g. state 2 will depend on what state I previously loaded. If I go state 1–>2, state 2 will have the rack in the configuration from state 1; if I go state 5–>2, state 2 will have the rack in the configuration from state 5. Not good from a predictability / “principle of least surprise” perspective.

After a few edits, I have no way of knowing which states have valid state information and which don’t (unless I look into the song file with a text editor) - Cantabile does not show if there is valid state information stored for a component in any given state. This, TBH, creates an unholy mess for me as a user…

The only way to be sure that there is valid state information for every state stored with my new rack is to manually go through all states in the song and do an “update state”. This will create valid state information for the rack for all states, so now I can go on editing without any nasty “carry-over-effects”.

Unfortunately, the “Update All States” function is buggy in that it creates incorrect state information for states where there isn’t any stored information. It will correctly update states where there is existing state information, but it will not solve the issue with “undefined” state information; in fact it creates more of a mess due to the “savedBehavior” parameter. So using the “Update All States” function on components with “undefined” state information should actually be avoided until this behavior can be fixed.

What’s the solution? My suggestion: whenever a new component (rack, plugin, route) is inserted in a song with existing state information, Cantabile should immediately create state information for ALL states for this component. Now we have a well-defined situation for all states, without “undefined data” that isn’t visible to the user.

(Not sure how this would work for plugins, with all the vst parameters and especially the “entire bank” parameter. Maybe create this information only when “ticking” the respective state behavior?)

Hope this clarifies - @brad, also happy to take this directly via email…

Hi @Torsten,

Thanks for your detailed write up. This is now top of my list for Monday morning when I hope to find a couple of quiet hours to focus on this properly. (Last week was a bit chaotic)

Brad

1 Like

Sounds great - let me know if I can help defining the to-be behavior / mode of operation

Hey @Torsten,

I had a look at this and found a bug in Update All States where the SavedBehaviour for the updated states wasn’t getting updated. I think this should resolve some of the frustration you’ve mentioned.

I’m still not sure what the best approach is when adding a new object to an existing object with states. Usually the approach I’ve taken is that the object should be configured such that when switching to a different state it’s as if it’s not there - ie: not to mess around with existing saved states.

For example, if you have a song with states and add a new route, when switching to another existing state that new route will be disabled.

So there’s already an existing mechanism to create a default non-affecting state for missing states - but it might not be optimally configured for some objects.

Brad

OK, interesting! This mechanism doesn’t seem to work for Racks, however - no state information whatsoever is created for new rack hosts, at least according to the song files I looked at. So if you update this mechanism to work for rack hosts as well, the problem of “undefined” state behavior should be solved?

Regarding the pre-setting of state behavior to be as “invisible” as possible in other states, I don’t 100% agree with the approach. I can understand your idea of new objects not affecting existing states if possible; I just haven’t found it very useful so far, TBH. When I insert a new object in an existing song, I am very aware that I am making a change, and I typically am not in the mindset “I am inserting a plugin / rack / route into a STATE”, but rather “I am inserting something into a SONG” - so I take care that I massage its behavior into something useful across the whole job - I find that is my job and not Cantabile’s.

So when, say, I have a song with multiple states, and I find that the piano could do with a string layer, I don’t want Cantabile to decide: “I’m going to de-activate that string layer in all states except the one you were in when you dropped the string layer in”, but rather make that decision myself explicitly. I don’t want to find myself scratching my head “why are the strings so silent in the 2nd chorus?” only to find that the route was de-activated by this mechanism…

So when inserting a new rack into a song, I would expect its default configuration (running mode “running”) to be the same for all states in the song - simple and non-surprising… Can’t think of an alternative default configuration that would be more useful for a rack.

There is only one scenario I have found where the existing mechanism was useful: when adding a new plugin to a multi-instrument rack with individual instruments being switched on/off depending on rack state. In that case, it saved me some state editing to have this new instrument only active for a specific state. But in that case, I was prepared to go and (1) make run/bypass mode state-dependent and (2) de-activate the plugin and use “Update All States” manually, in order to create that configuration; easy and predictable.

So I’d rather have new objects be inserted in a default state (and state behavior as defined per object type) in all song states, and having the responsibility myself to adapt them to song or rack states afterwards. Less potential for nasty surprises…

Just my 0.02 EUR, though - others may find the current behavior very intuitive.

Cheers,

Torsten

OK, that’s very interesting and something that I’ve wondered about. I’m starting to lean towards it’s being more confusing than helpful. Maybe letting go of this idea of keeping new objects invisible to old states is the root cause of all this confusion and I should just let it go and embrace the implications.

1 Like

Just recently I prepared a huge rack with all sorts of amp sims for guitar (most of them demos or free sims), to try them out and compare them. I agree on both your remarks:

  1. it has been useful that each added sim was not automatically active in all states
  2. however, after inserting each amp I had to do lots of editing anyway, so the gain of not having to de-activate each amp by hand was not substantial

I was wondering: what about giving the user the choice of the desired behaviour when creating or inserting a new object in a multi-state environment? Something like:
“Do you want the [object] to be active in all states?”
YES/NO

Another possibility would be to have the desired behaviour controlled by an option (hidden in the option dialog).

just my 0.01 euros (ok they do not exists anymore…but who cares… :wink:)
Gabriel

1 Like