DAWS not remembering parameter automation properly

Hi,

Im stumbling into a problem with renoise that i cant quite understand.

With my version 1.0, everything was working fine. I update a couple times and added some parameters, and old projects were being loaded correctly with the correct automation.

But with my current build I’m working on, old projects do not remember their parameters properly at all. i.e I set some automation up for “pitch”, using v1.0, try again in 1.1, and it works, but try with my current build and the automation of “pitch” shows a completely different boolean paramter.

I’ve been adding proper version hints to my parameters, but to my knowledge that was only for AU and Logic. This Renoise and VST3.

Anyone know what could be going on here?

The only thing I can think is that I changed a parameter from being a AudioParameterBool to AudioParameterChoice, and APCHoice to APBool, but the underlying values will remain the same, which is why i made the switch. That and I added some more parameters, but as I said I have added parameters in the past without this problem./

Cheers,
Dario

Update, i’ve been doing some investigating, and heres what I’ve observed.

This is not isolated to renoise. Have tested in Logic and Reason.

I’ll refer to the original version as version 1, and my current build as version 2.

In my “createParameterLayout” I add them my parameters in an order:

#add Parameter 1 (Choice)
#add Parameter 2 (Float)
#add Parameter 3 (Choice)
#add Parameter 4 (Bool)
#add Parameter 5 (Choice)

If I make some automation in version 1, and then load that project in version 2, it looks like all parameters are actually loaded correctly, but the parameters being automated read from 2 parameters above in the list.
e.g. Automate parameter 4, but then update to version 2, and the automation will be applied to parameter 2 instead.

This is seems consistent no matter what parameter I automate.

As I said before, I changed an APChoice to be a APBool, and a APBool to an APChoice, So I tried to revert them back to how they were.

This is almost successful. The first one I converted, (APBool to Choice) was early in the list of parameters, and when I converted it back to a Choice, the automation was one parameter closer to being correct. i.e. Automation drawn on Parameter 4, would then apply to parameter 3 with version 2.

This is obviously a step in the right direction but the second parameter I converted had no effect on this. So I’m still left stabbing in the dark a bit.

Logic seems to be behaving as well which I can’t explain. I am using correct version hints so that is probably helping.

In my experience, VersionHints don’t really work, at least not in a cross-host way. Maybe it works in Logic - but I’m not even convinced it would work in all AU and AUv3 hosts.

The only way I’ve found that works is to make sure the order of parameters is preserved and new parameters are added to the end. If you decide to remove parameters - you still have to keep them in the list basically forever.

That did mean that I had to stop using ParameterGroups, since they own the parameters and don’t let you control the order in which parameters are added.

1 Like

Hi, thanks for your reply.

I actually managed to find out the problem. It was automatable parameters.

The first parameter I modified, I not only changed its type, but I also turned from withAutomatable(true) to withAutomatable(false).

This meant that the list of automatable parameters was shifted slightly. I tracked down the other parameter that I changed to automatable, and added it to the end of the list. Now looks all fine.

It’s crazy to me how primitive this system seems to be. I would surely think that DAWs would prefer to hold the string ID of the parameter and to prefer that.

The version host mechanism was introduced specifically to work around issues in Logic and GarageBand. It is only used in AUv2 plugins, and isn’t needed in hosts other than Logic/GB.

Indeed, VST3, AUv2, AUv3, AAX, and LV2 all use unique identifiers for paramters, with the idea that these identifiers should be constant across plugin versions. This should allow automation to be restored even if there’s a change to the order in which parameters are declared. Hosts that don’t use these parameter IDs when restoring state are arguably broken.

1 Like

In my experience, preserving parameter indexes/ordering works in all hosts (with VersionHint always set to 1) and all formats. I think whatever interface JUCE uses should eventually create ordered indexes to the format/host.

Also, I think having a mechanism that only works in Logic is not useful to plugin developers, as there isn’t a plugin in existence that’s only meant to run on this host.

I’d prefer that non-cross format mechanisms wouldn’t even compile - we had to discover the bugs with VersionHint from users after updates.

In my experience, many hosts don’t respect that and work by parameter indexes. We had too many reports from users about this in the last couple of years with VST3 and AU.

The reason we ended up with this solution is that most hosts do the right thing - or at least, I don’t remember getting bug reports around automation restoration for other hosts, but we’ve had many reports of issues in Logic.

As you’ve discovered, putting all parameters in one big list may make it awkward to reorder parameters, or change parameter groupings. Additionally, relying on indices in a flat list makes it impossible to remove parameters across versions without breaking automation.

There are plugins that are never going to be shipped as AUs, and there’s no need to specify a VersionHint in this case.

I don’t understand what you’re asking for here. Do you want the build to fail if you specify a VersionHint for a plugin format that doesn’t use it, like VST3?

I’d also push back on calling the behaviour of VersionHint buggy. The purpose and behaviour of the version hint is explained clearly in the documentation:

It would be interesting to know exactly which hosts are affected. Hosts using parameter indices to identify parameters in VST3 and AU plugins are broken, so ideally we’d file bug reports against those hosts.

Since IMO many hosts don’t respect anything that isn’t strict ordering, we have to look at this as the main issue. Parameter reordering just doesn’t work in a cross-host way.

Regarding groups - I think if you change AudioParameterGroups to be non-owning and only hold raw pointers to the parameters, you can still have groups in this way.

In our code (that isn’t using groups) we do something like:

struct FilterParams
{
  //V1:
  AudioParameterFloat* cutoff;
  //V2
  AudioParameterFloat* resonance;
};

MyProcessor()
{
    //V1:
    addParameter(filter.cutoff);
    addParameter(otherV1Parameter);

    //V2
    addParameter(filter.resonance);
}

Notice how even though I had manual ordering in there, I still have logical placements for my filter parameters, and can add new filter parameters post-release.

If JUCE would have a non-owning version of the groups - I could also use groups in this situation.

I specifically remember bug reports with some versions of Cubase and Logic. But also I know of bugs with ‘semi hosts’ and meta plugins of sorts. I don’t have the full details ATM but it’s not one host that had the issue, it’s many.

Yes, so what I’d suggest (other than non-owning parameter groups) is to keep the VersionHint interface but make sure that on the back end, it creates strict parameter ordering. That would make VersionHint work as expected even in VST2 and in hosts that work by indexes.

Just to give some concrete information, I made a test project.
This is with Reaper 7.15, on Mac. VST3.

So a very recent version of a popular DAW.

For convenience, this test project creates 3 targets, which are all building the same plugin code but with different parameter versions.

The parameters are:
Original - a, b
OutOfOrder - c, b
InOrder - a, b, c

The saved project (attached) automates a and b in the original version.
When “Out Of Order” is loaded, the automation for “a” is incorrectly processed for the “c” parameter (as it’s the first parameter).

When “In Order” is loaded, automation is processed correctly.

V1Save.RPP.zip (2.0 KB)

1 Like

Update: Logic (11.0.1) also fails this test, even with VersionHint set correctly.
Attaching a saved file that automated the same 2 parameters from the original version.

Similar to the Reaper/VST3 test, when it loads the “out of order” component it is incorrectly applying the automation for a parameter that’s removed into a new parameter that was added - even though that new parameter has a different ID and a different version number.

savedSong - Logic.zip (1.6 MB)

Bumping this, because even though plugin makers can just ignore VersionHint and order their parameters manually, it would be great if better solutions to this problem would eventually be offered by JUCE.

(For example, non-owning versions of the parameter groups).

also bumping this because i am trying to make my new plugin recall some old versions and I needed to remove parameters in the new one and I am not sure how to go about this now

In setStateInformation() parse the recalled data and update the MemoryBlock or parameter xml if the version number in your saved data is older (you should save a version number in your presets)… otherwise look for an obsolete parameter and use that to detect that the preset data is older.

I find it easiest to convert the data block into xml then parse the xml to check parameters before recalling them.

Rail

that works for recalling the parameters but not for the mismatched automation lanes the host sets up before this step (i believe)

Oh this is a sad topic. It seams that some hosts, sorting the parameters using a hash of the parameter ID, and storing the position of the hash in a sorted array, to identify the automation lane. (imho)
Long story short, even the slightest change of a parameter-id, or adding a parameter (even at the end) can completely destroy your automation.
Instead of fixing the problem (in the wrapper?/host?) the VersionHint was introduced, which it makes imho it more confusing, but it looks like it does not work.
So first rule, once you released a plugin, never change any plugin-ID, nor add/remove any parameters.

1 Like

I think that might be true for AUv3, but I’m pretty sure it’s safe to add a parameter to an AUv2, as long as the new parameter has a higher versionHint than any existing parameter. This will ensure that the parameter is added at the end of the parameter list, where Logic uses the index in the parameter list in place of the parameter ID.

In VST3, hosts are supposed to use each parameter’s ID to uniquely identify that parameter. In practice, some hosts don’t get this quite right, but this mainly seems to cause problems when removing parameters.

I don’t think I’ve seen automation recall problems when only adding parameters. I’d be interested to investigate if you can provide an example of a host failing to recall a plugin after only adding parameters. I’d say being unable to add parameters is a more severe issue than being unable to remove parameters - given that these behavours are host bugs, the host developer(s) may be interested in solving these problems.

In AUv2 (at least in Logic), I think adding parameters out of order might work but once you remove a parameter chaos happens even with a new version hint - see my posts above for a way to reproduce.

Cubase is the only DAW I’ve tested that can handle removed/reordered parameters correctly in sessions with existing automation written.

Otherwise only have strict ordering and never removing parameters is the only ‘safe’ way.

Yes, removing a parameter has never been safe in Logic, and this is thoroughly discussed in the documentation for version hints.

so far my issue is with AAX (havent yet resolved this to check other DAWs)
im hoping i don’t need to add a bunch of empty parameters just to get automation lanes to match up; QA for this is not trivial either, can the versionhint workaround help me for AAX?

my example has both removed and added parameters:

a, b, c, d (old version)
b, c, d, e, f, g (new version)

automation from old version params a, b, d actually ended up automating parameters at the end of the list (lets say f & g) and i cannot yet figure out why (maybe related to using legacy IDs)

IMHO, only way to make this work is to keep a in the list. You can have it do nothing in your code, of course (but perhaps think of what it means for users to ignore those existing values).