Since there is considerable push for using the AudioProcessorParameter class, why not provide a means of saving and restoring these parameters via XML, for use in AudioProcessor's getStateInformation()/setStateInformation() ?
The following implementation is quite specific to the code I've been working on, but it could no doubt be rehashed for everyone to use with a bit of TLC. The caveat is that I have to use an explicit method that provides an Identifier for my custom processors and parameter base-classes (instead of using the parameter name or processor name, in case anyone happens to use TRANS()).
void CustomProcessor::getStateInformation (MemoryBlock& destData)
{
ValueTree valueTree (getIdentifier());
{
ScopedLock sl (getCallbackLock());
const OwnedArray<AudioProcessorParameter>& parameters = getParameters();
for (int i = 0; i < parameters.size(); ++i)
if (CustomAudioProcessorParameter* const p = dynamic_cast<CustomAudioProcessorParameter*> (parameters.getUnchecked (i)))
valueTree.setProperty (p->getIdentifier(), p->getValue(), nullptr);
}
ScopedPointer<XmlElement> state (valueTree.createXml());
if (state != nullptr)
copyXmlToBinary (*state, destData);
}
void CustomProcessor::setStateInformation (const void* data, const int sizeInBytes)
{
ScopedPointer<XmlElement> state (getXmlFromBinary (data, sizeInBytes));
if (state != nullptr)
{
ValueTree valueTree (ValueTree::fromXml (*state));
if (valueTree.getType() == getIdentifier())
{
ScopedLock sl (getCallbackLock());
const OwnedArray<AudioProcessorParameter>& parameters = getParameters();
for (int i = 0; i < valueTree.getNumProperties(); ++i)
{
for (int f = 0; f < parameters.size(); ++f)
if (CustomAudioProcessorParameter* const p = dynamic_cast<CustomAudioProcessorParameter*> (parameters.getUnchecked (i)))
if (p->getIdentifier() == valueTree.getPropertyName (i))
p->setValue (valueTree.getProperty (valueTree.getPropertyName (i)));
}
}
}
updateHostDisplay();
}
