diff --git a/TODO b/TODO
index 538752c..3374f2c 100644
--- a/TODO
+++ b/TODO
@@ -3,12 +3,12 @@
code:
* android, ios
-* debugging (design by contract?, trace calls?)
1.0.0
-----
code:
+* debugging
* check all examples again
* osc post filter (and one pole init, slew rate, etc.) val from input? set state instead?
* audio rate optional pulse width/slope inputs?
@@ -59,9 +59,10 @@ code:
* should remove bw_config?
* use custom NDEBUG?
* NULL (C) vs BW_SIZE_T (non-C)...?
+* clearly specify that state is tied to a particular set of coeffs (1:N)
build system:
-* single header generation
+* single header generation (vs modules in bwp... to think about)
post 1.0.0
----------
diff --git a/include/bw_note_queue.h b/include/bw_note_queue.h
index 8b37e97..37f00a5 100644
--- a/include/bw_note_queue.h
+++ b/include/bw_note_queue.h
@@ -125,7 +125,7 @@ static inline void bw_note_queue_add(bw_note_queue *BW_RESTRICT queue, unsigned
*
* #### bw_note_queue_add()
* ```>>> */
-static inline char bw_note_queue_is_valid(bw_note_queue *BW_RESTRICT queue);
+static inline char bw_note_queue_is_valid(const bw_note_queue *BW_RESTRICT queue);
/*! <<<```
* WRITEME
* }}} */
@@ -179,7 +179,7 @@ static inline void bw_note_queue_add(bw_note_queue *BW_RESTRICT queue, unsigned
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
}
-static inline char bw_note_queue_is_valid(bw_note_queue *BW_RESTRICT queue) {
+static inline char bw_note_queue_is_valid(const bw_note_queue *BW_RESTRICT queue) {
BW_ASSERT(queue != NULL);
if (queue->n_events >= 128 || queue->n_pressed >= 128)
diff --git a/include/bw_one_pole.h b/include/bw_one_pole.h
index 1cae903..b9e5ad7 100644
--- a/include/bw_one_pole.h
+++ b/include/bw_one_pole.h
@@ -32,6 +32,10 @@
*
* - Version 0.6.0:
*
+ * bw_one_pole_process()
and
+ * bw_one_pole_process_multi()
now use
+ * BW_SIZE_T
to count samples and channels.
+ * - Added debugging code.
* - Removed dependency on bw_config.
* - Fixed bug when setting very high cutoff values.
*
@@ -168,7 +172,7 @@ static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeff
*
* #### bw_one_pole_process()
* ```>>> */
-static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
+static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, BW_SIZE_T n_samples);
/*! <<<```
* Processes the first `n_samples` of the input buffer `x` and fills the
* first `n_samples` of the output buffer `y`, while using and updating both
@@ -178,7 +182,7 @@ static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, b
*
* #### bw_one_pole_process_multi()
* ```>>> */
-static inline void bw_one_pole_process_multi(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state **BW_RESTRICT state, const float **x, float **y, int n_channels, int n_samples);
+static inline void bw_one_pole_process_multi(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state **BW_RESTRICT state, const float **x, float **y, BW_SIZE_T n_channels, BW_SIZE_T n_samples);
/*! <<<```
* Processes the first `n_samples` of the `n_channels` input buffers `x` and
* fills the first `n_samples` of the `n_channels` output buffers `y`, while
@@ -290,6 +294,18 @@ static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT c
static inline float bw_one_pole_get_y_z1(const bw_one_pole_state *BW_RESTRICT state);
/*! <<<```
* Returns the last output sample as stored in `state`.
+ *
+ * #### bw_one_pole_coeffs_is_valid()
+ * ```>>> */
+static inline char bw_one_pole_coeffs_is_valid(const bw_one_pole_coeffs *BW_RESTRICT coeffs);
+/*! <<<```
+ * WRITEME
+ *
+ * #### bw_one_pole_state_is_valid()
+ * ```>>> */
+static inline char bw_one_pole_state_is_valid(const bw_one_pole_state *BW_RESTRICT state);
+/*! <<<```
+ * WRITEME
* }}} */
/*** Implementation ***/
@@ -299,24 +315,44 @@ static inline float bw_one_pole_get_y_z1(const bw_one_pole_state *BW_RESTRICT st
#include
-struct _bw_one_pole_coeffs {
- // Coefficients
- float Ttm2pi;
+#ifdef BW_DEBUG_DEEP
+enum _bw_one_pole_coeffs_state {
+ _bw_one_pole_coeffs_state_invalid,
+ _bw_one_pole_coeffs_state_init,
+ _bw_one_pole_coeffs_state_set_sample_rate,
+ _bw_one_pole_coeffs_state_reset_coeffs,
+};
+#endif
- float mA1u;
- float mA1d;
- float st2;
+struct _bw_one_pole_coeffs {
+#ifdef BW_DEBUG_DEEP
+ uint32_t hash;
+ enum _bw_one_pole_coeffs_state state;
+ uint32_t reset_id;
+#endif
+
+ // Coefficients
+ float Ttm2pi;
+
+ float mA1u;
+ float mA1d;
+ float st2;
// Parameters
- float cutoff_up;
- float cutoff_down;
- float sticky_thresh;
- bw_one_pole_sticky_mode sticky_mode;
- int param_changed;
+ float cutoff_up;
+ float cutoff_down;
+ float sticky_thresh;
+ bw_one_pole_sticky_mode sticky_mode;
+ int param_changed;
};
struct _bw_one_pole_state {
- float y_z1;
+#ifdef BW_DEBUG_DEEP
+ uint32_t hash;
+ uint32_t coeffs_reset_id;
+#endif
+
+ float y_z1;
};
#define _BW_ONE_POLE_PARAM_CUTOFF_UP 1
@@ -324,27 +360,36 @@ struct _bw_one_pole_state {
#define _BW_ONE_POLE_PARAM_STICKY_THRESH (1<<2)
static inline void bw_one_pole_init(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ BW_ASSERT(coeffs != NULL);
+
coeffs->cutoff_up = INFINITY;
coeffs->cutoff_down = INFINITY;
coeffs->sticky_thresh = 0.f;
coeffs->sticky_mode = bw_one_pole_sticky_mode_abs;
+
+#ifdef BW_DEBUG_DEEP
+ coeffs->hash = bw_hash_sdbm("bw_one_pole_coeffs");
+ coeffs->state = _bw_one_pole_coeffs_state_init;
+ coeffs->reset_id = coeffs->hash + 1;
+#endif
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
}
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *BW_RESTRICT coeffs, float sample_rate) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+
coeffs->Ttm2pi = -6.283185307179586f / sample_rate;
+
+#ifdef BW_DEBUG_DEEP
+ coeffs->state = _bw_one_pole_coeffs_state_set_sample_rate;
+#endif
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state == _bw_one_pole_coeffs_state_set_sample_rate);
}
-static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
- coeffs->param_changed = ~0;
- bw_one_pole_update_coeffs_ctrl(coeffs);
-}
-
-static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float y_z1) {
- (void)coeffs;
- state->y_z1 = y_z1;
-}
-
-static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+static inline void _bw_one_pole_do_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
if (coeffs->param_changed) {
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_CUTOFF_UP)
coeffs->mA1u = coeffs->cutoff_up > 1.591549430918953e8f ? 0.f : bw_expf_3(coeffs->Ttm2pi * coeffs->cutoff_up);
@@ -358,86 +403,236 @@ static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRIC
}
}
+static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_set_sample_rate);
+
+ coeffs->param_changed = ~0;
+ _bw_one_pole_do_update_coeffs_ctrl(coeffs);
+
+#ifdef BW_DEBUG_DEEP
+ coeffs->state = _bw_one_pole_coeffs_state_reset_coeffs;
+ coeffs->reset_id++;
+#endif
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state == _bw_one_pole_coeffs_state_reset_coeffs);
+}
+
+static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float y_z1) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT(bw_is_finite(y_z1));
+
+ (void)coeffs;
+ state->y_z1 = y_z1;
+
+#ifdef BW_DEBUG_DEEP
+ state->hash = bw_hash_sdbm("bw_one_pole_state");
+ state->coeffs_reset_id = coeffs->reset_id;
+#endif
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+}
+
+static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+
+ _bw_one_pole_do_update_coeffs_ctrl(coeffs);
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+}
+
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+
(void)coeffs;
}
static inline float bw_one_pole_process1(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
const float y = x + coeffs->mA1u * (state->y_z1 - x);
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
static inline float bw_one_pole_process1_sticky_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
float y = x + coeffs->mA1u * (state->y_z1 - x);
const float d = y - x;
if (d * d <= coeffs->st2)
y = x;
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
static inline float bw_one_pole_process1_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
float y = x + coeffs->mA1u * (state->y_z1 - x);
const float d = y - x;
if (d * d <= coeffs->st2 * x * x)
y = x;
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
static inline float bw_one_pole_process1_asym(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
const float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
static inline float bw_one_pole_process1_asym_sticky_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
const float d = y - x;
if (d * d <= coeffs->st2)
y = x;
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(x));
+
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
const float d = y - x;
if (d * d <= coeffs->st2 * x * x)
y = x;
state->y_z1 = y;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(bw_is_finite(y));
+
return y;
}
-static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
+static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, BW_SIZE_T n_samples) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT(n_samples == 0 || x != NULL);
+ BW_ASSERT_DEEP(!bw_has_nan(x, n_samples));
+
bw_one_pole_update_coeffs_ctrl(coeffs);
if (y != NULL) {
if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1_asym_sticky_abs(coeffs, state, x[i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1_asym_sticky_rel(coeffs, state, x[i]);
}
else {
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1_asym(coeffs, state, x[i]);
}
}
else {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1_sticky_abs(coeffs, state, x[i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1_sticky_rel(coeffs, state, x[i]);
}
else {
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[i] = bw_one_pole_process1(coeffs, state, x[i]);
}
}
@@ -445,93 +640,104 @@ static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, b
if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym_sticky_abs(coeffs, state, x[i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym_sticky_rel(coeffs, state, x[i]);
}
else {
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym(coeffs, state, x[i]);
}
}
else {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_sticky_abs(coeffs, state, x[i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_sticky_rel(coeffs, state, x[i]);
}
else {
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1(coeffs, state, x[i]);
}
}
}
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+ BW_ASSERT_DEEP(coeffs->reset_id == state->coeffs_reset_id);
+ BW_ASSERT_DEEP(!bw_has_nan(y, n_samples));
}
-static inline void bw_one_pole_process_multi(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state **BW_RESTRICT state, const float **x, float **y, int n_channels, int n_samples) {
+static inline void bw_one_pole_process_multi(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state **BW_RESTRICT state, const float **x, float **y, BW_SIZE_T n_channels, BW_SIZE_T n_samples) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_reset_coeffs);
+ //...
+
bw_one_pole_update_coeffs_ctrl(coeffs);
if (y != NULL) {
if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym_sticky_rel(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym_sticky_rel(coeffs, state[j], x[j][i]);
}
else {
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_asym(coeffs, state[j], x[j][i]);
}
}
else {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_sticky_rel(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1_sticky_rel(coeffs, state[j], x[j][i]);
}
else {
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
if (y[j] != NULL)
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
bw_one_pole_process1(coeffs, state[j], x[j][i]);
}
}
@@ -539,89 +745,187 @@ static inline void bw_one_pole_process_multi(bw_one_pole_coeffs *BW_RESTRICT coe
if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1_asym_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1_asym_sticky_rel(coeffs, state[j], x[j][i]);
}
else {
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1_asym(coeffs, state[j], x[j][i]);
}
}
else {
if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]);
else
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1_sticky_rel(coeffs, state[j], x[j][i]);
}
else {
- for (int i = 0; i < n_samples; i++)
- for (int j = 0; j < n_channels; j++)
+ for (BW_SIZE_T i = 0; i < n_samples; i++)
+ for (BW_SIZE_T j = 0; j < n_channels; j++)
bw_one_pole_process1(coeffs, state[j], x[j][i]);
}
}
}
+
+ //...
}
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
bw_one_pole_set_cutoff_up(coeffs, value);
bw_one_pole_set_cutoff_down(coeffs, value);
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
if (coeffs->cutoff_up != value) {
coeffs->cutoff_up = value;
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_UP;
}
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
if (coeffs->cutoff_down != value) {
coeffs->cutoff_down = value;
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_DOWN;
}
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
bw_one_pole_set_tau_up(coeffs, value);
bw_one_pole_set_tau_down(coeffs, value);
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
bw_one_pole_set_cutoff_up(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
// tau < 1 ns is instantaneous for any practical purpose
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ BW_ASSERT(!bw_is_nan(value));
+ BW_ASSERT(value >= 0.f);
+
bw_one_pole_set_cutoff_down(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
// as before
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ //...
+
if (coeffs->sticky_thresh != value) {
coeffs->sticky_thresh = value;
coeffs->param_changed |= _BW_ONE_POLE_PARAM_STICKY_THRESH;
}
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_sticky_mode value) {
+ BW_ASSERT(coeffs != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
+ //...
+
coeffs->sticky_mode = value;
+
+ BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
+ BW_ASSERT_DEEP(coeffs->state >= _bw_one_pole_coeffs_state_init);
}
static inline float bw_one_pole_get_y_z1(const bw_one_pole_state *BW_RESTRICT state) {
+ BW_ASSERT(state != NULL);
+ BW_ASSERT_DEEP(bw_one_pole_state_is_valid(state));
+
return state->y_z1;
}
+static inline char bw_one_pole_coeffs_is_valid(const bw_one_pole_coeffs *BW_RESTRICT coeffs) {
+ BW_ASSERT(coeffs != NULL);
+
+#ifdef BW_DEBUG_DEEP
+ if (coeffs->hash != bw_hash_sdbm("bw_one_pole_coeffs"))
+ return 0;
+#endif
+ //...
+
+ return 1;
+}
+
+static inline char bw_one_pole_state_is_valid(const bw_one_pole_state *BW_RESTRICT state) {
+ BW_ASSERT(state != NULL);
+
+#ifdef BW_DEBUG_DEEP
+ if (state->hash != bw_hash_sdbm("bw_one_pole_state"))
+ return 0;
+#endif
+
+ return bw_is_finite(state->y_z1);
+}
+
#undef _BW_ONE_POLE_PARAM_CUTOFF_UP
#undef _BW_ONE_POLE_PARAM_CUTOFF_DOWN
#undef _BW_ONE_POLE_PARAM_STICKY_THRESH