AAX PT 10 bug + fix


#1

There is a bug with the AAX wrapper when working in PT 10.

The reproduction is a bit intricate:

  • A preset was saved with the RTAS version of the plugin (".tfx" format)
  • In PT 10, using the AAX version of the plugin, load that preset
  • Save the session and close it
  • Reopen the session. It opens without the preset loaded

What seems to happen is that PT saves the plugin parameter values in addition to the 'juce' chunk, these are not updated when loading the preset, and these override the preset when opening the session, with their values from before loading the preset.

Here's a proposed fix for the problem:

https://github.com/soundradix/JUCE/commit/8f20715c682ca57e964ed858839d082a2fc04310

Cheers, Yair


#2

I am sorry to revive this old thread, but it turns out that the proposed fix, which has been integrated in juce with the commit linked below, is triggering some undesired behavior in a project that we have just now ported over from JUCE 3 to 4.3.0.

Would it be possible to put in under a conditional macro, so that it can be disabled at will?
No need of fancy stuff in the Projucer, I don’t use it anyway. Just a plain #ifdef that surrounds it is fine (obviously, retaining its current behavior as default not to break existing projects).

Thanks


#3

Could you expand on what undesired behavior this caused? (I’d like to know so as to make sure that our products don’t exhibit problems as well)


#4

Sure!

  1. When Pro Tools loads a session, to restore the state of the plug-ins, it calls that SetChunk() method from an helper thread, that is not the message thread and neither the audio thread.

  2. In that plug-in of mine, setStateInformation() and setParameter() calls are processed synchronously only when they are invoked on the message thread.
    When they come in from another thread, they are deferred with an AsyncUpdater for later processing on the message thread.

With these two facts in mind, let’s see what happens in the code.
Let’s suppose, for simplicity, that my plug-in only has one parameter, whose value starts at 0.5 by default and that should be restored to 0.8 for the session that we are loading.

So:

  • the parameter starts at 0.5

  • pluginInstance->setStateInformation ((void*) chunk->fData, chunk->fSize);
    This should have restored the plug-in state, including setting the value of its parameter to 0.8, but because we are not in the message thread, this will happen only at a deferred time, not synchronously.
    The net result is that, past this point, the parameter value is still 0.5

  • Now, the fix introduced in JUCE that I am talking about, results in:
    SetParameterNormalizedValue (getAAXParamIDFromJuceIndex (0), (double) pluginInstance->getParameter(0));
    which, for the wrapped AudioProcessor, translates to:
    setParameter(0, getParameter(0)).
    Because of statement #2 above, this invocation of setParameter() is also posted for deferred processing on the message thread, rather than processed synchronously, but the value that it should set at that moment is obtained calling getParameter(0) right now, which again returns 0.5.

  • After that, SetChunk() finally exits and the message thread can resume:

  • the deferred setStateInformation() finally restores the plug-in state, setting the parameter to its desired value of 0.8

  • …but the setParameter (0, 0.5) that comes immediately next in the queue, resets the parameter’s value back to 0.5, effectively canceling the effect of the setStateInformation()
    This very last step is the undesired bit that I wish to exclude by disabling the fix added to JUCE.


#5

Thanks for the info!
I guess this won’t affect our products because we process setStateInformation from the thread it is called from, which worked fine for us so far.