Commit b6b1abac3703fd1c39d8a1d398bcaf4ebbea253a

Thomas de Grivel 2018-08-26T11:12:23

WIP rtbuf_dynamic

diff --git a/Makefile.am b/Makefile.am
index 02ad9a7..586f800 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -71,6 +71,14 @@ include_HEADERS += \
 	rtbuf_signal_type.h
 endif
 
+lib_LTLIBRARIES += librtbuf_dynamic.la
+librtbuf_dynamic_la_LIBADD = -lm librtbuf_signal.la librtbuf.la
+librtbuf_dynamic_la_SOURCES = \
+	rtbuf_dynamic.c \
+	rtbuf_dynamic_limiter.c
+include_HEADERS += \
+	rtbuf_dynamic.h
+
 rtbuf_synth_type: rtbuf_synth_type.c rtbuf_synth.h
 	${CC} ${CFLAGS} ${CPPFLAGS} -o rtbuf_synth_type rtbuf_synth_type.c
 rtbuf_synth_type.h: rtbuf_synth_type
diff --git a/rtbuf_dynamic.c b/rtbuf_dynamic.c
new file mode 100644
index 0000000..dabf81a
--- /dev/null
+++ b/rtbuf_dynamic.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
+ *
+ * Permission to use, copy, modify, and 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.
+ */
+
+#include "rtbuf.h"
+#include "rtbuf_lib.h"
+#include "rtbuf_signal.h"
+#include "rtbuf_signal_type.h"
+#include "rtbuf_dynamic.h"
+
+s_rtbuf_lib_fun_var g_rtbuf_dynamic_limiter_var[] = {
+  { "signal"  , RTBUF_SIGNAL_TYPE },
+  { "gain"    , RTBUF_SIGNAL_TYPE },
+  { "treshold", RTBUF_SIGNAL_TYPE },
+  { "limit"   , RTBUF_SIGNAL_TYPE },
+  { "attack"  , RTBUF_SIGNAL_TYPE },
+  { "release" , RTBUF_SIGNAL_TYPE },
+  { 0, 0 } };
+
+s_rtbuf_lib_fun_out g_rtbuf_dynamic_limiter_out[] = {
+  { "signal", RTBUF_SIGNAL_TYPE },
+  { "gain"  , RTBUF_SIGNAL_SAMPLE_TYPE },
+  { 0, 0 } };
+
+const char     *rtbuf_lib_name = "dynamic";
+unsigned long   rtbuf_lib_ver = RTBUF_LIB_VER;
+s_rtbuf_lib_fun rtbuf_lib_fun[] = {
+  { "limiter", rtbuf_dynamic_limiter, rtbuf_dynamic_limiter_start, 0,
+    g_rtbuf_dynamic_limiter_var, g_rtbuf_dynamic_limiter_out },
+  { 0, 0, 0, 0, 0, 0 } };
diff --git a/rtbuf_dynamic.h b/rtbuf_dynamic.h
new file mode 100644
index 0000000..be26310
--- /dev/null
+++ b/rtbuf_dynamic.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
+ *
+ * Permission to use, copy, modify, and 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 RTBUF_DYNAMIC_H
+#define RTBUF_DYNAMIC_H
+
+#include "rtbuf_signal.h"
+
+enum {
+  RTBUF_DYNAMIC_LIMITER_VAR_SIGNAL = 0,
+  RTBUF_DYNAMIC_LIMITER_VAR_GAIN,
+  RTBUF_DYNAMIC_LIMITER_VAR_TRESHOLD,
+  RTBUF_DYNAMIC_LIMITER_VAR_LIMIT,
+  RTBUF_DYNAMIC_LIMITER_VAR_ATTACK,
+  RTBUF_DYNAMIC_LIMITER_VAR_RELEASE,
+  RTBUF_DYNAMIC_LIMITER_VAR_N
+};
+
+typedef struct rtbuf_dynamic_limiter_data {
+  t_rtbuf_signal signal;
+  t_rtbuf_signal_sample gain;
+} s_rtbuf_dynamic_limiter_data;
+
+int rtbuf_dynamic_limiter (s_rtbuf *rtb);
+int rtbuf_dynamic_limiter_start (s_rtbuf *rtb);
+
+#endif
diff --git a/rtbuf_dynamic_limiter.c b/rtbuf_dynamic_limiter.c
new file mode 100644
index 0000000..b192b28
--- /dev/null
+++ b/rtbuf_dynamic_limiter.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018 Thomas de Grivel <thoxdg@gmail.com> +33614550127
+ *
+ * Permission to use, copy, modify, and 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.
+ */
+
+#include <math.h>
+#include "rtbuf.h"
+#include "rtbuf_dynamic.h"
+
+int rtbuf_dynamic_limiter (s_rtbuf *rtb)
+{
+  s_rtbuf_signal_fun in_;
+  s_rtbuf_signal_fun g_;
+  s_rtbuf_signal_fun t_;
+  s_rtbuf_signal_fun l_;
+  s_rtbuf_signal_fun a_;
+  s_rtbuf_signal_fun r_;
+  s_rtbuf_dynamic_limiter_data *data;
+  unsigned int i = 0;
+  double *signal;
+  double s1;
+  assert(rtb);
+  assert(rtb->fun);
+  assert(rtb->data);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_SIGNAL  , &in_,
+                   &g_rtbuf_signal_sample_zero);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_GAIN    , &g_,
+                   &g_rtbuf_signal_sample_one);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_TRESHOLD, &t_,
+                   &g_rtbuf_signal_sample_half);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_LIMIT   , &l_,
+                   &g_rtbuf_signal_sample_one);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_ATTACK  , &a_,
+                   &g_rtbuf_signal_sample_one);
+  rtbuf_signal_fun(rtb, RTBUF_DYNAMIC_LIMITER_VAR_RELEASE , &r_,
+                   &g_rtbuf_signal_sample_one);
+  data = (s_rtbuf_dynamic_limiter_data*) rtb->data;
+  signal = data->signal;
+  s1 = data->signal[RTBUF_SIGNAL_SAMPLES - 1];
+  while (i < RTBUF_SIGNAL_SAMPLES) {
+    double in = in_.sample_fun(in_.signal, i);
+    double g = max(0.0, g_.sample_fun(g_.signal, i));
+    double t = max(0.0, t_.sample_fun(t_.signal, i));
+    double l = max(0.0, l_.sample_fun(l_.signal, i));
+    double a = max(0.0, a_.sample_fun(a_.signal, i));
+    double r = max(0.0, r_.sample_fun(r_.signal, i));
+    double in_g = in * g;
+    double s = in_g * data->gain;
+    double ds = s - s1;
+    if (fabs(s) >= t) {
+      double ds_max = (l - t) / (a * RTBUF_SIGNAL_SAMPLERATE);
+      if (fabs(ds) > ds_max) {
+        if (ds < 0.0)
+          s = s1 - ds_max;
+        else
+          s = s1 + ds_max;
+        data->gain = s / in_g;
+      }
+    }
+    else if (data->gain < 1.0) {
+      double dr = (t - fabs(s)) / (r * RTBUF_SIGNAL_SAMPLERATE);
+      if (ds < 0.0)
+        s -= dr;
+      else
+        s += dr;
+      data->gain = min(s / in_g, 1.0);
+    }
+    *signal++ = s1 = s;
+    i++;
+  }
+  return 0;
+}
+
+int rtbuf_dynamic_limiter_start (s_rtbuf *rtb)
+{
+  s_rtbuf_dynamic_limiter_data *data;
+  assert(rtb);
+  assert(rtb->fun);
+  assert(rtb->data);
+  assert(rtb->fun->out_bytes == sizeof(*data));
+  data = (s_rtbuf_dynamic_limiter_data*) rtb->data;
+  data->signal[RTBUF_SIGNAL_SAMPLES - 1] = 0.0;
+  data->gain = 1.0;
+  return 0;
+}