How to link parameters.
On this page
Linked Parameter Operation
The key rule, that can be difficult to follow, is to ONLY LINK USER EDITING. As it states, this means to only link parameters when a user is editing them. This can be somewhat of a difficult rule to follow, but will simplify many issues, both preventing conflicts with automation data which can be edited by the user and avoiding strange behaviors when restoring a chunk. This means your plug-in should still operate the parameters independently without linked behaviors. This is the difficult part!
Here is how the system works WITH linked parameters (aided by our AAX SDK sample plug-in DemoGain_LinkedParameters):
User Editing
- 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.
- The user changes the parameter from the GUI or controls surface. A SET token should be sent at this point.
{
if ( inTouchState )
{
AAX_CParamID linkedControl = this->GetLinkedControl ( inParameterID );
if ( linkedControl )
{
this->TouchParameter ( linkedControl );
mLinkTouchMap.insert ( std::pair<std::string,std::string>( inParameterID, linkedControl ) );
}
}
[...]
}
- 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 it's value set for it's 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.
- The plug-in updates it's internal state and sends an UPDATE tokens for both parameters.
{
bool touched = this->IsParameterTouched ( inParameterID );
[...]
{
if ( type == eType_Pan )
this->SetParameterNormalizedValue( linkedControl, (1.0 - inValue) );
else if ( type == eType_Gain )
this->SetParameterNormalizedValue( linkedControl, inValue );
}
[...]
}
- Repeat steps 2-4 while changing the parameter.
- 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.
{
if ( inTouchState )
{
[...]
}
else
{
[...]
this->ReleaseParameter ( iter->second.c_str () );
[...]
}
}
Automation Playback
- 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.
- The plug-in updates it's internal state and sends an UPDATE token.
- Repeat steps 1-2 while playing back automation.
Chunk Restoring
- Plug-in loads the chuck.
- The plug-in sets every parameters value.
- 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.
- The plug-in updates it's 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:
- 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.
- 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_CParamID linkedControl = this->GetLinkedControl ( inParameterID );
if ( linkedControl )
{
if ( this->IsParameterLinkReady ( inParameterID, inSource ) )
this->SetParameterNormalizedValue( linkedControl, inValue );
}
return result;
}