diff --git a/include/bw_slew_lim.h b/include/bw_slew_lim.h
index 3edca45..4006030 100644
--- a/include/bw_slew_lim.h
+++ b/include/bw_slew_lim.h
@@ -28,7 +28,7 @@
*
* - Version 0.2.0:
*
- * - Refactored API to avoid dynamic memory allocation.
+ * - Refactored API.
*
*
* - Version 0.1.0:
@@ -47,66 +47,63 @@
extern "C" {
#endif
+#include
+
/*! api {{{
- * #### bw_slew_lim
+ * #### bw_slew_lim_coeffs
* ```>>> */
-typedef struct _bw_slew_lim bw_slew_lim;
+typedef struct _bw_slew_lim_coeffs bw_slew_lim_coeffs;
/*! <<<```
- * Instance object.
+ * Coefficients.
+ *
+ * ### bw_slew_lim_state
* >>> */
-
-/*! ...
+typedef struct _bw_slew_lim_state bw_slew_lim_state;
+/*! <<<```
+ * State.
+ *
* #### bw_slew_lim_init()
* ```>>> */
-void bw_slew_lim_new(bw_slew_lim *instance);
+static inline void bw_slew_lim_init(bw_slew_lim_coeffs *BW_RESTRICT coeffs);
/*! <<<```
- * Initializes the `instance` object.
- * >>> */
-
-/*! ...
+ * Initializes `coeffs`.
+ *
* #### bw_slew_lim_set_sample_rate()
* ```>>> */
-void bw_slew_lim_set_sample_rate(bw_slew_lim *instance, float sample_rate);
+static inline void bw_slew_lim_set_sample_rate(bw_slew_lim_coeffs *BW_RESTRICT coeffs, float sample_rate);
/*! <<<```
- * Sets the `sample_rate` (Hz) value for the given `instance`.
+ * Sets the `sample_rate` (Hz) value for the given `coeffs`.
+ *
+ * #### bw_slew_lim_reset_state()
+ * ```>>> */
+static inline void bw_slew_lim_reset_state(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float y_z1);
+/*! <<<```
+ * Resets the given `state` to the initial state using the given `coeffs`.
* >>> */
-/*! ...
- * #### bw_slew_lim_reset()
- * ```>>> */
-void bw_slew_lim_reset(bw_slew_lim *instance);
-/*! <<<```
- * Resets the given `instance` to its initial state.
- * >>> */
+static inline void bw_slew_lim_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs);
+
+static inline void bw_slew_lim_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs);
+static inline void bw_slew_lim_update_coeffs_audio(bw_one_pole_coeffs *BW_RESTRICT coeffs);
+
+static inline float bw_slew_lim_process1(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x);
+static inline float bw_slew_lim_process1_up(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x);
+static inline float bw_slew_lim_process1_down(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x);
/*! ...
* #### bw_slew_lim_process()
* ```>>> */
-void bw_slew_lim_process(bw_slew_lim *instance, const float* x, float* y, int n_samples);
+static inline void bw_slew_lim_process(bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
/*! <<<```
* Lets the given `instance` process `n_samples` samples from the input
* buffer `x` and fills the corresponding `n_samples` samples in the output
* buffer `y`.
* >>> */
-/*! ...
- * #### bw_slew_lim_set_init_val()
- * ```>>> */
-void bw_slew_lim_set_init_val(bw_slew_lim *instance, float value);
-/*! <<<```
- * Sets the initial/quiescent `value` for the given `instance`.
- *
- * In practice, when processing the first buffer after a reset, the past
- * input and output are both assumed to have virtually been constant and of
- * the specified `value`.
- *
- * Default value: `0.f`.
- * >>> */
-
/*! ...
* #### bw_slew_lim_set_max_rate()
* ```>>> */
-void bw_slew_lim_set_max_rate(bw_slew_lim *instance, float value);
+static inline void bw_slew_lim_set_max_rate(bw_slew_lim *BW_RESTRICT coeffs, float value);
/*! <<<```
* Sets both the maximum increasing and decreasing variation rate to the
* given `value` (1/s) for the given `instance`.
@@ -121,9 +118,9 @@ void bw_slew_lim_set_max_rate(bw_slew_lim *instance, float value);
* >>> */
/*! ...
- * #### bw_slew_lim_set_max_inc_rate()
+ * #### bw_slew_lim_set_max_rate_up()
* ```>>> */
-void bw_slew_lim_set_max_inc_rate(bw_slew_lim *instance, float value);
+static inline void bw_slew_lim_set_max_rate_up(bw_slew_lim *BW_RESTRICT coeffs, float value);
/*! <<<```
* Sets the maximum increasing variation rate to the given `value` (1/s) for
* the given `instance`.
@@ -137,7 +134,7 @@ void bw_slew_lim_set_max_inc_rate(bw_slew_lim *instance, float value);
/*! ...
* #### bw_slew_lim_set_max_inc_rate()
* ```>>> */
-void bw_slew_lim_set_max_dec_rate(bw_slew_lim *instance, float value);
+static inline void bw_slew_lim_set_max_rate_down(bw_slew_lim *BW_RESTRICT coeffs, float value);
/*! <<<```
* Sets the maximum decreasing variation rate to the given `value` (1/s) for
* the given `instance`.
@@ -148,23 +145,111 @@ void bw_slew_lim_set_max_dec_rate(bw_slew_lim *instance, float value);
* Default value: `INFINITY`.
* }}} */
-/* WARNING: the internal definition of this struct is not part of the public
- * API. Its content may change at any time in future versions. Please, do not
- * access its members directly. */
-struct _bw_slew_lim {
+static inline float bw_slew_lim_get_y_z1(const bw_slew_lim_state *BW_RESTRICT state);
+
+/*** Implementation ***/
+
+/* WARNING: This part of the file is not part of the public API. Its content may
+ * change at any time in future versions. Please, do not use it directly. */
+
+struct _bw_slew_lim_coeffs {
// Coefficients
float T;
- // Parameters
- float init_val;
- float max_inc_rate;
- float max_dec_rate;
+ float max_inc;
+ float max_dec;
+ // Parameters
+ float max_rate_up;
+ float max_rate_down;
+};
+
+struct _bw_slew_lim_state {
// State
- char first_run;
float y_z1;
};
+static inline void bw_slew_lim_init(bw_slew_lim_coeffs *BW_RESTRICT coeffs) {
+ coeffs->init_val = 0.f;
+ coeffs->max_inc = INFINITY;
+ coeffs->max_dec = INFINITY;
+}
+
+static inline void bw_slew_lim_set_sample_rate(bw_slew_lim_coeffs *BW_RESTRICT coeffs, float sample_rate) {
+ coeffs->T = 1.f / sample_rate;
+}
+
+static inline void bw_slew_lim_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ bw_one_pole_update_coeffs_ctrl(coeffs);
+}
+
+static inline void bw_slew_lim_reset_state(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float y_z1) {
+ state->y_z1 = y_z1;
+}
+
+static inline void bw_slew_lim_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ // tracking parameter changes is more trouble than it's worth
+ coeffs->max_inc = coeffs->T * coeffs->max_rate_up;
+ coeffs->max_dec = coeffs->T * coeffs->max_rate_down;
+}
+
+static inline void bw_slew_lim_update_coeffs_audio(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+}
+
+static inline float bw_slew_lim_process1(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x) {
+ float y = bw_clipf(x, state->y_z1 - coeffs->max_dec, state->y_z1 + coeffs->max_inc);
+ state->y_z1 = y;
+ return y;
+}
+
+static inline float bw_slew_lim_process1_up(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x) {
+ float y = bw_minf(x, state->y_z1 + coeffs->max_inc);
+ state->y_z1 = y;
+ return y;
+}
+
+static inline float bw_slew_lim_process1_down(const bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, float x) {
+ float y = bw_maxf(x, state->y_z1 - coeffs->max_dec);
+ state->y_z1 = y;
+ return y;
+}
+
+static inline void bw_slew_lim_process(bw_slew_lim_coeffs *BW_RESTRICT coeffs, bw_slew_lim_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
+ bw_slew_lim_update_coeffs_ctrl(coeffs);
+ if (instance->max_rate_up != INFINITY) {
+ if (instance->max_rate_down != INFINITY)
+ for (int i = 0; i < n_samples; i++)
+ y[i] = bw_slew_lim_process1(coeffs, state, x[i]);
+ else
+ for (int i = 0; i < n_samples; i++)
+ y[i] = bw_slew_lim_process1_up(coeffs, state, x[i]);
+ } else {
+ if (instance->max_rate_down != INFINITY)
+ for (int i = 0; i < n_samples; i++)
+ y[i] = bw_slew_lim_process1_down(coeffs, state, x[i]);
+ else
+ for (int i = 0; i < n_samples; i++)
+ y[i] = x[i];
+ }
+}
+
+static inline void bw_slew_lim_set_max_rate(bw_slew_lim *BW_RESTRICT coeffs, float value) {
+ bw_slew_lim_set_max_rate_up(coeffs, value);
+ bw_slew_lim_set_max_rate_down(coeffs, value);
+}
+
+static inline void bw_slew_lim_set_max_rate_up(bw_slew_lim *BW_RESTRICT coeffs, float value) {
+ coeffs->max_rate_up = value;
+}
+
+static inline void bw_slew_lim_set_max_rate_down(bw_slew_lim *BW_RESTRICT coeffs, float value) {
+ coeffs->max_rate_down = value;
+}
+
+static inline float bw_slew_lim_get_y_z1(const bw_slew_lim_state *BW_RESTRICT state) {
+ return state->y_z1;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/bw_slew_lim.c b/src/bw_slew_lim.c
deleted file mode 100644
index ed69b27..0000000
--- a/src/bw_slew_lim.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Brickworks
- *
- * Copyright (C) 2022 Orastron Srl unipersonale
- *
- * Brickworks 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, version 3 of the License.
- *
- * Brickworks 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
- *
- * File author: Stefano D'Angelo
- */
-
-#include
-
-#include
-
-void bw_slew_lim_init(bw_slew_lim *instance) {
- instance->init_val = 0.f;
- instance->max_inc = INFINITY;
- instance->max_dec = INFINITY;
-}
-
-void bw_slew_lim_set_sample_rate(bw_slew_lim *instance, float sample_rate) {
- instance->T = 1.f / sample_rate;
-}
-
-void bw_slew_lim_reset(bw_slew_lim *instance) {
- instance->first_run = 1;
- instance->param_changed = ~0;
-}
-
-void bw_slew_lim_process(bw_slew_lim *instance, const float* x, float* y, int n_samples) {
- if (instance->first_run) {
- instance->y_z1 = instance->init_val;
- instance->first_run = 0;
- }
-
- if (instance->max_inc_rate != INFINITY) {
- const float max_inc = instance->T * instance->max_inc_rate;
- if (instance->max_dec_rate != INFINITY) {
- const float max_dec = instance->T * instance->max_dec_rate;
- for (int i = 0; i < n_samples; i++) {
- y[i] = bw_clipf(x[i], instance->y_z1 - max_dec, instance->y_z1 + max_inc);
- instance->y_z1 = y[i];
- }
- } else {
- for (int i = 0; i < n_samples; i++) {
- y[i] = bw_minf(x[i], instance->y_z1 + max_inc);
- instance->y_z1 = y[i];
- }
- }
- } else {
- if (instance->max_dec_rate != INFINITY) {
- const float max_dec = instance->T * instance->max_dec_rate;
- for (int i = 0; i < n_samples; i++) {
- y[i] = bw_maxf(x[i], instance->y_z1 - max_dec);
- instance->y_z1 = y[i];
- }
- } else {
- for (int i = 0; i < n_samples; i++) {
- y[i] = x[i];
- instance->y_z1 = y[n_samples - 1];
- }
- }
-}
-
-void bw_slew_lim_set_init_val(bw_slew_lim *instance, float value) {
- instance->init_val = value;
-}
-
-void bw_slew_lim_set_max_rate(bw_slew_lim *instance, float value) {
- instance->max_inc_rate = value;
- instance->max_dec_rate = value;
-}
-
-void bw_slew_lim_set_max_inc_rate(bw_slew_lim *instance, float value) {
- instance->max_inc_rate = value;
-}
-
-void bw_slew_lim_set_max_dec_rate(bw_slew_lim *instance, float value) {
- instance->max_dec_rate = value;
-}