Looking at the AAX documentation is says that AAX_CParamID can only have a strlen of 31 maximum, which is nowhere enforced in the AAX wrapper, which could lead to parameter collisions as this is stored as the key to a std::map<std::string, *> by the mParameterManager.
Also there is no point duplicating the storing of juce parameters in a possibly clashing hash table when an extra pointer can be stored directly to the juce parameter by inheriting from the AAX_CParameter class, and using the mechanism already provide, which already gets called when doing operations (ie a hash table on top of the existing std::map is just extra work):
struct Juce_AAX_CParameter : AAX_CParameter<float>
{
Juce_AAX_CParameter(AudioProcessorParameter* juceParam_, AAX_CParamID identifier, const AAX_IString& name, float defaultValue, const AAX_ITaperDelegate<float>& taperDelegate, const AAX_IDisplayDelegate<float>& displayDelegate, bool automatable)
: AAX_CParameter<float>(identifier, name, defaultValue, taperDelegate, displayDelegate, automatable)
, juceParam(juceParam_)
{
jassert (juceParam);
}
AudioProcessorParameter* juceParam;
};
If you possibly object to doing a reinterpret_cast<Juce_AAX_CParameter*> on the mParameterManager fetching, then don’t have a look at all the other juce parameter code doing this all over the place in the plugin wrappers. Also the juceParam passed in can be a legacy wrapped param, so this logic is done in a single place at construction time instead of every time parameters are accessed.
edit: here is an example of where the lookup is already done, and then it is done again by juce:
AAX_Result SetParameterNormalizedValue (AAX_CParamID paramID, double newValue) override
{
if (auto* p = mParameterManager.GetParameterByID (paramID))
p->SetValueWithFloat ((float) newValue);
setAudioProcessorParameter (paramID, (float) newValue);
return AAX_SUCCESS;
}
void setAudioProcessorParameter (AAX_CParamID paramID, double value)
{
if (auto* param = getParameterFromID (paramID))
{
auto newValue = static_cast<float> (value);
if (newValue != param->getValue())
{
param->setValue (newValue);
inParameterChangedCallback = true;
param->sendValueChangedMessageToListeners (newValue);
}
}
}
AudioProcessorParameter* getParameterFromID (AAX_CParamID paramID) const noexcept
{
return paramMap [AAXClasses::getAAXParamHash (paramID)];
}
And this is what it would look like if it was done just the once:
AAX_Result SetParameterNormalizedValue (AAX_CParamID paramID, double newValue) override
{
if (auto* p = reinterpret_cast<Juce_AAX_CParameter*>(mParameterManager.GetParameterByID (paramID)))
{
p->SetValueWithFloat ((float) newValue);
setAudioProcessorParameter (p->juceParam, (float) newValue);
}
return AAX_SUCCESS;
}