AudioParameter versionHint in updated product - does this work?

We have an existing project build with JUCE 6 and no version hints in the parameters of course. Now we upgraded to JUCE 7 and got an assertion that we should set the versionHint to be non 0 for AU plugins. If we set this to 1 and release an update to our existing product, will this break automation in existing projects?
Also wondering why that assertion is only for AU and not for AUv3?
Thanks!

2 Likes

I’m running into this same assertion on MacOS using the standalone PluginHolder.

does the MacOS build of the Standalone Plugin Holder load the AU build of the plugin and not the VST3 build?

1 Like

This should be safe as long as you don’t add any new parameters during the update. Any new parameters must have a higher version hint than any old parameters.

At the moment, there’s no way for us to adjust the parameter order exposed to the host by an AUv3 plug-in. As a result, the version hints don’t really have any effect in that format.

The standalone wrapper doesn’t load any plug-in. It is statically linked with a shared-code library containing all of the non-format-specific plug-in code. When this library is built, flags (such as JucePlugin_Build_AU, JucePlugin_Build_VST3) are defined, depending on the formats that are enabled in the project.

In the context of this question, this means that you’ll see the version hint warning in all plug-in formats (VST3, AU, Standalone etc.) as long as the AU format is enabled for the project. This is useful because developers are much more likely to debug the Standalone format than the AU format, especially with the out-of-process hosting changes on M1 machines.

3 Likes

Okay, this causes a bit confusion after updating to JUCE7 and reading the comments in the AudioProcessorParameter.

So the best practice is, to update all version hints to “1”?

But the comment in AudioProcessorParameter raises the next question, because it mentions “parameters in AUv2 plugins are sorted first by their version hint, and then by the hash of their string identifier.” (which is imho not true, because in the AU-Wrapper actually not the hash is used, only the identifier, which I guess also results in the alphabetically sorted parameters in the logic controls-view) … in order to “recall of automation data will work as expected”

BUT When I check in JUCE6, there seems no parameter sorting at all?

So the big question is? Is that guaranteed that the order for logic automation will be exact the same after updating from JUCE6 to JUCE7 in general?

PS:
(I’m very sensitive to these issues after my personal “kAudioUnitParameterFlag_IsHighResolution” disaster, which in order to solve I needed a custom modification, because It was never addressed for plugins who already used JucePlugin_AUHighResolutionParameters in conjunction with JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE, but thats another topic.)

1 Like

I believe this is true in JUCE 7, though it depends on whether you are using JUCE_FORCE_USE_LEGACY_PARAM_IDS. Parameter IDs are reported to the host by GetParameterList. In the implementation of this function, we can see that the IDs are generated by calling generateAUParameterID, which internally calls LegacyAudioParameter::getParamID to find the String ID of the parameter, and then calls String::hashCode to generate a hash from this string. When JUCE_FORCE_USE_LEGACY_PARAM_IDS is off, this hash is used as the parameter ID; when the setting is on, the JUCE parameter index is used instead.

Yes, provided:

  • no parameters have been added/removed
  • no parameter IDs have changed
  • no JUCE parameter indices have changed
  • all version hints are set to the same value
  • JUCE_FORCE_USE_LEGACY_PARAM_IDS has not been changed

If you want to be absolutely certain that parameters appear in a certain order, you could use the version hint for this. The first parameter would have hint “1”, the second parameter hint “2”, and so on.

1 Like

Aha! Thanks :slight_smile:

I did a bit research in the forum and old juce code. Speaking to myself, and for all others at the same point, this problem has a loooong history, and the versionHint is the fix, for the messed up parameter access deep down in logic or the audio unit sdk.

It also means for existing plugins, renaming even a single parameter identifier, can mess up the whole logic automation, if I understand this right.

The sheer complexity of things sometimes makes it difficult to keep track of that right away.

1 Like

VersionHints didn’t really work for us, and we got many reports of them not working in several hosts/formats.

The only way we’ve found that works across all formats/hosts is to add new parameters at the end.

FR: Please add non-owning ParameterGroups so we could add new parameters to groups even if the new parameters are added to the processor in a different order than the order the groups are added in.

1 Like

But this is also problematic, and version hints are the solution, to not mess-up logic automation. Because the parameters are sorted after the hashed id in logic, and if you just add new parameters without an incremented version id, the position of all parameter can change, which then can mess up logic automation.

PS: I think the name version hint is misleading, it should be called orderIndexBecauseOfMessedUpAUParameterHandling :smirk:

1 Like

This is not what we experienced. In fact using VersionHint failed for us in Logic and parameter ordering did work. We did have to remove groups as that was the cause of parameters going out of order for us.

Which version of Logic did you test?

I spent a bunch of time investigating this, and came to the conclusion that when Logic stores automation, it always uses the index of a parameter (as returned by GetParameterList) to identify each automated parameter - and this was confirmed by an engineer at Apple.

This is surprising. The whole reason that VersionHint exists is for Logic/GarageBand compatibility. Any chance you could post an example of the code you tried? If it’s a bug on our side, we should fix it.

1 Like

Sure, unfortunately this was several months ago and we’re gearing for a release now and can’t take too long away from it.

The basics of what happened was:

  1. We had parameters in groups using nested subgroups as well.

  2. We added a parameter with VersionHint = 2 and immediately got a report from a Logic user.

  3. After a bit of experimentation we’ve found some way that works with Logic with flat groups, but that broke sessions in all other DAWs.

  4. After some trial and error we’ve found the only way that works across all hosts and formats, including AUv3, VST2, etc is to remove groups and add parameters at the end.

To do it logically using structs/vectors we’ve also added a “ForwardingParameter” class so that our parameters could still be logically organized but there’s one flat list of forwarding parameters that report to the host.

This is exactly what we experienced. The problem as I understood it at the time was that if you’re using ParameterGroups, which in JUCE are owning the parameters and forcing the parameters at certain index position, it’s very difficult to find a way to force the index to be in order, especially if you have 5 new parameters coming in at version #2 and not just 1 new parameter.

1 Like

What do you mean by “nested subgroups”? The docs for AudioProcessorParameterGroup explicitly mentions that a group may not contain inner groups when building for AU:

@param subgroupSeparator   A separator string to use between the name of this group and the name of any
                           subgroups if this group is flattened. AUv3 and VST3 plug-ins can have multiple
                           layers of nested subgroups, but AU plug-ins cannot have any subgroups.

I just tested out the DSPModulePluginDemo_AU in Logic 10.7.9:

So, it looks to me like the version hint does work as expected, even with parameter groups.

1 Like

Our real plugin had something that looked like (simplified)

Kick Group:
    Volume (V1)
    Pan (V1)
    Mono (V2)
Snare Group:
    Volume (V1)
    Pan (V1)
    Mono (V2)
Master Group:
    Filter Cutoff (V1)
    Filter Reso (V2)

So V2 had more than one parameter added, and that’s where things got confusing/buggy.

Also, as I said earlier - in some combination of groups and version hints we did get version hint to work and be stable in Logic (don’t remember which one it was). But it then failed in Cubase and failed in VST2 hosts.

Because we deliver our plugins to multiple formats from a shared codebase, a solution that won’t work with AUv3, won’t work with VST2, etc is not a viable solution for us.

1 Like

To get back to the point.

The whole fuss is because Logic relies on the index instead of the ID in the automation?

Yes? Then it would be cool if that was fixed in Logic.

@mfritze

3 Likes

I don’t think this is going to happen soon though… The only way you can avoid any issues is sticking to index and ID. It’s not hard to add parameters to the end, and it doesn’t hurt.

The issue is backwards compatibility and from the plugin side it is avoidable: you can avoid changing parameters in a way that the index changes – annoying, but possible and most plugins have no problem with it.

The trouble is the backwards compatibility also from the plugin side.
For flat parameter list, it’s easy to add new parameter to the end, but for more complicated architecture, this isn’t so easy.
Currently, every time we add new parameters, we broke the compatibility with param automations of previous version.

No matter how complex the architecture, it shouldn’t be hard to add parameters to the end. Otherwise the architecture needs refactoring. I’d rather have a bad sorted list of parameters than breaking compatibility.

What annoys me the most is that the newly introduced IDs were supposed to simplify maintainability.

Now it’s the other way around, it’s even more complicated and cumbersome. Renaming or adding a parameter can mess up the automation in Logic. And since Logic is very important, you can’t ignore that.

If we had just stuck with the flat parameter list it would be less of a problem. The VersionHint “fix” has an unsatisfactory workaround to the original problem

@mfritze
I understand the problem, but Logic could also save the ID (or hash) and prioritize it in newer versions. So there is the chance we can one day forget this problem :wink:

2 Likes

Yes, supporting everything AUs can do is clearly better, but Logic, etc. simply do not support everything.

Maybe in the future, but realistically almost no existing AU requires it and with the limited amount of engineering time, as we all know, it is tricky to pay for this, especially that this has impact on the file format.