2#include <ossia/network/dataspace/gain.hpp>
23 return std::pow(10., -db_per_s / (20. * rate));
35 void prepare(
double rate,
double fall_db_per_s = 20.)
noexcept
41 void process(
const auto* in,
int n)
noexcept
44 for(
int i = 0; i < n; i++)
45 l = std::max(
double(std::abs(in[i])), l * fall);
61 bool sine_referenced{};
63 void prepare(
double rate,
double integration = 0.3,
bool aes17 =
false)
noexcept
65 const double tau = integration / std::log(100.);
66 coef = 1. - std::exp(-1. / (tau * rate));
67 sine_referenced = aes17;
71 void process(
const auto* in,
int n)
noexcept
74 for(
int i = 0; i < n; i++)
76 const double x = in[i];
77 m += coef * (x * x - m);
82 double level()
const noexcept
84 const double r = std::sqrt(std::max(ms, 0.));
85 return sine_referenced ? r * std::numbers::sqrt2 : r;
97 static constexpr double zeta = 0.8127169864286775;
99 static constexpr double omega = 13.511933333385695;
106 void prepare(
double rate)
noexcept
112 void process(
const auto* in,
int n)
noexcept
114 double yy = y, vv = v;
116 for(
int i = 0; i < n; i++)
118 const double x = std::abs(
double(in[i]));
119 vv += (w2 * (x - yy) - d * vv) * dt;
151 static constexpr double integration_time(type t)
noexcept
153 return t == type_i ? 0.005 : 0.010;
155 static constexpr double fall_db_per_s(type t)
noexcept
157 return t == type_i ? 20. / 1.5 : 24. / 2.8;
163 type designed_type{};
165 void prepare(
double rate, type t)
noexcept
175 auto steady = [&](
double a) {
176 ppm p{.attack = a, .fall = fall};
177 return p.tone_reading(rate, 0.1);
179 auto burst = [&](
double a) {
180 ppm p{.attack = a, .fall = fall};
181 return p.tone_reading(rate, integration_time(t));
185 const double target = ossia::detail::DecibelsToLinearGain(-2.);
186 double lo = 1e-7, hi = 1.;
187 for(
int i = 0; i < 60; i++)
189 const double mid = std::sqrt(lo * hi);
190 if(burst(mid) / steady(mid) < target)
195 attack = std::sqrt(lo * hi);
196 gain = 1. / steady(attack);
199 void process(
const auto* in,
int n)
noexcept
202 for(
int i = 0; i < n; i++)
204 const double x = std::abs(
double(in[i]));
207 e += attack * (x - e);
212 double level() const noexcept {
return env * gain; }
219 const int n = std::max(1,
int(duration * rate));
221 const double w = 2. * std::numbers::pi * 5000. / rate;
222 const double cw = std::cos(w), sw = std::sin(w);
223 double re = 1., im = 0.;
224 for(
int i = 0; i < n; i++)
227 peak = std::max(peak, env);
228 const double r = re * cw - im * sw;
229 im = re * sw + im * cw;
231 if((i & 1023) == 1023)
233 const double norm = 1. / std::sqrt(re * re + im * im);
251 static constexpr int taps_per_phase = 12;
252 static constexpr int max_factor = 4;
255 std::array<std::array<double, taps_per_phase>, max_factor> coefs{};
258 std::array<double, 2 * taps_per_phase>
history{};
262 void prepare(
double rate)
noexcept
264 factor = rate < 96000. ? 4 : rate < 192000. ? 2 : 1;
269 const int len = taps_per_phase * factor;
270 const double beta = 7.865;
271 auto bessel_i0 = [](
double x) {
272 double sum = 1., term = 1.;
273 for(
int k = 1; k < 32; k++)
275 term *= (x / (2. * k)) * (x / (2. * k));
280 const double i0b = bessel_i0(beta);
281 for(
int t = 0; t < len; t++)
283 const double m = t - (len - 1) / 2.;
284 const double x = m / factor;
286 = std::abs(x) < 1e-12 ? 1. : std::sin(std::numbers::pi * x) / (std::numbers::pi * x);
287 const double r = 2. * t / (len - 1) - 1.;
288 const double win = bessel_i0(beta * std::sqrt(std::max(0., 1. - r * r))) / i0b;
289 coefs[t % factor][t / factor] = sinc * win;
293 void process(
const auto* in,
int n)
noexcept
298 for(
int i = 0; i < n; i++)
299 peak = std::max(peak, std::abs(
double(in[i])));
303 for(
int i = 0; i < n; i++)
305 pos = pos + 1 == taps_per_phase ? 0 : pos + 1;
307 const double* h =
history.data() + pos + 1;
308 for(
int ph = 0; ph < factor; ph++)
311 const auto& c = coefs[ph];
312 for(
int k = 0; k < taps_per_phase; k++)
314 peak = std::max(peak, std::abs(acc));
327 double lr{}, ll{}, rr{};
330 void prepare(
double rate,
double integration = 0.3)
noexcept
332 const double tau = integration / std::log(100.);
333 coef = 1. - std::exp(-1. / (tau * rate));
337 void process(
const auto* l,
const auto* r,
int n)
noexcept
339 double a = lr, b = ll, c = rr;
340 for(
int i = 0; i < n; i++)
342 const double x = l[i], y = r[i];
343 a += coef * (x * y - a);
344 b += coef * (x * x - b);
345 c += coef * (y * y - c);
352 double value()
const noexcept
354 const double d = std::sqrt(ll * rr);
355 return d > 1e-12 ? std::clamp(lr / d, -1., 1.) : 0.;
366 double hold_frames{};
368 double fall_per_frame{};
370 void prepare(
double rate,
double hold_s = 1.5,
double fall_db_per_s = 20.)
noexcept
372 hold_frames = hold_s * rate;
378 void feed(
double level,
int frames)
noexcept
387 if(since > hold_frames)
388 value = std::max(level, value * std::pow(fall_per_frame, frames));
double fall_coefficient(double db_per_s, double rate) noexcept
Per-sample factor of an exponential fall of db_per_s decibels per second.
Definition meters.hpp:21
Definition meters.hpp:326
Definition meters.hpp:364
Definition meters.hpp:139
double designed_rate
The design the coefficients were computed for: preparing again for the same one only clears the envel...
Definition meters.hpp:162
double tone_reading(double rate, double duration) noexcept
Highest reading reached during a 5 kHz unit sine lasting duration.
Definition meters.hpp:215
Definition meters.hpp:250
std::array< double, 2 *taps_per_phase > history
The last taps_per_phase samples, stored twice so that the newest ones are always contiguous: history[...
Definition meters.hpp:258
static constexpr double omega
300 ms to 99% of a step, for that damping
Definition meters.hpp:99
static constexpr double sine_average_to_rms
Full-wave average of a sine to its RMS value: pi / (2 sqrt(2)).
Definition meters.hpp:101