39template <
typename SmoothedValueType>
44 template <
typename T>
struct FloatTypeHelper;
49 using Type = FloatType;
55 using Type = FloatType;
59 using FloatType =
typename FloatTypeHelper<SmoothedValueType>::Type;
83 target = currentValue = newValue;
95 jassert (numSamples >= 0);
99 for (
int i = 0; i < numSamples; ++i)
100 samples[i] *= getNextSmoothedValue();
116 jassert (numSamples >= 0);
120 for (
int i = 0; i < numSamples; ++i)
132 jassert (numSamples >= 0);
136 if (buffer.getNumChannels() == 1)
138 auto*
samples = buffer.getWritePointer (0);
140 for (
int i = 0; i < numSamples; ++i)
141 samples[i] *= getNextSmoothedValue();
145 for (
auto i = 0; i < numSamples; ++i)
147 auto gain = getNextSmoothedValue();
149 for (
int channel = 0; channel < buffer.getNumChannels(); channel++)
150 buffer.setSample (channel, i, buffer.getSample (channel, i) * gain);
156 buffer.applyGain (0, numSamples, target);
162 FloatType getNextSmoothedValue()
noexcept
169 FloatType currentValue = 0;
170 FloatType target = currentValue;
184namespace ValueSmoothingTypes
223template <
typename FloatType,
typename SmoothingType = ValueSmoothingTypes::Linear>
238 jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value &&
initialValue == 0));
242 this->target = this->currentValue;
271 if (newValue == this->target)
274 if (stepsToTarget <= 0)
281 jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && newValue == 0));
283 this->target = newValue;
284 this->countdown = stepsToTarget;
303 this->currentValue = this->target;
305 return this->currentValue;
314 FloatType
skip (
int numSamples)
noexcept
316 if (numSamples >= this->countdown)
322 skipCurrentValue (numSamples);
324 this->countdown -= numSamples;
325 return this->currentValue;
339 JUCE_DEPRECATED_WITH_BODY (
void setValue (FloatType newValue,
bool force =
false)
noexcept,
352 template <typename T>
353 using LinearVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Linear>::value, void>::type;
355 template <
typename T>
356 using MultiplicativeVoid =
typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Multiplicative>::value,
void>::type;
359 template <
typename T = SmoothingType>
362 step = (this->target - this->currentValue) / (FloatType) this->countdown;
365 template <
typename T = SmoothingType>
368 step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / this->countdown);
372 template <
typename T = SmoothingType>
373 LinearVoid<T> setNextValue() noexcept
375 this->currentValue += step;
378 template <
typename T = SmoothingType>
379 MultiplicativeVoid<T> setNextValue() noexcept
381 this->currentValue *= step;
385 template <
typename T = SmoothingType>
386 LinearVoid<T> skipCurrentValue (
int numSamples)
noexcept
388 this->currentValue += step * (FloatType) numSamples;
391 template <
typename T = SmoothingType>
392 MultiplicativeVoid<T> skipCurrentValue (
int numSamples)
394 this->currentValue *= (FloatType) std::pow (step, numSamples);
398 FloatType step = FloatType();
399 int stepsToTarget = 0;
402template <
typename FloatType>
403using LinearSmoothedValue = SmoothedValue <FloatType, ValueSmoothingTypes::Linear>;
410template <
class SmoothedValueType>
411class CommonSmoothedValueTests :
public UnitTest
415 : UnitTest (
"CommonSmoothedValueTests",
"SmoothedValues")
418 void runTest()
override
420 beginTest (
"Initial state");
424 auto value =
sv.getCurrentValue();
425 expectEquals (
sv.getTargetValue(), value);
428 expectEquals (
sv.getCurrentValue(), value);
429 expect (!
sv.isSmoothing());
432 beginTest (
"Resetting");
444 expect (
sv.isSmoothing());
446 auto currentValue =
sv.getNextValue();
448 expectEquals (
sv.getCurrentValue(), currentValue);
450 expect (
sv.isSmoothing());
456 expect (!
sv.isSmoothing());
461 sv.setTargetValue (1.5f);
468 expectEquals (
sv.getCurrentValue(),
newStart);
469 expect (!
sv.isSmoothing());
472 beginTest (
"Sample rate");
477 auto numSamples = 12;
480 svTime.reset (numSamples * 2, 1.0);
482 for (
int i = 0; i < numSamples; ++i)
485 expectWithinAbsoluteError (
svSamples.getNextValue(),
491 beginTest (
"Block processing");
496 sv.setTargetValue (2.0f);
498 const auto numSamples = 15;
502 for (
int i = 0; i < numSamples; ++i)
516 result.setSample (0, i, 1.0f);
522 const AudioBuffer<float>& reference)
524 for (
int i = 0; i <
test.getNumSamples(); ++i)
525 expectWithinAbsoluteError (
test.getSample (0, i),
526 reference.getSample (0, i),
531 sv.setCurrentAndTargetValue (1.0f);
532 sv.setTargetValue (2.0f);
533 sv.applyGain (
testData.getWritePointer (0), numSamples);
537 AudioBuffer<float>
destData (1, numSamples);
538 sv.setCurrentAndTargetValue (1.0f);
539 sv.setTargetValue (2.0f);
547 sv.setCurrentAndTargetValue (1.0f);
548 sv.setTargetValue (2.0f);
558 sv.setCurrentAndTargetValue (1.0f);
559 sv.setTargetValue (2.0f);
563 for (
int i = 0; i < 15; ++i)
564 reference.add (
sv.getNextValue());
566 sv.setCurrentAndTargetValue (1.0f);
567 sv.setTargetValue (2.0f);
569 expectWithinAbsoluteError (
sv.skip (1), reference[0], 1.0e-6f);
570 expectWithinAbsoluteError (
sv.skip (1), reference[1], 1.0e-6f);
571 expectWithinAbsoluteError (
sv.skip (2), reference[3], 1.0e-6f);
573 expectWithinAbsoluteError (
sv.getCurrentValue(), reference[6], 1.0e-6f);
574 expectEquals (
sv.skip (300),
sv.getTargetValue());
575 expectEquals (
sv.getCurrentValue(),
sv.getTargetValue());
578 beginTest (
"Negative");
585 std::vector<std::pair<float, float>> ranges = { { -1.0f, -2.0f },
586 { -100.0f, -3.0f } };
588 for (
auto range : ranges)
590 auto start = range.first,
end = range.second;
592 sv.setCurrentAndTargetValue (start);
593 sv.setTargetValue (
end);
607 expectEquals (
sv.getNextValue(),
end);
608 expectEquals (
sv.getCurrentValue(),
end);
610 sv.setCurrentAndTargetValue (start);
611 sv.setTargetValue (
end);
618 expectEquals (
sv.getNextValue(), -
positiveSv.getNextValue());
Holds a resizable array of primitive or copy-by-value objects.
Array()=default
Creates an empty array.
ElementType * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
Multiplies the destination values by the source values.
A base class for the smoothed value classes.
bool isSmoothing() const noexcept
Returns true if the current value is currently being interpolated.
SmoothedValueBase()=default
Constructor.
void applyGain(FloatType *samples, int numSamples) noexcept
Applies a smoothed gain to a stream of samples S[i] *= gain.
void applyGain(AudioBuffer< FloatType > &buffer, int numSamples) noexcept
Applies a smoothed gain to a buffer.
void setCurrentAndTargetValue(FloatType newValue)
Sets the current value and the target value.
FloatType getTargetValue() const noexcept
Returns the target value towards which the smoothed value is currently moving.
FloatType getCurrentValue() const noexcept
Returns the current value of the ramp.
void applyGain(FloatType *samplesOut, const FloatType *samplesIn, int numSamples) noexcept
Computes output as a smoothed gain applied to a stream of samples.
A utility class for values that need smoothing to avoid audio glitches.
FloatType skip(int numSamples) noexcept
Skip the next numSamples samples.
FloatType getNextValue() noexcept
Compute the next value.
(void setValue(FloatType newValue, bool force=false) noexcept, { if(force) { this->setCurrentAndTargetValue(newValue);return;} setTargetValue(newValue);}) private typename std::enable_if< std::is_same< T, ValueSmoothingTypes::Multiplicative >::value, void >::type MultiplicativeVoid
THIS FUNCTION IS DEPRECATED.
SmoothedValue(FloatType initialValue) noexcept
Constructor.
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
SmoothedValue() noexcept
Constructor.
void reset(int numSteps) noexcept
Set a new ramp length directly in samples.
void setTargetValue(FloatType newValue) noexcept
Set the next value to ramp towards.
Used to indicate a linear smoothing between values.
Used to indicate a smoothing between multiplicative values.