2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
23 ==============================================================================
31 //==============================================================================
33 Utility class for logarithmically smoothed linear values.
35 Logarithmically smoothed values can be more relevant than linear ones for
36 specific cases such as algorithm change smoothing, using two of them in
39 The gradient of the logarithmic/exponential slope can be configured by
40 calling LogRampedValue::setLogParameters.
46 template <typename FloatType
>
47 class LogRampedValue
: public SmoothedValueBase
<LogRampedValue
<FloatType
>>
50 //==============================================================================
52 LogRampedValue() = default;
55 LogRampedValue (FloatType initialValue
) noexcept
57 // Visual Studio can't handle base class initialisation with CRTP
58 this->currentValue
= initialValue
;
59 this->target
= initialValue
;
62 //==============================================================================
63 /** Sets the behaviour of the log ramp.
64 @param midPointAmplitudedB Sets the amplitude of the mid point in
65 decibels, with the target value at 0 dB
66 and the initial value at -inf dB
67 @param rateOfChangeShouldIncrease If true then the ramp starts shallow
68 and gets progressively steeper, if false
69 then the ramp is initially steep and
70 flattens out as you approach the target
73 void setLogParameters (FloatType midPointAmplitudedB
, bool rateOfChangeShouldIncrease
) noexcept
75 jassert (midPointAmplitudedB
< (FloatType
) 0.0);
76 B
= Decibels::decibelsToGain (midPointAmplitudedB
);
78 increasingRateOfChange
= rateOfChangeShouldIncrease
;
81 //==============================================================================
82 /** Reset to a new sample rate and ramp length.
83 @param sampleRate The sample rate
84 @param rampLengthInSeconds The duration of the ramp in seconds
86 void reset (double sampleRate
, double rampLengthInSeconds
) noexcept
88 jassert (sampleRate
> 0 && rampLengthInSeconds
>= 0);
89 reset ((int) std::floor (rampLengthInSeconds
* sampleRate
));
92 /** Set a new ramp length directly in samples.
93 @param numSteps The number of samples over which the ramp should be active
95 void reset (int numSteps
) noexcept
97 stepsToTarget
= numSteps
;
99 this->setCurrentAndTargetValue (this->target
);
101 updateRampParameters();
104 //==============================================================================
105 /** Set a new target value.
107 @param newValue The new target value
109 void setTargetValue (FloatType newValue
) noexcept
111 if (newValue
== this->target
)
114 if (stepsToTarget
<= 0)
116 this->setCurrentAndTargetValue (newValue
);
120 this->target
= newValue
;
121 this->countdown
= stepsToTarget
;
122 source
= this->currentValue
;
124 updateRampParameters();
127 //==============================================================================
128 /** Compute the next value.
129 @returns Smoothed value
131 FloatType
getNextValue() noexcept
133 if (! this->isSmoothing())
138 temp
*= r
; temp
+= d
;
139 this->currentValue
= jmap (temp
, source
, this->target
);
141 return this->currentValue
;
144 //==============================================================================
145 /** Skip the next numSamples samples.
147 This is identical to calling getNextValue numSamples times.
150 FloatType
skip (int numSamples
) noexcept
152 if (numSamples
>= this->countdown
)
154 this->setCurrentAndTargetValue (this->target
);
158 this->countdown
-= numSamples
;
160 auto rN
= (FloatType
) std::pow (r
, numSamples
);
162 temp
+= d
* (rN
- (FloatType
) 1) / (r
- (FloatType
) 1);
164 this->currentValue
= jmap (temp
, source
, this->target
);
165 return this->currentValue
;
169 //==============================================================================
170 void updateRampParameters()
172 auto D
= increasingRateOfChange
? B
: (FloatType
) 1 - B
;
173 auto base
= ((FloatType
) 1 / D
) - (FloatType
) 1;
174 r
= std::pow (base
, (FloatType
) 2 / (FloatType
) stepsToTarget
);
175 auto rN
= std::pow (r
, (FloatType
) stepsToTarget
);
176 d
= (r
- (FloatType
) 1) / (rN
- (FloatType
) 1);
180 //==============================================================================
181 bool increasingRateOfChange
= true;
182 FloatType B
= Decibels::decibelsToGain ((FloatType
) -40);
184 int stepsToTarget
= 0;
185 FloatType temp
= 0, source
= 0, r
= 0, d
= 1;