2#include <ossia/detail/config.hpp>
5#include <ossia/detail/small_vector.hpp>
44 const T r = T(ossia::two_pi) * cutoff * dt;
45 return r / (r + T(1));
59[[nodiscard]] OSSIA_INLINE T
lag_alpha(T tau, T dt)
noexcept
61 return dt / (dt + tau);
71template <
typename T =
float>
84 OSSIA_INLINE
void reset() noexcept
91 OSSIA_INLINE
void reset(T x)
noexcept
104 [[nodiscard]] OSSIA_INLINE T
operator()(T x, T alpha)
noexcept
113 return y += alpha * (x -
y);
133template <
typename T =
float>
136 using value_type = T;
181 if(dt <= T(0)) [[unlikely]]
185 const T k = T(ossia::two_pi) * dt;
192 const T edx =
dx_filter(dx, kd / (kd + T(1)));
195 const T kc = k * cutoff;
196 return x_filter(x, kc / (kc + T(1)));
210template <
typename T =
float, std::
size_t N = 8>
213 static_assert(N >= 1,
"a moving average needs at least one sample");
215 using value_type = T;
243 [[nodiscard]] OSSIA_INLINE T operator()(T x)
noexcept
271template <
typename T =
float, std::
size_t N = 5>
274 static_assert(N >= 1,
"a median needs at least one sample");
276 using value_type = T;
300 [[nodiscard]] OSSIA_INLINE T operator()(T x)
noexcept
302 const auto begin =
sorted.begin();
307 const auto last = begin + N;
308 const auto old = std::lower_bound(begin, last,
history[
head]);
309 std::move(old + 1, last, old);
311 const auto pos = std::lower_bound(begin, last - 1, x);
312 std::move_backward(pos, last - 1, last);
317 const auto last = begin +
count;
318 const auto pos = std::lower_bound(begin, last, x);
319 std::move_backward(pos, last, last + 1);
327 const std::uint32_t n =
count;
344template <
typename Filter, std::
size_t N = 4>
347 using filter_type = Filter;
348 using value_type =
typename Filter::value_type;
365 if(
filters.size() != n) [[unlikely]]
393 template <
typename... Args>
394 OSSIA_INLINE
void operator()(value_type* v, std::size_t n, Args... args)
noexcept
397 for(std::size_t i = 0; i < n; i++)
398 v[i] =
filters[i](v[i], args...);
415 return reference + T(ossia::remainder(a - reference, T(ossia::two_pi)));
OSSIA_INLINE T lag_alpha(T tau, T dt) noexcept
Smoothing factor of a first-order lag with a given time constant.
Definition filters.hpp:59
OSSIA_INLINE T lowpass_alpha(T cutoff, T dt) noexcept
Smoothing factor of a first-order low-pass, for a sample spaced dt seconds from the previous one.
Definition filters.hpp:42
OSSIA_INLINE T unwrap_angle(T a, T reference) noexcept
Move a onto the branch closest to reference.
Definition filters.hpp:412
Simple moving average over the last N samples.
Definition filters.hpp:212
std::uint32_t count
How many entries of history are valid, saturating at N.
Definition filters.hpp:230
std::uint32_t head
Where the next sample goes in history.
Definition filters.hpp:227
std::conditional_t< std::is_same_v< T, float >, double, T > accumulator_type
Widened so that the incremental sum does not drift.
Definition filters.hpp:218
std::array< T, N > history
Chronological ring of the window contents.
Definition filters.hpp:221
OSSIA_INLINE void assign_parameters(const moving_average_filter &) noexcept
No runtime parameters: the window size is a template argument.
Definition filters.hpp:241
OSSIA_INLINE void reset() noexcept
Forget the history: the next sample restarts the filter.
Definition filters.hpp:233
accumulator_type sum
Running sum of the first count entries of the window.
Definition filters.hpp:224
Applies one independent Filter per component of a vector-valued signal.
Definition filters.hpp:346
OSSIA_INLINE void operator()(value_type *v, std::size_t n, Args... args) noexcept
Filter n components in place.
Definition filters.hpp:394
void reset() noexcept
Forget every component's history, keeping the component count.
Definition filters.hpp:377
ossia::small_vector< Filter, N > filters
One filter per component.
Definition filters.hpp:355
OSSIA_INLINE void configure() noexcept
Push the prototype's tuning onto the live filters, keeping their history.
Definition filters.hpp:370
Filter prototype
Definition filters.hpp:352
OSSIA_INLINE void ensure(std::size_t n)
Make sure there are exactly n components.
Definition filters.hpp:363
void clear() noexcept
Drop every component.
Definition filters.hpp:384
One-euro filter: a low-pass whose cutoff rises with the speed of the signal.
Definition filters.hpp:135
OSSIA_INLINE void reset() noexcept
Forget the history: the next sample restarts the filter.
Definition filters.hpp:157
T min_cutoff
Cutoff at zero speed, in Hz. Lower is smoother, and laggier.
Definition filters.hpp:139
OSSIA_INLINE void assign_parameters(const one_euro_filter &p) noexcept
Adopt p's tuning, keeping the history.
Definition filters.hpp:165
one_pole_filter< T > x_filter
Smoother for the value.
Definition filters.hpp:148
OSSIA_INLINE T operator()(T x, T dt) noexcept
Definition filters.hpp:179
T x_prev
Previous raw input.
Definition filters.hpp:154
one_pole_filter< T > dx_filter
Smoother for the derivative.
Definition filters.hpp:151
T beta
How much the speed raises the cutoff. 0 degrades to a plain low-pass.
Definition filters.hpp:142
T d_cutoff
Cutoff of the low-pass applied to the derivative itself, in Hz.
Definition filters.hpp:145
First-order low-pass. The building block for everything below.
Definition filters.hpp:73
OSSIA_INLINE void assign_parameters(const one_pole_filter &) noexcept
No runtime parameters: the coefficient is passed per-sample.
Definition filters.hpp:98
T y
Last output. Only meaningful once primed.
Definition filters.hpp:77
OSSIA_INLINE void reset(T x) noexcept
Restart the filter as if x had just been output.
Definition filters.hpp:91
OSSIA_INLINE T operator()(T x, T alpha) noexcept
Definition filters.hpp:104
OSSIA_INLINE void reset() noexcept
Forget the history: the next sample restarts the filter.
Definition filters.hpp:84
bool primed
Definition filters.hpp:81