From c72994d000b974ccc7560ee748bf44b78a32bc89 Mon Sep 17 00:00:00 2001
From: David Braun <2096055+DBraun@users.noreply.github.com>
Date: Fri, 13 Dec 2024 20:38:48 -0500
Subject: [PATCH] add oneEuro filter
---
filters.lib | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/filters.lib b/filters.lib
index 9ca4dcd..90d8aff 100644
--- a/filters.lib
+++ b/filters.lib
@@ -2908,6 +2908,49 @@ dynamicSmoothing(sensitivity, baseCF, x) = f ~ _ : ! , _
};
};
+
+//-----------------`(fi.)oneEuro`----------------------------------
+// The One Euro Filter (1€ Filter) is an adaptive lowpass filter.
+// The input signal is smoothed according to an exponential
+// moving average (EMA) whose alpha value is determined
+// according to an EMA of the input's first-order derivative.
+// This kind of filter is commonly used in object-tracking,
+// not necessarily audio processing.
+//
+// #### Usage
+//
+// ```
+// _ : oneEuro(derivativeCutoff, beta, minCutoff) : _
+// ```
+//
+// Where:
+//
+// * `derivativeCutoff`: Used to filter the first derivative of the input. 1 Hz is a good default.
+// * `beta`: "Speed" parameter where higher values reduce latency. Range is [0-1].
+// * `minCutoff`: Minimum cutoff frequency in Hz. Lower values remove more jitter.
+//
+// #### References
+// *
+//------------------------------------------------------------------------
+declare oneEuro author "David Braun";
+declare oneEuro copyright "Copyright (C) 2024 by David Braun ";
+declare oneEuro license "MIT";
+oneEuro(derivativeCutoff, beta, minCutoff, x) = x : ema(adaptiveCutoff)
+with {
+ // exponential moving average that calculates its own alpha from a cutoff in Hz
+ // _ : ema(cutoff) : _
+ ema(cutoff) = tick ~ _
+ with {
+ alpha = 1.0 / (1.0 + ma.SR / (2 * ma.PI * cutoff));
+ tick(prev, y) = prev*(1-alpha) + y*alpha;
+ };
+
+ derivative = x - x';
+ derivativeFiltered = derivative : ema(derivativeCutoff);
+ adaptiveCutoff = minCutoff + beta * abs(derivativeFiltered);
+};
+
+
//===========Linkwitz-Riley 4th-order 2-way, 3-way, and 4-way crossovers=====
//
// The Linkwitz-Riley (LR) crossovers are designed to produce a fully-flat