Dusk Audio Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
daf
extra
ValueSmoother.hpp
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 DAF_VALUE_SMOOTHER_HPP_INCLUDED
19
#define DAF_VALUE_SMOOTHER_HPP_INCLUDED
20
21
#include "../DafUtils.hpp"
22
23
START_NAMESPACE_DAF
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), 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), step), dy));
191
}
192
193
private
:
194
void
updateStep()
noexcept
195
{
196
step = std::abs(target - mem) / (tau * sampleRate);
197
}
198
};
199
200
// --------------------------------------------------------------------------------------------------------------------
201
202
END_NAMESPACE_DAF
203
204
#endif
// DAF_VALUE_SMOOTHER_HPP_INCLUDED
END_NAMESPACE_DAF
#define END_NAMESPACE_DAF
Definition
DafInfo.hpp:996
START_NAMESPACE_DAF
#define START_NAMESPACE_DAF
Definition
DafInfo.hpp:990
Generated by
1.18.0