Pro Tools automation timing

This has been reported before, but it was ten years ago, so I thought it was time for a new post.

The parameter updates for JUCE plugins don’t happen at the right time in Pro Tools, sometimes arriving early by 2000 samples. The discrepancy is different in real time and offline.

I have reproduced this with the JUCE Gain plugin, comparing it to the built in Trim plugin. I recorded the output of silencing/loudening a tone using a 32 sample buffer size and also did an offline bounce of the same audio.

Zooming in, the audio is 2784 samples early in this case. For the next beep, it was 2304, and so on.

This does not seem to be a problem in Reaper/VST, where the offset seems to be related to buffer size:

Is there any way to fix this sooner than the move to sample accurate automation?

I’ve just been doing some more poking around and it seems that the ‘Master Bypass’ parameter is not subject to the same problem, and is registered with the ‘Packet Dispatcher’, as in the AAX SDK example plugin. What difference does the packet dispatcher make versus the UpdateParameterNormalizedValue? I’d appreciate any clues - I’d be keen to work on this problem.

Well I wasn’t put off and had another look at this…

In the AAX SDK example, the ‘internal plugin parameter value’ is not updated when the host calls UpdateParameterNormalizedValue(). Instead, the parameter is marked as ‘dirty’ and the actual update to the internal value is made in GenerateCoefficients().

In the JUCE AAX wrapper, the AudioProcessorParameter value is updated in UpdateParameterNormalizedValue() and GenerateCoefficients() is not overridden.

In a brief testing I did, 1-2 1024-sample buffers were processed in between calls to UpdateParameterNormalizedValue() and GenerateCoefficients(). So if GenerateCoefficients() is indeed the time and place to be updating parameter values (despite the function names), it could explain why automation fires early for JUCE plugins in Pro Tools.

I’ve found the relevant part of the AAX documentation, the relevant AAX demo plugin and even the provided extension designed to handle JUCE’s use case.

  • Doc page: AAX SDK Manual » Additional Topics » Parameter updates » Parameter update timing » Fixing timing issues due to shared data
  • Demo plugin: DemoMIDI_Synth
  • Extension: aax-sdk/Extensions/Topology/AAX_CMonolithicParameters.cpp

The documentation describes JUCE’s use case (“monolithic plug-in objects which are designed to work across multiple plug-in formats”) and explains that “if the algorithm directly shares data with the data model then the algorithm will immediately start using any new data model state without waiting for the corresponding coefficient delivery.”

The extension provides an alternate framework for parameter update delivery which uses a member function (rather than a relocatable free function) for audio processing and introduces a concept of ‘synchronized parameters’ designed to allow the audio processing function access to accurate parameter values.

Is there a reason this ‘monolithic’ plugin design was not used in the first place?

1 Like