From db99c38a5dfaab56e6255ed28cf6f7392c1a0a27 Mon Sep 17 00:00:00 2001
From: Vito Caputo <vcaputo@pengaru.com>
Date: Mon, 3 Feb 2020 04:24:25 -0800
Subject: libs/sig: add sig_ops_lerp linear interpoplation

This takes three signals; a, b, and t

t controls the weight interpolating between a and b, they all key
off the same time ticks_ms.
---
 src/libs/sig/Makefile.am |  2 +-
 src/libs/sig/ops_lerp.c  | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/libs/sig/sig.h       |  1 +
 3 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 src/libs/sig/ops_lerp.c

(limited to 'src/libs/sig')

diff --git a/src/libs/sig/Makefile.am b/src/libs/sig/Makefile.am
index 4c41f41..7c35742 100644
--- a/src/libs/sig/Makefile.am
+++ b/src/libs/sig/Makefile.am
@@ -1,3 +1,3 @@
 noinst_LIBRARIES = libsig.a
-libsig_a_SOURCES = ops_const.c ops_mult.c ops_sin.c sig.c sig.h
+libsig_a_SOURCES = ops_const.c ops_lerp.c ops_mult.c ops_sin.c sig.c sig.h
 libsig_a_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/libs/sig/ops_lerp.c b/src/libs/sig/ops_lerp.c
new file mode 100644
index 0000000..8002803
--- /dev/null
+++ b/src/libs/sig/ops_lerp.c
@@ -0,0 +1,68 @@
+#include <assert.h>
+
+#include "sig.h"
+
+
+typedef struct ops_lerp_ctxt_t {
+	sig_t	*a, *b, *t;
+} ops_lerp_ctxt_t;
+
+
+static size_t ops_lerp_size(va_list ap)
+{
+	return sizeof(ops_lerp_ctxt_t);
+}
+
+
+/* supply two sig_t's to be multiplied, this sig_t takes
+ * ownership of them so they'll be freed by the multiplier
+ * on destroy when that sig_t is freed.
+ */
+static void ops_lerp_init(void *context, va_list ap)
+{
+	ops_lerp_ctxt_t	*ctxt = context;
+
+	assert(ctxt);
+
+	ctxt->a = va_arg(ap, sig_t *);
+	ctxt->b = va_arg(ap, sig_t *);
+	ctxt->t = va_arg(ap, sig_t *);
+}
+
+
+static inline float lerp(float a, float b, float t)
+{
+	return (1.f - t) * a + b * t;
+}
+
+
+static float ops_lerp_output(void *context, unsigned ticks_ms)
+{
+	ops_lerp_ctxt_t	*ctxt = context;
+
+	assert(ctxt);
+
+	return lerp(sig_output(ctxt->a, ticks_ms),
+		    sig_output(ctxt->b, ticks_ms),
+		    sig_output(ctxt->t, ticks_ms));
+}
+
+
+static void ops_lerp_destroy(void *context)
+{
+	ops_lerp_ctxt_t	*ctxt = context;
+
+	assert(ctxt);
+
+	sig_free(ctxt->a);
+	sig_free(ctxt->b);
+	sig_free(ctxt->t);
+}
+
+
+sig_ops_t	sig_ops_lerp = {
+	.size = ops_lerp_size,
+	.init = ops_lerp_init,
+	.destroy = ops_lerp_destroy,
+	.output = ops_lerp_output,
+};
diff --git a/src/libs/sig/sig.h b/src/libs/sig/sig.h
index f377f00..0a374f5 100644
--- a/src/libs/sig/sig.h
+++ b/src/libs/sig/sig.h
@@ -26,6 +26,7 @@ extern sig_ops_t	sig_ops_saw;
 extern sig_ops_t	sig_ops_sqr;
 */
 
+extern sig_ops_t	sig_ops_lerp;
 extern sig_ops_t	sig_ops_mult;
 
 #endif
-- 
cgit v1.2.3