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;
+}