diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DPF-Prymula-audioplugins/dpf/distrho/extra/ValueSmoother.hpp	Mon Oct 16 21:53:34 2023 +0200
@@ -0,0 +1,204 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
+ * Copyright (C) 2021-2023 Filipe Coelho <falktx@falktx.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any purpose with
+ * or without fee is hereby granted, provided that the above copyright notice and this
+ * permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED
+#define DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED
+
+#include "../DistrhoUtils.hpp"
+
+START_NAMESPACE_DISTRHO
+
+// --------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @brief An exponential smoother for control values
+ *
+ * This continually smooths a value towards a defined target,
+ * using a low-pass filter of the 1st order, which creates an exponential curve.
+ *
+ * The length of the curve is defined by a T60 constant,
+ * which is the time it takes for a 1-to-0 smoothing to fall to -60dB.
+ *
+ * Note that this smoother has asymptotical behavior,
+ * and it must not be assumed that the final target is ever reached.
+ */
+class ExponentialValueSmoother {
+    float coef;
+    float target;
+    float mem;
+    float tau;
+    float sampleRate;
+
+public:
+    ExponentialValueSmoother()
+        : coef(0.f),
+          target(0.f),
+          mem(0.f),
+          tau(0.f),
+          sampleRate(0.f) {}
+
+    void setSampleRate(const float newSampleRate) noexcept
+    {
+        if (d_isNotEqual(sampleRate, newSampleRate))
+        {
+            sampleRate = newSampleRate;
+            updateCoef();
+        }
+    }
+
+    void setTimeConstant(const float newT60) noexcept
+    {
+        const float newTau = newT60 * (float)(1.0 / 6.91);
+
+        if (d_isNotEqual(tau, newTau))
+        {
+            tau = newTau;
+            updateCoef();
+        }
+    }
+
+    float getCurrentValue() const noexcept
+    {
+        return mem;
+    }
+
+    float getTargetValue() const noexcept
+    {
+        return target;
+    }
+
+    void setTargetValue(const float newTarget) noexcept
+    {
+        target = newTarget;
+    }
+
+    void clearToTargetValue() noexcept
+    {
+        mem = target;
+    }
+
+    inline float peek() const noexcept
+    {
+        return mem * coef + target * (1.f - coef);
+    }
+
+    inline float next() noexcept
+    {
+        return (mem = mem * coef + target * (1.f - coef));
+    }
+
+private:
+    void updateCoef() noexcept
+    {
+        coef = std::exp(-1.f / (tau * sampleRate));
+    }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @brief A linear smoother for control values
+ *
+ * This continually smooths a value towards a defined target, using linear segments.
+ *
+ * The duration of the smoothing segment is defined by the given time constant.
+ * Every time the target changes, a new segment restarts for the whole duration of the time constant.
+ *
+ * Note that this smoother, unlike an exponential smoother, eventually should converge to its target value.
+ */
+class LinearValueSmoother {
+    float step;
+    float target;
+    float mem;
+    float tau;
+    float sampleRate;
+
+public:
+    LinearValueSmoother()
+        : step(0.f),
+          target(0.f),
+          mem(0.f),
+          tau(0.f),
+          sampleRate(0.f) {}
+
+    void setSampleRate(const float newSampleRate) noexcept
+    {
+        if (d_isNotEqual(sampleRate, newSampleRate))
+        {
+            sampleRate = newSampleRate;
+            updateStep();
+        }
+    }
+
+    void setTimeConstant(const float newTau) noexcept
+    {
+        if (d_isNotEqual(tau, newTau))
+        {
+            tau = newTau;
+            updateStep();
+        }
+    }
+
+    float getCurrentValue() const noexcept
+    {
+        return mem;
+    }
+
+    float getTargetValue() const noexcept
+    {
+        return target;
+    }
+
+    void setTargetValue(const float newTarget) noexcept
+    {
+        if (d_isNotEqual(target, newTarget))
+        {
+            target = newTarget;
+            updateStep();
+        }
+    }
+
+    void clearToTargetValue() noexcept
+    {
+        mem = target;
+    }
+
+    inline float peek() const noexcept
+    {
+        const float dy = target - mem;
+        return mem + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy);
+    }
+
+    inline float next() noexcept
+    {
+        const float y0 = mem;
+        const float dy = target - y0;
+        return (mem = y0 + std::copysign(std::fmin(std::abs(dy), std::abs(step)), dy));
+    }
+
+private:
+    void updateStep() noexcept
+    {
+        step = (target - mem) / (tau * sampleRate);
+    }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DISTRHO
+
+#endif // DISTRHO_VALUE_SMOOTHER_HPP_INCLUDED