comparison DPF-Prymula-audioplugins/dpf/distrho/extra/ValueSmoother.hpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
4 * Copyright (C) 2021-2023 Filipe Coelho <falktx@falktx.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any purpose with
7 * or without fee is hereby granted, provided that the above copyright notice and this
8 * permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
11 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
12 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
14 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #ifndef DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED
19 #define DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED
20
21 #include "../DistrhoUtils.hpp"
22
23 START_NAMESPACE_DISTRHO
24
25 // --------------------------------------------------------------------------------------------------------------------
26
27 /**
28 * @brief An exponential smoother for control values
29 *
30 * This continually smooths a value towards a defined target,
31 * using a low-pass filter of the 1st order, which creates an exponential curve.
32 *
33 * The length of the curve is defined by a T60 constant,
34 * which is the time it takes for a 1-to-0 smoothing to fall to -60dB.
35 *
36 * Note that this smoother has asymptotical behavior,
37 * and it must not be assumed that the final target is ever reached.
38 */
39 class ExponentialValueSmoother {
40 float coef;
41 float target;
42 float mem;
43 float tau;
44 float sampleRate;
45
46 public:
47 ExponentialValueSmoother()
48 : coef(0.f),
49 target(0.f),
50 mem(0.f),
51 tau(0.f),
52 sampleRate(0.f) {}
53
54 void setSampleRate(const float newSampleRate) noexcept
55 {
56 if (d_isNotEqual(sampleRate, newSampleRate))
57 {
58 sampleRate = newSampleRate;
59 updateCoef();
60 }
61 }
62
63 void setTimeConstant(const float newT60) noexcept
64 {
65 const float newTau = newT60 * (float)(1.0 / 6.91);
66
67 if (d_isNotEqual(tau, newTau))
68 {
69 tau = newTau;
70 updateCoef();
71 }
72 }
73
74 float getCurrentValue() const noexcept
75 {
76 return mem;
77 }
78
79 float getTargetValue() const noexcept
80 {
81 return target;
82 }
83
84 void setTargetValue(const float newTarget) noexcept
85 {
86 target = newTarget;
87 }
88
89 void clearToTargetValue() noexcept
90 {
91 mem = target;
92 }
93
94 inline float peek() const noexcept
95 {
96 return mem * coef + target * (1.f - coef);
97 }
98
99 inline float next() noexcept
100 {
101 return (mem = mem * coef + target * (1.f - coef));
102 }
103
104 private:
105 void updateCoef() noexcept
106 {
107 coef = std::exp(-1.f / (tau * sampleRate));
108 }
109 };
110
111 // --------------------------------------------------------------------------------------------------------------------
112
113 /**
114 * @brief A linear smoother for control values
115 *
116 * This continually smooths a value towards a defined target, using linear segments.
117 *
118 * The duration of the smoothing segment is defined by the given time constant.
119 * Every time the target changes, a new segment restarts for the whole duration of the time constant.
120 *
121 * Note that this smoother, unlike an exponential smoother, eventually should converge to its target value.
122 */
123 class LinearValueSmoother {
124 float step;
125 float target;
126 float mem;
127 float tau;
128 float sampleRate;
129
130 public:
131 LinearValueSmoother()
132 : step(0.f),
133 target(0.f),
134 mem(0.f),
135 tau(0.f),
136 sampleRate(0.f) {}
137
138 void setSampleRate(const float newSampleRate) noexcept
139 {
140 if (d_isNotEqual(sampleRate, newSampleRate))
141 {
142 sampleRate = newSampleRate;
143 updateStep();
144 }
145 }
146
147 void setTimeConstant(const float newTau) noexcept
148 {
149 if (d_isNotEqual(tau, newTau))
150 {
151 tau = newTau;
152 updateStep();
153 }
154 }
155
156 float getCurrentValue() const noexcept
157 {
158 return mem;
159 }
160
161 float getTargetValue() const noexcept
162 {
163 return target;
164 }
165
166 void setTargetValue(const float newTarget) noexcept
167 {
168 if (d_isNotEqual(target, newTarget))
169 {
170 target = newTarget;
171 updateStep();
172 }
173 }
174
175 void clearToTargetValue() noexcept
176 {
177 mem = target;
178 }
179
180 inline float peek() const noexcept
181 {
182 const float dy = target - mem;
183 return mem + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy);
184 }
185
186 inline float next() noexcept
187 {
188 const float y0 = mem;
189 const float dy = target - y0;
190 return (mem = y0 + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy));
191 }
192
193 private:
194 void updateStep() noexcept
195 {
196 step = (target - mem) / (tau * sampleRate);
197 }
198 };
199
200 // --------------------------------------------------------------------------------------------------------------------
201
202 END_NAMESPACE_DISTRHO
203
204 #endif // DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED