From 51a1d45cc91c84b127463a4205de415cd7b5e629 Mon Sep 17 00:00:00 2001 From: David Rowland Date: Wed, 7 Jun 2023 12:15:11 +0100 Subject: [PATCH] VolumeAndPan: Made vol/pan parameters undoable --- .../internal/tracktion_VolumeAndPan.cpp | 33 ++++-- .../plugins/internal/tracktion_VolumeAndPan.h | 5 +- .../internal/tracktion_VolumeAndPan.test.cpp | 104 ++++++++++++++++++ .../tracktion_engine_plugins.cpp | 1 + 4 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.test.cpp diff --git a/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.cpp b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.cpp index 3cecaf875a6..6da59bba417 100644 --- a/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.cpp +++ b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.cpp @@ -122,8 +122,8 @@ VolumeAndPanPlugin::VolumeAndPanPlugin (PluginCreationInfo info, bool isMasterVo addAutomatableParameter (panParam = new PanAutomatableParameter ("pan", TRANS("Pan"), *this, { -1.0f, 1.0f })); } - volParam->attachToCurrentValue (volume); - panParam->attachToCurrentValue (pan); + volParam->setParameter (volume, juce::dontSendNotification); + panParam->setParameter (pan, juce::dontSendNotification); } VolumeAndPanPlugin::VolumeAndPanPlugin (Edit& ed, const juce::ValueTree& v, bool isMaster) @@ -134,9 +134,6 @@ VolumeAndPanPlugin::VolumeAndPanPlugin (Edit& ed, const juce::ValueTree& v, bool VolumeAndPanPlugin::~VolumeAndPanPlugin() { notifyListenersOfDeletion(); - - volParam->detachFromCurrentValue(); - panParam->detachFromCurrentValue(); } juce::ValueTree VolumeAndPanPlugin::create() @@ -256,7 +253,7 @@ void VolumeAndPanPlugin::setVolumeDb (float vol) void VolumeAndPanPlugin::setSliderPos (float newV) { - volParam->setParameter (juce::jlimit (0.0f, 1.0f, newV), juce::sendNotification); + volume = juce::jlimit (0.0f, 1.0f, newV); } void VolumeAndPanPlugin::setPan (float p) @@ -264,7 +261,7 @@ void VolumeAndPanPlugin::setPan (float p) if (p >= -0.005f && p <= 0.005f) p = 0.0f; - panParam->setParameter (juce::jlimit (-1.0f, 1.0f, p), juce::sendNotification); + pan = juce::jlimit (-1.0f, 1.0f, p); } PanLaw VolumeAndPanPlugin::getPanLaw() const noexcept @@ -310,9 +307,27 @@ void VolumeAndPanPlugin::restorePluginStateFromValueTree (const juce::ValueTree& copyPropertiesToNullTerminatedCachedValues (v, cvsFloat); copyPropertiesToNullTerminatedCachedValues (v, cvsInt); copyPropertiesToNullTerminatedCachedValues (v, cvsBool); +} - for (auto p : getAutomatableParameters()) - p->updateFromAttachedValue(); +void VolumeAndPanPlugin::valueTreePropertyChanged (juce::ValueTree& v, const juce::Identifier& i) +{ + Plugin::valueTreePropertyChanged (v, i); + + if (v == state) + { + if (i == IDs::volume) + { + volume.forceUpdateOfCachedValue(); + volParam->setParameter (juce::jlimit (0.0f, 1.0f, static_cast (volume)), + juce::sendNotification); + } + else if (i == IDs::pan) + { + pan.forceUpdateOfCachedValue(); + panParam->setParameter (juce::jlimit (-1.0f, 1.0f, static_cast (pan)), + juce::sendNotification); + } + } } }} // namespace tracktion { inline namespace engine diff --git a/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.h b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.h index 8b7d72e7d88..c380ce964c0 100644 --- a/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.h +++ b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.h @@ -65,7 +65,6 @@ class VolumeAndPanPlugin : public Plugin void restorePluginStateFromValueTree (const juce::ValueTree&) override; //============================================================================== - juce::CachedValue volume, pan; juce::CachedValue applyToMidi, ignoreVca, polarity; juce::CachedValue panLaw; @@ -73,6 +72,8 @@ class VolumeAndPanPlugin : public Plugin AutomatableParameter::Ptr volParam, panParam; private: + juce::CachedValue volume, pan; + float lastGainL = 0.0f, lastGainR = 0.0f, lastGainS = 0.0f, lastVolumeBeforeMute = 0.0f; juce::CriticalSection vcaTrackLock; @@ -81,6 +82,8 @@ class VolumeAndPanPlugin : public Plugin void refreshVCATrack(); + void valueTreePropertyChanged (juce::ValueTree&, const juce::Identifier&) override; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VolumeAndPanPlugin) }; diff --git a/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.test.cpp b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.test.cpp new file mode 100644 index 00000000000..3aa7c79457e --- /dev/null +++ b/modules/tracktion_engine/plugins/internal/tracktion_VolumeAndPan.test.cpp @@ -0,0 +1,104 @@ +/* + ,--. ,--. ,--. ,--. + ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2018 + '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software + | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation + `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com + + Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details. +*/ + +#if TRACKTION_UNIT_TESTS && ENGINE_UNIT_TESTS_VOLPANPLUGIN + +namespace tracktion { inline namespace engine +{ + +//============================================================================== +//============================================================================== +class VolPanTests : public juce::UnitTest +{ +public: + VolPanTests() + : juce::UnitTest ("VolumeAndPan Plugin", "tracktion_engine") + { + } + + void runTest() override + { + runUndoTests(); + } + +private: + void runUndoTests() + { + auto& engine = *Engine::getEngines()[0]; + juce::ValueTree editState; + + beginTest ("Undo/redo"); + { + auto edit = Edit::createSingleTrackEdit (engine); + auto& um = edit->getUndoManager(); + um.setMaxNumberOfStoredUnits (30000, 30); // Ensure this isn't the default "single transaction" + um.clearUndoHistory(); + + auto p = getAudioTracks (*edit)[0]->getVolumePlugin(); + + // Starting new undo transaction + um.beginNewTransaction(); + expect (! um.canUndo()); + expect (! um.canRedo()); + + expectWithinAbsoluteError (p->getVolumeDb(), 0.0f, 0.001f); + p->setVolumeDb (-60.0f); + expectWithinAbsoluteError (p->getVolumeDb(), -60.0f, 0.001f); + expect (um.canUndo()); + + um.beginNewTransaction(); + expectWithinAbsoluteError (p->getPan(), 0.0f, 0.001f); + p->setPan (1.0f); + expectWithinAbsoluteError (p->getPan(), 1.0f, 0.001f); + expect (um.canUndo()); + + um.undo(); + expect (um.canUndo()); + expect (um.canRedo()); + + expectWithinAbsoluteError (p->getVolumeDb(), -60.0f, 0.001f); + expectWithinAbsoluteError (p->getPan(), 0.0f, 0.001f); + + um.undo(); + expect (! um.canUndo()); + expect (um.canRedo()); + + expectWithinAbsoluteError (p->getVolumeDb(), 0.0f, 0.001f); + expectWithinAbsoluteError (p->getPan(), 0.0f, 0.001f); + + um.redo(); + expect (um.canRedo()); + expectWithinAbsoluteError (p->getVolumeDb(), -60.0f, 0.001f); + expectWithinAbsoluteError (p->getPan(), 0.0f, 0.001f); + + um.redo(); + expectWithinAbsoluteError (p->getVolumeDb(), -60.0f, 0.001f); + expectWithinAbsoluteError (p->getPan(), 1.0f, 0.001f); + + edit->flushState(); + editState = edit->state; + } + + beginTest ("Load saved state"); + { + Edit edit ({ engine, editState, ProjectItemID::createNewID (0) }); + auto p = getAudioTracks (edit)[0]->getVolumePlugin(); + expectWithinAbsoluteError (p->getVolumeDb(), -60.0f, 0.001f); + expectWithinAbsoluteError (p->getPan(), 1.0f, 0.001f); + } + } +}; + +static VolPanTests volPanTests; + + +}} // namespace tracktion { inline namespace engine + +#endif diff --git a/modules/tracktion_engine/tracktion_engine_plugins.cpp b/modules/tracktion_engine/tracktion_engine_plugins.cpp index 52c904bd04e..baea2bdfec7 100644 --- a/modules/tracktion_engine/tracktion_engine_plugins.cpp +++ b/modules/tracktion_engine/tracktion_engine_plugins.cpp @@ -67,6 +67,7 @@ using namespace std::literals; #include "plugins/internal/tracktion_TextPlugin.cpp" #include "plugins/internal/tracktion_VCA.cpp" #include "plugins/internal/tracktion_VolumeAndPan.cpp" +#include "plugins/internal/tracktion_VolumeAndPan.test.cpp" #include "plugins/internal/tracktion_InternalPlugins.test.cpp" #include "plugins/effects/tracktion_Chorus.cpp"