Hi!
I’m working on an application using macro parameters to control plugin parameters in a rack.
Everything works as expected until the edit is saved to a file and then loaded again. After reloading the parameter modified by the macro seems to have the wrong value.
Looks like the offset coming from the macro is added to the base value of the modified parameter each time the edit is saved and loaded (see comments and assertions below for details).
Here is an example application for replicating the issue
te::Engine engine("app");
const juce::File editFile(juce::File::getCurrentWorkingDirectory().getChildFile("macros.tracktionedit"));
const float macroParameterValue = 0.3f;
const float modifierValue = 0.5f;
const float modifierOffset = 0.2f;
std::unique_ptr<te::Edit> edit;
// 1. create a new edit and add rack with a macro parameter
{
editFile.deleteFile();
edit = te::createEmptyEdit(engine, editFile);
auto rackType = edit->getRackList().addNewRack();
if (auto volumePlugin = edit->getPluginCache().createNewPlugin(te::VolumeAndPanPlugin::xmlTypeName, {})) {
// Add plugin to rack
rackType->addPlugin(volumePlugin, {}, true);
// Add macro parameter
const auto macroParameter = rackType->macroParameterList.createMacroParameter();
macroParameter->setNormalisedParameter(macroParameterValue, juce::NotificationType::sendNotification);
if (auto volumeAndPan = dynamic_cast<te::VolumeAndPanPlugin*>(volumePlugin.get())) {
auto volParam = volumeAndPan->volParam;
volParam->setNormalisedParameter(0.0f, juce::NotificationType::sendNotification);
volParam->addModifier(*macroParameter, modifierValue, modifierOffset, 0.5f);
// Run the dispatch loop so the ValueTree properties attached to the parameter are updated. (Otherwise the assertions below will fail)
// This happens implicitly in the real application.
juce::MessageManager::getInstance()->runDispatchLoopUntil(1000);
jassert(juce::approximatelyEqual(volParam->getCurrentBaseValue() , volParam->valueRange.convertFrom0to1(0.0f)));
jassert(juce::approximatelyEqual(volParam->getCurrentValue() , volParam->valueRange.convertFrom0to1(modifierOffset + modifierValue * macroParameterValue)));
jassert(juce::approximatelyEqual(volParam->getCurrentModifierValue(), volParam->valueRange.convertFrom0to1(modifierOffset + modifierValue * macroParameterValue) - volParam->getCurrentBaseValue()));
DBG(volParam->getCurrentValue()); // prints 0.35 As expected
}
}
// volume="0.35" is saved in the plugin state xml. (Similar behaviour is seen in Waveform12)
te::EditFileOperations(*edit).save(true, true, false);
}
// 2. Load previously saved edit and check the parameter value
{
edit = te::loadEditFromFile(engine, editFile);
if (auto rackType = edit->getRackList().getRackType(0)) {
if (auto volumeAndPan = dynamic_cast<te::VolumeAndPanPlugin*>(rackType->getPlugins().getFirst())) {
auto volParam = volumeAndPan->volParam;
// These assertions were OK above after the modifier is added but fail after loading the edit again from file.
jassert(juce::approximatelyEqual(volParam->getCurrentBaseValue() , volParam->valueRange.convertFrom0to1(0.0f)));
jassert(juce::approximatelyEqual(volParam->getCurrentValue() , volParam->valueRange.convertFrom0to1(modifierOffset + modifierValue * macroParameterValue)));
jassert(juce::approximatelyEqual(volParam->getCurrentModifierValue(), volParam->valueRange.convertFrom0to1(modifierOffset + modifierValue * macroParameterValue) - volParam->getCurrentBaseValue()));
// This passes: The modifier value coming from the macro modifier seems to be added to the base parameter value.
jassert(juce::approximatelyEqual(volParam->getCurrentValue(), 2.0f * volParam->valueRange.convertFrom0to1(modifierOffset + modifierValue * macroParameterValue)));
DBG(volParam->getCurrentValue());// prints 0.7. Seems like the modifier value is added again to the previous value (already modified by the macro)
}
}
// Run the dispatch loop so the ValueTree properties attached to the parameter are updated just like in a real
// application.
juce::MessageManager::getInstance()->runDispatchLoopUntil(1000);
te::EditFileOperations(*edit).save(true, true, false);
}
Waveform 12 also seems to save the parameter value taking into account the base value and the offset added by the macro parameter but does not seem to have the issue described above when the edit is loaded again.
Tried the example above with the latest commit on develop too (64229cf14) but no changes compared to the version I’m using in the actual application (bf2bf46e1).
Not sure if this is a bug or if I’m somehow using the tracktion classes incorrectly. Any help on this would be appreciated
