diff options
author | Sander Vocke <sandervocke@gmail.com> | 2024-07-26 21:57:32 +0200 |
---|---|---|
committer | Sander Vocke <sandervocke@gmail.com> | 2024-07-27 14:54:55 +0200 |
commit | f6660bc51fe8c02ff7c3b6188e8437c67712bddf (patch) | |
tree | bb8074fcbff6f1a4a6e242941b3cf494ebe4d6cc /src | |
parent | 019d478818950f7880d2c0f80d8fc8f963e9736b (diff) |
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/curvemap.cc (renamed from src/powermap.cc) | 122 | ||||
-rw-r--r-- | src/curvemap.h | 94 | ||||
-rw-r--r-- | src/powermap.h | 76 | ||||
-rw-r--r-- | src/powermapfilter.h | 4 |
5 files changed, 172 insertions, 128 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a8bdb59..e2a2583 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,7 @@ libdg_la_SOURCES = \ $(top_srcdir)/src/midimapper.cc \ $(top_srcdir)/src/path.cc \ $(top_srcdir)/src/powerlist.cc \ - $(top_srcdir)/src/powermap.cc \ + $(top_srcdir)/src/curvemap.cc \ $(top_srcdir)/src/powermapfilter.cc \ $(top_srcdir)/src/random.cc \ $(top_srcdir)/src/sample.cc \ @@ -126,7 +126,7 @@ EXTRA_DIST = \ path.h \ platform.h \ powerlist.h \ - powermap.h \ + curvemap.h \ powermapfilter.h \ random.h \ range.h \ diff --git a/src/powermap.cc b/src/curvemap.cc index 2bb45b7..073dde4 100644 --- a/src/powermap.cc +++ b/src/curvemap.cc @@ -24,7 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "powermap.h" +#include "curvemap.h" #include <cassert> #include <cmath> @@ -32,31 +32,31 @@ namespace { -using Power = Powermap::Power; -using PowerPair = Powermap::PowerPair; +using CurveValue = CurveMap::CurveValue; +using CurveValuePair = CurveMap::CurveValuePair; -Power h00(Power x) +CurveValue h00(CurveValue x) { return (1 + 2 * x) * pow(1 - x, 2); } -Power h10(Power x) +CurveValue h10(CurveValue x) { return x * pow(1 - x, 2); } -Power h01(Power x) +CurveValue h01(CurveValue x) { return x * x * (3 - 2 * x); } -Power h11(Power x) +CurveValue h11(CurveValue x) { return x * x * (x - 1); } -Power computeValue(const Power x, const PowerPair& P0, const PowerPair& P1, - const Power m0, const Power m1) +CurveValue computeValue(const CurveValue x, const CurveValuePair& P0, const CurveValuePair& P1, + const CurveValue m0, const CurveValue m1) { const auto x0 = P0.in; const auto x1 = P1.in; @@ -74,21 +74,22 @@ Power computeValue(const Power x, const PowerPair& P0, const PowerPair& P1, } // end anonymous namespace -Powermap::Powermap() -{ - reset(); -} +constexpr std::array<CurveValuePair, 3> CurveMap::default_fixed; -Power Powermap::map(Power in) +CurveValue CurveMap::map(CurveValue in) { assert(in >= 0. && in <= 1.); + if (invert) + { + in = 1.0 - in; + } if (spline_needs_update) { updateSpline(); } - Power out; + CurveValue out; if (in < fixed[0].in) { out = shelf ? fixed[0].out @@ -113,84 +114,100 @@ Power Powermap::map(Power in) return out; } -void Powermap::reset() +void CurveMap::reset() { - setFixed0({eps, eps}); - setFixed1({.5, .5}); - setFixed2({1 - eps, 1 - eps}); - // FIXME: better false? - shelf = true; + *this = CurveMap{}; updateSpline(); } -void Powermap::setFixed0(PowerPair new_value) +void CurveMap::setFixed0(CurveValuePair new_value) { - if (fixed[0] != new_value) + auto prev = fixed[0]; + fixed[0].in = clamp(new_value.in, eps, fixed[1].in - eps); + fixed[0].out = clamp(new_value.out, eps, fixed[1].out - eps); + if (fixed[0] != prev) { spline_needs_update = true; - fixed[0].in = clamp(new_value.in, eps, fixed[1].in - eps); - fixed[0].out = clamp(new_value.out, eps, fixed[1].out - eps); } } -void Powermap::setFixed1(PowerPair new_value) +void CurveMap::setFixed1(CurveValuePair new_value) { - if (fixed[1] != new_value) + auto prev = fixed[1]; + fixed[1].in = clamp(new_value.in, fixed[0].in + eps, fixed[2].in - eps); + fixed[1].out = clamp(new_value.out, fixed[0].out + eps, fixed[2].out - eps); + if (fixed[1] != prev) { spline_needs_update = true; - fixed[1].in = clamp(new_value.in, fixed[0].in + eps, fixed[2].in - eps); - fixed[1].out = clamp(new_value.out, fixed[0].out + eps, fixed[2].out - eps); } } -void Powermap::setFixed2(PowerPair new_value) +void CurveMap::setFixed2(CurveValuePair new_value) { - if (fixed[2] != new_value) + auto prev = fixed[2]; + fixed[2].in = clamp(new_value.in, fixed[1].in + eps, 1 - eps); + fixed[2].out = clamp(new_value.out, fixed[1].out + eps, 1 - eps); + if (fixed[2] != prev) { spline_needs_update = true; - fixed[2].in = clamp(new_value.in, fixed[1].in + eps, 1 - eps); - fixed[2].out = clamp(new_value.out, fixed[1].out + eps, 1 - eps); } } -void Powermap::setShelf(bool enable) +void CurveMap::setInvert(bool enable) +{ + if (invert != enable) + { + spline_needs_update = true; + invert = enable; + } +} + +void CurveMap::setShelf(bool enable) { if (shelf != enable) { spline_needs_update = true; - this->shelf = enable; + shelf = enable; } } -PowerPair Powermap::getFixed0() const +CurveValuePair CurveMap::getFixed0() const { return fixed[0]; } -PowerPair Powermap::getFixed1() const +CurveValuePair CurveMap::getFixed1() const { return fixed[1]; } -PowerPair Powermap::getFixed2() const +CurveValuePair CurveMap::getFixed2() const { return fixed[2]; } +bool CurveMap::getInvert() const { + return invert; +} + +bool CurveMap::getShelf() const { + return shelf; +} + // This mostly followes the wikipedia article for monotone cubic splines: // https://en.wikipedia.org/wiki/Monotone_cubic_interpolation -void Powermap::updateSpline() +void CurveMap::updateSpline() { assert(0. <= fixed[0].in && fixed[0].in < fixed[1].in && fixed[1].in < fixed[2].in && fixed[2].in <= 1.); assert(0. <= fixed[0].out && fixed[0].out <= fixed[1].out && fixed[1].out <= fixed[2].out && fixed[2].out <= 1.); - Powers X = shelf ? Powers{fixed[0].in, fixed[1].in, fixed[2].in} - : Powers{0., fixed[0].in, fixed[1].in, fixed[2].in, 1.}; - Powers Y = shelf ? Powers{fixed[0].out, fixed[1].out, fixed[2].out} - : Powers{0., fixed[0].out, fixed[1].out, fixed[2].out, 1.}; + CurveValues X = shelf ? CurveValues{fixed[0].in, fixed[1].in, fixed[2].in} + : CurveValues{0., fixed[0].in, fixed[1].in, fixed[2].in, 1.}; + CurveValues Y = shelf ? CurveValues{fixed[0].out, fixed[1].out, fixed[2].out} + : CurveValues{0., fixed[0].out, fixed[1].out, fixed[2].out, 1.}; auto slopes = calcSlopes(X, Y); @@ -215,12 +232,12 @@ void Powermap::updateSpline() // This follows the monotone cubic spline algorithm of Steffen, from: // "A Simple Method for Monotonic Interpolation in One Dimension" -std::vector<float> Powermap::calcSlopes(const Powers& X, const Powers& Y) +std::vector<float> CurveMap::calcSlopes(const CurveValues& X, const CurveValues& Y) { - Powers m(X.size()); + CurveValues m(X.size()); - Powers d(X.size() - 1); - Powers h(X.size() - 1); + CurveValues d(X.size() - 1); + CurveValues h(X.size() - 1); for (std::size_t i = 0; i < d.size(); ++i) { h[i] = X[i + 1] - X[i]; @@ -245,7 +262,16 @@ std::vector<float> Powermap::calcSlopes(const Powers& X, const Powers& Y) return m; } -Power Powermap::clamp(Power in, Power min, Power max) const +CurveValue CurveMap::clamp(CurveValue in, CurveValue min, CurveValue max) const { return std::max(min, std::min(in, max)); } + +bool CurveMap::operator==(const CurveMap& other) const +{ + return getFixed0() == other.getFixed0() && + getFixed1() == other.getFixed1() && + getFixed2() == other.getFixed2() && + getShelf() == other.getShelf() && + getInvert() == other.getInvert(); +} diff --git a/src/curvemap.h b/src/curvemap.h new file mode 100644 index 0000000..926543d --- /dev/null +++ b/src/curvemap.h @@ -0,0 +1,94 @@ +/* -*- Mode: c++ -*- */ +/*************************************************************************** + * curvemap.h + * + * Fri Apr 17 23:06:12 CEST 2020 + * Copyright 2020 André Nusser + * andre.nusser@googlemail.com + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <array> +#include <vector> + +class CurveMap +{ +public: + using CurveValue = float; + using CurveValues = std::vector<CurveValue>; + + bool operator==(const CurveMap& other) const; + + struct CurveValuePair + { + CurveValue in; + CurveValue out; + + bool operator==(const CurveValuePair& other) + { + return in == other.in || out == other.out; + } + bool operator!=(const CurveValuePair& other) + { + return !(*this == other); + } + }; + + CurveValue map(CurveValue in); + void reset(); + + void setFixed0(CurveValuePair new_value); + void setFixed1(CurveValuePair new_value); + void setFixed2(CurveValuePair new_value); + void setShelf(bool enable); + + //! If enabled, inversion inverts (1 - x) the input value before mapping + //! it through the curve. + void setInvert(bool enable); + + CurveValuePair getFixed0() const; + CurveValuePair getFixed1() const; + CurveValuePair getFixed2() const; + bool getShelf() const; + bool getInvert() const; + +private: + static constexpr CurveValue eps = 1e-4; + static constexpr std::array<CurveValuePair, 3> default_fixed { + CurveValuePair {eps, eps}, + CurveValuePair {.5, .5}, + CurveValuePair {1 - eps, 1 - eps} + }; + + // input parameters (state of this class) + std::array<CurveValuePair, 3> fixed { default_fixed }; + bool shelf { true }; + bool invert { false }; + + // spline parameters (deterministically computed from the input parameters) + bool spline_needs_update { true }; + std::array<float, 5> m { 0, 0, 0, 0, 0 }; + + void updateSpline(); + std::vector<float> calcSlopes(const CurveValues& X, const CurveValues& P); + + CurveValue clamp(CurveValue in, CurveValue min, CurveValue max) const; +};
\ No newline at end of file diff --git a/src/powermap.h b/src/powermap.h deleted file mode 100644 index 3a406cc..0000000 --- a/src/powermap.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: c++ -*- */ -/*************************************************************************** - * powermap.h - * - * Fri Apr 17 23:06:12 CEST 2020 - * Copyright 2020 André Nusser - * andre.nusser@googlemail.com - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include <array> -#include <vector> - -class Powermap -{ -public: - using Power = float; - using Powers = std::vector<Power>; - struct PowerPair - { - Power in; - Power out; - - bool operator!=(const PowerPair& other) - { - return in != other.in || out != other.out; - } - }; - - Powermap(); - - Power map(Power in); - void reset(); - - void setFixed0(PowerPair new_value); - void setFixed1(PowerPair new_value); - void setFixed2(PowerPair new_value); - void setShelf(bool enable); - - PowerPair getFixed0() const; - PowerPair getFixed1() const; - PowerPair getFixed2() const; - -private: - // input parameters (state of this class) - std::array<PowerPair, 3> fixed; - bool shelf; - - // spline parameters (deterministically computed from the input parameters) - bool spline_needs_update; - std::array<float, 5> m; - const Power eps = 1e-4; - - void updateSpline(); - std::vector<float> calcSlopes(const Powers& X, const Powers& P); - - Power clamp(Power in, Power min, Power max) const; -}; diff --git a/src/powermapfilter.h b/src/powermapfilter.h index 263f809..b9dfe5b 100644 --- a/src/powermapfilter.h +++ b/src/powermapfilter.h @@ -27,7 +27,7 @@ #pragma once #include "inputfilter.h" -#include "powermap.h" +#include "curvemap.h" struct Settings; @@ -43,5 +43,5 @@ public: private: Settings& settings; - Powermap powermap; + CurveMap powermap; }; |