1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

APVTS: Use atomic floats for current parameter states

This commit is contained in:
reuk 2019-12-06 17:52:58 +00:00 committed by Tom Poole
parent eb780b56b8
commit 70ddcd16e6
3 changed files with 40 additions and 18 deletions

View file

@ -4,11 +4,33 @@ JUCE breaking changes
Develop
=======
Change
------
AudioProcessorValueTreeState::getRawParameterValue now returns a
std::atomic<float>* instead of a float*.
Possible Issues
---------------
Existing code which explicitly mentions the type of the returned value, or
interacts with the dereferenced float in ways unsupported by the std::atomic
wrapper, will fail to compile. Certain evaluation-reordering compiler
optimisations may no longer be possible.
Workaround
----------
Update your code to deal with a std::atomic<float>* instead of a float*.
Rationale
---------
Returning a std::atomic<float>* allows the JUCE framework to have much stronger
guarantees about thread safety.
Change
------
Removed a workaround from the ASIOAudioIODevice::getOutputLatencyInSamples()
and ASIOAudioIODevice::getInputLatencyInSamples() methods which was adding
an arbitrary amount to the reported latencies to compensate for dodgy, old
and ASIOAudioIODevice::getInputLatencyInSamples() methods which was adding an
arbitrary amount to the reported latencies to compensate for dodgy, old
drivers.
Possible Issues
@ -17,8 +39,8 @@ Code which relied on these altered values may now behave differently.
Workaround
----------
Update your code to deal with the new, correct values reported from the
drivers directly.
Update your code to deal with the new, correct values reported from the drivers
directly.
Rationale
---------
@ -37,8 +59,8 @@ Possible Issues
AudioProcessor subclasses which have overridden the default implementations of
get/setProgramStateInformation (which simply call through to
get/setStateInformation) may be unable to load previously saved state; state
previously saved via a call to getProgramStateInformation will be presented
to setStateInformation.
previously saved via a call to getProgramStateInformation will be presented to
setStateInformation.
Workaround
----------

View file

@ -124,8 +124,8 @@ public:
return parameter.getText (normalise (value), 0);
}
float getDenormalisedValue() const { return unnormalisedValue; }
float& getRawDenormalisedValue() { return unnormalisedValue; }
float getDenormalisedValue() const { return unnormalisedValue; }
std::atomic<float>& getRawDenormalisedValue() { return unnormalisedValue; }
bool flushToTree (const Identifier& key, UndoManager* um)
{
@ -139,12 +139,12 @@ public:
if ((float) *valueProperty != unnormalisedValue)
{
ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true);
tree.setProperty (key, unnormalisedValue, um);
tree.setProperty (key, unnormalisedValue.load(), um);
}
}
else
{
tree.setProperty (key, unnormalisedValue, nullptr);
tree.setProperty (key, unnormalisedValue.load(), nullptr);
}
return true;
@ -188,7 +188,7 @@ private:
RangedAudioParameter& parameter;
ListenerList<Listener> listeners;
float unnormalisedValue{};
std::atomic<float> unnormalisedValue{};
std::atomic<bool> needsUpdate { true };
bool listenersNeedCalling { true }, ignoreParameterChangedCallbacks { false };
};
@ -355,7 +355,7 @@ RangedAudioParameter* AudioProcessorValueTreeState::getParameter (StringRef para
return nullptr;
}
float* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept
std::atomic<float>* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept
{
if (auto* p = getParameterAdapter (paramID))
return &p->getRawDenormalisedValue();
@ -791,7 +791,7 @@ struct ParameterAdapterTests : public UnitTest
adapter.setDenormalisedValue (value);
expectEquals (adapter.getDenormalisedValue(), value);
expectEquals (adapter.getRawDenormalisedValue(), value);
expectEquals (adapter.getRawDenormalisedValue().load(), value);
};
test ({ -20, -10 }, -15);
@ -1044,7 +1044,7 @@ public:
const auto value = 0.5f;
param->setValueNotifyingHost (value);
expectEquals (*proc.state.getRawParameterValue (key), value);
expectEquals (proc.state.getRawParameterValue (key)->load(), value);
}
beginTest ("After adding an APVTS::Parameter, its value is the default value");
@ -1062,7 +1062,7 @@ public:
nullptr,
nullptr));
expectEquals (*proc.state.getRawParameterValue (key), value);
expectEquals (proc.state.getRawParameterValue (key)->load(), value);
}
beginTest ("Listeners receive notifications when parameters change");
@ -1138,7 +1138,7 @@ public:
value = newValue;
expectEquals (param->getValue(), newValue);
expectEquals (*proc.state.getRawParameterValue (key), newValue);
expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);
}
beginTest ("When the parameter value is changed, custom parameter values are updated");
@ -1154,7 +1154,7 @@ public:
value = newValue;
expectEquals (paramPtr->getCurrentChoiceName(), choices[int (newValue)]);
expectEquals (*proc.state.getRawParameterValue (key), newValue);
expectEquals (proc.state.getRawParameterValue (key)->load(), newValue);
}
beginTest ("When the parameter value is changed, listeners are notified");

View file

@ -285,7 +285,7 @@ public:
Note that calling this method from within AudioProcessorValueTreeState::Listener::parameterChanged()
is not guaranteed to return an up-to-date value for the parameter.
*/
float* getRawParameterValue (StringRef parameterID) const noexcept;
std::atomic<float>* getRawParameterValue (StringRef parameterID) const noexcept;
//==============================================================================
/** A listener class that can be attached to an AudioProcessorValueTreeState.