AAX SDK  2.4.1
Avid Audio Extensions Development Kit

How to link parameters.

On this page

Basics of Linked Parameters

A "linked" parameter can be defined as any parameter whose state is somehow dependent on another parameter. Within this general definition, there are various different kinds of parameter linking:

Basic considerations for parameter linking

Although the concept of parameter linking is simple, implementing linked parameter behavior that is intuitive and consistent can require careful design.

In all of these cases, a plug-in should provide consistent linked parameter behavior: every automated playback pass should be identical, parameters should never "fight" one another or trigger rapid and unexpected changes in other parameters, parameters should not become "stuck" in a particular state, etc.

Here comes trouble

Here comes trouble

Defining proper linked parameter behavior

A good way to approach parameter linking is to start with an understanding of exactly what behavior you desire.

Here are some behaviors that you probably don't want in your plug-in:

With those potential problems in mind, here is a description of how parameter linking should behave.

Correct behavior for linked parameters

Notes

During user-generated real-time edits (from the plug-in GUI or a control surface) both the linker and the linked parameters should be updated. Without this requirement, there would be no parameter linking. In order for this requirement to be enforced consistently the following behaviors must be maintained:

When playing back automation, parameters should operate independently and should not attempt to force dependent parameters to a new state. This prevents fighting in the presence of incompatible automation and ensures deterministic automation playback with every playback pass. As above, there are some more subtle behaviors that must be maintained for this to work properly:

When handling preset changes and plug-in initialization, a similar approach should be taken as with plug-in automation playback. In these cases it is very unlikely that the plug-in's parameters will be left in an incompatible state and attempts at linking may result in unwanted update cycles between inter-dependent parameters or unnecessary coefficient churn. This latter concern can be a real problem for AAX DSP plug-ins that initialize internal algorithmic state based on initial coefficient data.

Compatibility caveat

This behavior was not possible under the RTAS/TDM format, and many RTAS and TDM plug-ins reverted to workarounds such as writing automation to only one parameter at a time and linking the parameters during playback. Therefore, plug-ins that previously supported linked automatable parameters under the RTAS/TDM format may not be able to both implement this recommended parameter linking behavior and maintain compatibility with automation in saved sessions.

Most of Avid's plug-ins that were available in the RTAS and TDM formats fall into this category and should not be used as examples of proper parameter linking behavior. Instead, use the SDK's DemoGain_LinkedParameters example plug-in as an example of proper linked parameter operation.

Linked Parameter Operation

As described above, the key rule for linked parameters is to link during real-time user edits only, and should operate the parameters independently (without linked behavior) during automation playback and preset restore. This rule will simplify many issues: it will prevent conflicts with automation data, avoid potentially strange behaviors when restoring presets, and more.

Here is how the system works WITH linked parameters, using code snippets from the DemoGain_LinkedParameters example plug-in:

User Editing

  1. User clicks on a parameter in the GUI or grabs a parameter on the controls surface. A TOUCH token should be sent at this point.
    • The touched parameter status comes back to the plug-in. If the parameters are linked the other linked parameter should have a TOUCH token sent. This really should only be done for linked continuous parameters. This is done by overriding the AAX_CEffectParameters::UpdateParameterTouch() method.
  2. The user changes the parameter from the GUI or controls surface. A SET token should be sent at this point.
    // *******************************************************************************
    // METHOD: UpdateParameterTouch
    // *******************************************************************************
    AAX_Result DemoGain_Parameters::UpdateParameterTouch ( AAX_CParamID inParameterID, AAX_CBoolean inTouchState )
    {
    if ( inTouchState )
    {
    AAX_CParamID linkedControl = this->GetLinkedControl ( inParameterID );
    if ( linkedControl )
    {
    this->TouchParameter ( linkedControl );
    mLinkTouchMap.insert ( std::pair<std::string,std::string>( inParameterID, linkedControl ) );
    }
    }
    [...]
    }
    const char * AAX_CParamID
    Parameter identifier.
    Definition: AAX.h:352
    int32_t AAX_Result
    Definition: AAX.h:337
    uint8_t AAX_CBoolean
    Cross-compiler boolean type used by AAX interfaces.
    Definition: AAX.h:329
  3. The SET token goes into the system and comes back to the plugin via AAX_CEffectParameters::UpdateParameterNormalizedValue().
    • If the parameter is linked then the other linked parameter should have its value set for its linked behaviour. The system knows this is a linked parameter so when the value comes back to the plug-in via UpdateParameterNormalizedValue() it will know not to perform linked behaviors on that value change. To determine if a parameter should set a linked parameter you check it with the AAX_CEffectParameters::IsParameterTouched() method.
  4. The plug-in updates its internal state and sends an UPDATE tokens for both parameters.
    // *******************************************************************************
    // METHOD: UpdateParameterNormalizedValue
    // *******************************************************************************
    AAX_Result DemoGain_Parameters::UpdateParameterNormalizedValue ( AAX_CParamID inParameterID, double inValue, AAX_EUpdateSource inSource )
    {
    AAX_Result result = AAX_CEffectParameters::UpdateParameterNormalizedValue ( inParameterID, inValue, inSource );
    bool touched = this->IsParameterTouched ( inParameterID );
    [...]
    if ( touched && inSource == AAX_eUpdateSource_Unspecified )
    {
    if ( type == eType_Pan )
    this->SetParameterNormalizedValue( linkedControl, (1.0 - inValue) );
    else if ( type == eType_Gain )
    this->SetParameterNormalizedValue( linkedControl, inValue );
    }
    [...]
    }
    AAX_EUpdateSource
    Source for values passed into UpdateParameterNormalizedValue().
    Definition: AAX_Enums.h:1028
    @ AAX_eUpdateSource_Unspecified
    Parameter updates of unknown / unspecified origin, currently including all updates from control surfa...
    Definition: AAX_Enums.h:1029
    AAX_Result UpdateParameterNormalizedValue(AAX_CParamID iParameterID, double iValue, AAX_EUpdateSource iSource) AAX_OVERRIDE
    Updates a single parameter's state to its current value.
  5. Repeat steps 2-4 while changing the parameter.
  6. The user lets go of the GUI or controls surface. A TOUCH token with the released state should be sent.
    • The touched parameter status comes back to the plug-in. If the parameters were linked the other linked parameter should have a TOUCH token with the release status sent. This again is done by overriding the AAX_CEffectParameters::UpdateParameterTouch() method.
      // *******************************************************************************
      // METHOD: UpdateParameterTouch
      // *******************************************************************************
      AAX_Result DemoGain_Parameters::UpdateParameterTouch ( AAX_CParamID inParameterID, AAX_CBoolean inTouchState )
      {
      if ( inTouchState )
      {
      [...]
      }
      else
      {
      [...]
      this->ReleaseParameter ( iter->second.c_str () );
      [...]
      }
      return AAX_SUCCESS;
      }
      @ AAX_SUCCESS
      Definition: AAX_Errors.h:39

Automation Playback

  1. The SET token comes from the automation system and enters the plugin via UpdateParameterNormalizedValue().
    • The plug-in will know this is not from the user editing therefore it will NOT set the other linked parameter. Remember ONLY LINK USER EDITING. That way there's no conflicts if the user edited the automation or if the order in which automation arrives at the plug-in changes.
  2. The plug-in updates its internal state and sends an UPDATE token.
  3. Repeat steps 1-2 while playing back automation.

Chunk Restoring

  1. Plug-in loads the chuck.
  2. The plug-in sets every parameters value.
  3. The SET tokens comes back to the plugin via UpdateParameterNormalizedValue().
    • The plug-in will know this is not from the user editing therefore it will NOT set the other linked parameter. Remember ONLY LINK USER EDITING. Hopefully the result of this is that the contents of the chunk will be restored to its exact state.
  4. The plug-in updates its internal state and sends out UPDATE tokens.

Changing Tapers

One common use of linked parameters is to change the taper associated with a parameter. For changing tapers there are basically only a two rules you need to follow:

  1. When you're loading a new chunk you need to set the taper values first. If a parameter is what updates the taper then set that value first. That way when the value of a parameter is set from a chunk it wont change because of a taper change.
  2. Update the taper from the UpdateParameterNormalizedValue() method. If the new taper needs to change the value of the parameter you only do so if the user is editing the linked parameter. This still follows the ONLY LINK USER EDITING rule.
AAX_Result Simple_Parameters::UpdateParameterNormalizedValue ( AAX_CParamID inParameterID, double inValue, AAX_EUpdateSource inSource )
{
// GetLinkedControl() is a user defined method which determines the linked control ID.
AAX_CParamID linkedControl = this->GetLinkedControl ( inParameterID );
if ( linkedControl )
{
// IsParameterLinkReady()* is a built in method of AAX_CEffectParameters which determines if the
// parameter should perform linked behaviors based on the touch state of the parameter and the
// source of the UpdateParameterNormalizedValue() call.
if ( this->IsParameterLinkReady ( inParameterID, inSource ) )
this->SetParameterNormalizedValue( linkedControl, inValue );
}
// Call the inherited method for the original parameter
AAX_Result result = AAX_CEffectParameters::UpdateParameterNormalizedValue ( inParameterID, inValue, inSource );
return result;
}
Collaboration diagram for Linked parameters: