summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-06-19 00:28:43 +0200
committerRobin Gareus <robin@gareus.org>2017-06-21 18:12:01 +0200
commite91b80eb85452586f226f4b7eb84d8be36ea1a3c (patch)
treeca8d4445d5b886f12c8d9611b090a76f8c9c365c /libs/pbd
parent9f37396315d0ff2ca063679f85b9cc0b778da86b (diff)
Centralize control-parameter math functions in libpbd.
Functions formerly in ardour/util.h and some more functions. The main motivation is libevoral which can use libpbd but not libardour. The eventual goal is to consolidate various different interpolation, scaling and deflection methods.
Diffstat (limited to 'libs/pbd')
-rw-r--r--libs/pbd/pbd/control_math.h105
1 files changed, 105 insertions, 0 deletions
diff --git a/libs/pbd/pbd/control_math.h b/libs/pbd/pbd/control_math.h
new file mode 100644
index 0000000000..8ead1c918a
--- /dev/null
+++ b/libs/pbd/pbd/control_math.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 1999 Paul Davis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __pbd_control_math_h__
+#define __pbd_control_math_h__
+
+#include <assert.h>
+#include <math.h>
+
+/* map gain-coeff [0..2] to position [0..1] */
+static inline double
+gain_to_position (double g)
+{
+ if (g == 0) {
+ return 0;
+ }
+ return pow ((6.0 * log (g) / log (2.0) + 192.0) / 198.0, 8.0);
+}
+
+/* map position [0..1] to gain-coeff [0..2] */
+static inline double
+position_to_gain (double pos)
+{
+ if (pos == 0.0) {
+ return 0.0;
+ }
+ return exp (((pow (pos, 1.0 / 8.0) * 198.0) - 192.0) / 6.0 * log (2.0));
+}
+
+/* map position [0..1] to parameter [lower..upper] on a logarithmic scale */
+static inline double
+position_to_logscale (double pos, double lower, double upper)
+{
+ assert (upper > lower && lower * upper > 0);
+ assert (pos >= 0.0 && pos <= 1.0);
+ return lower * pow (upper / lower, pos);
+}
+
+/* map parameter [lower..upper] to position [0..1] on a logarithmic scale*/
+static inline double
+logscale_to_position (double val, double lower, double upper)
+{
+ assert (upper > lower && lower * upper > 0);
+ assert (val >= lower && val <= upper);
+ return log (val / lower) / log (upper / lower);
+}
+
+static inline double
+logscale_to_position_with_steps (double val, double lower, double upper, uint32_t steps)
+{
+ assert (steps > 1);
+ double v = logscale_to_position (val, lower, upper) * (steps - 1.0);
+ return round (v) / (steps - 1.0);
+}
+
+static inline double
+position_to_logscale_with_steps (double pos, double lower, double upper, uint32_t steps)
+{
+ assert (steps > 1);
+ double p = round (pos * (steps - 1.0)) / (steps - 1.0);
+ return position_to_logscale (p, lower, upper);
+}
+
+
+static inline double
+interpolate_linear (double from, double to, double fraction)
+{
+ return from + (fraction * (to - from));
+}
+
+static inline double
+interpolate_logarithmic (double from, double to, double fraction, double lower, double upper)
+{
+ // this is expensive -- optimize
+ double l0 = logscale_to_position (from, lower, upper);
+ double l1 = logscale_to_position (to, lower, upper);
+ return position_to_logscale (l0 + fraction * (l1 - l0), lower, upper);
+}
+
+static inline double
+interpolate_gain (double from, double to, double fraction, double upper)
+{
+ // this is expensive -- optimize
+ double g0 = gain_to_position (from * 2. / upper);
+ double g1 = gain_to_position (to * 2. / upper);
+ return position_to_gain (g0 + fraction * (g1 - g0)) * upper / 2.;
+}
+
+#endif