diff --git a/TODO b/TODO
index 22a6c9d..94ab6e0 100644
--- a/TODO
+++ b/TODO
@@ -26,6 +26,10 @@ code:
* better common config.h (less stuff maybe, or more stuff - decide)
* separate tests an examples?
* define common midi CCs for examples
+* get_y_z1, common strategy?
+* sqrt(0) and corner cases, common strategy?
+* MEM_REQ_ROUGH() macro?
+* use BW_SIZE_T, check constant types
build system:
* make makefiles handle paths with spaces etc
diff --git a/include/bw_buf.h b/include/bw_buf.h
index 7e249dc..3150f0e 100644
--- a/include/bw_buf.h
+++ b/include/bw_buf.h
@@ -29,7 +29,7 @@
*
* - Version 0.4.0:
*
- * - Added `bw_buf_add()`.
+ * - Added `bw_buf_fill()` and `bw_buf_add()`.
*
*
* - Version 0.3.0:
@@ -51,6 +51,12 @@ extern "C" {
#endif
/*! api {{{
+ * #### bw_buf_fill()
+ * ```>>> */
+static inline voide bw_buf_fill(float *dest, float k, int n_elems);
+/*! <<<```
+ * Sets the first `n_elems` in `dest` to `k`.
+ *
* #### bw_buf_add()
* ```>>> */
static inline void bw_buf_add(float *dest, const float *src, float k, int n_elems);
@@ -85,6 +91,11 @@ static inline void bw_buf_mul(float *dest, const float *src1, const float *src2,
/* 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. */
+static inline voide bw_buf_fill(float *dest, float k, int n_elems) {
+ for (int i = 0; i < n_elems; i++)
+ dest[i] = k;
+}
+
static inline void bw_buf_add(float *dest, const float *src, float k, int n_elems) {
for (int i = 0; i < n_elems; i++)
dest[i] = k + src[i];
diff --git a/include/bw_common.h b/include/bw_common.h
index 1a71bca..8e8ffd7 100644
--- a/include/bw_common.h
+++ b/include/bw_common.h
@@ -20,7 +20,7 @@
/*!
* module_type {{{ foundation }}}
- * version {{{ 0.2.0 }}}
+ * version {{{ 0.4.0 }}}
* requires {{{ bw_config }}}
* description {{{
* A common header to make sure that a bunch of basic definitions are
@@ -28,10 +28,15 @@
* }}}
* changelog {{{
*
+ * - Version 0.4.0:
+ *
+ * - Added `BW_SIZE_T`.
+ *
+ *
* - Version 0.2.0:
*
- * - Removed
BW_MALLOC
, BW_REALLOC
, and BW_FREE
.
- * - Added
BW_RESTRICT
.
+ * - Removed `BW_MALLOC`, `BW_REALLOC`, and `BW_FREE`.
+ * - Added `BW_RESTRICT`.
*
*
* - Version 0.1.0:
@@ -58,11 +63,16 @@
#include
/*! ...
*
- * #### NULL
- * If `NULL` is not defined, then `stddef.h` is `#include`d.
+ * #### NULL and BW_SIZE_T
+ * If `NULL` or `BW_SIZE_T` are not defined, then `stddef.h` is `#include`d.
+ *
+ * If `BW_SIZE_T` is not defined, the it is defined as `size_t`.
* >>> */
-#ifndef NULL
+#if !defined(NULL) || !defined(BW_SIZE_T)
# include
+# if !defined(BW_SIZE_T)
+# define BW_SIZE_T size_t
+# endif
#endif
/*! ...
*
@@ -86,7 +96,8 @@
/*! ...
*
* #### BW_RESTRICT
- * If `BW_RESTRICT` is not defined, then it is defined as `restrict` if C99 is supported.
+ * If `BW_RESTRICT` is not defined, then it is defined as `restrict` if C99
+ * is supported.
* >>> */
#ifndef BW_RESTRICT
# if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
diff --git a/include/bw_delay.h b/include/bw_delay.h
new file mode 100644
index 0000000..0f25726
--- /dev/null
+++ b/include/bw_delay.h
@@ -0,0 +1,213 @@
+/*
+ * Brickworks
+ *
+ * Copyright (C) 2023 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
+ * along with Brickworks. If not, see .
+ *
+ * File author: Stefano D'Angelo
+ */
+
+/*!
+ * module_type {{{ dsp }}}
+ * version {{{ 0.4.0 }}}
+ * requires {{{ bw_buf bw_config bw_common bw_math }}}
+ * description {{{
+ * Interpolated delay line.
+ * }}}
+ * changelog {{{
+ *
+ * - Version 0.4.0:
+ *
+ *
+ *
+ * }}}
+ */
+
+#ifndef _BW_DELAY_H
+#define _BW_DELAY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+/*! api {{{
+ * #### bw_delay_coeffs
+ * ```>>> */
+typedef struct _bw_delay_coeffs bw_delay_coeffs;
+/*! <<<```
+ * Coefficients and related.
+ *
+ * ### bw_delay_state
+ * ```>>> */
+typedef struct _bw_delay_state bw_delay_state;
+/*! <<<```
+ * Internal state and related.
+ *
+ * #### bw_delay_init()
+ * ```>>> */
+static inline void bw_delay_init(bw_delay_coeffs *BW_RESTRICT coeffs);
+/*! <<<```
+ * Initializes input parameter values in `coeffs`.
+ *
+ * #### bw_delay_set_sample_rate()
+ * ```>>> */
+static inline void bw_delay_set_sample_rate(bw_delay_coeffs *BW_RESTRICT coeffs, float sample_rate);
+/*! <<<```
+ * Sets the `sample_rate` (Hz) value in `coeffs`.
+ *
+ * ### bw_delay_mem_req()
+ * ```>>> */
+static inline BW_SIZE_T bw_delay_mem_req(bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, float max_delay);
+/*! <<<```
+ * XXX
+ *
+ * ### bw_delay_mem_set()
+ * ```>>> */
+static inline void bw_delay_mem_set(bw_delay_state *BW_RESTRICT state, void *mem);
+/*! <<<```
+ * XXX
+ *
+ * #### bw_delay_reset_coeffs()
+ * ```>>> */
+static inline void bw_delay_reset_coeffs(bw_delay_coeffs *BW_RESTRICT coeffs);
+/*! <<<```
+ * Resets coefficients in `coeffs` to assume their target values.
+ *
+ * #### bw_delay_reset_state()
+ * ```>>> */
+static inline void bw_delay_reset_state(const bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state);
+/*! <<<```
+ * Resets the given `state` to its initial values using the given `coeffs`.
+ *
+ * #### bw_delay_update_coeffs_ctrl()
+ * ```>>> */
+static inline void bw_delay_update_coeffs_ctrl(bw_delay_coeffs *BW_RESTRICT coeffs);
+/*! <<<```
+ * Triggers control-rate update of coefficients in `coeffs`.
+ *
+ * #### bw_delay_update_coeffs_audio()
+ * ```>>> */
+static inline void bw_delay_update_coeffs_audio(bw_delay_coeffs *BW_RESTRICT coeffs);
+/*! <<<```
+ * Triggers audio-rate update of coefficients in `coeffs`.
+ *
+ * #### bw_delay_process1()
+ * ```>>> */
+static inline float bw_delay_process1(const bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, float x);
+/*! <<<```
+ * Processes one input sample `x` using `coeffs`, while using and updating
+ * `state`. Returns the corresponding output sample.
+ *
+ * #### bw_env_follow_process()
+ * ```>>> */
+static inline void bw_delay_process(bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, const float *x, float *y, int 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
+ * `coeffs` and `state` (control and audio rate).
+ *
+ * #### bw_delay_set_delay()
+ * ```>>> */
+static inline void bw_delay_set_delay(bw_delay_coeffs *BW_RESTRICT coeffs, float value);
+/*! <<<```
+ * XXX
+ *
+ * Default value: `0.f`.
+ * }}} */
+
+/*** 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. */
+
+#include
+#include
+
+struct _bw_delay_coeffs {
+ // Coefficients
+ float fs;
+
+ // Parameters
+ float delay;
+};
+
+struct _bw_delay_state {
+ float *buf;
+ BW_SIZE_T len;
+ BW_SIZE_T idx;
+};
+
+static inline void bw_delay_init(bw_delay_coeffs *BW_RESTRICT coeffs) {
+ coeffs->delay = 0.f;
+}
+
+static inline void bw_delay_set_sample_rate(bw_delay_coeffs *BW_RESTRICT coeffs, float sample_rate) {
+ coeffs->fs = sample_rate;
+}
+
+static inline BW_SIZE_T bw_delay_mem_req(bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, float max_delay) {
+ return (BW_SIZE_T)bw_ceilf(coeffs->fs * max_delay) + 1;
+}
+
+static inline void bw_delay_mem_set(bw_delay_state *BW_RESTRICT state, void *mem) {
+ state->buf = (float *)mem;
+}
+
+static inline void bw_delay_reset_coeffs(bw_delay_coeffs *BW_RESTRICT coeffs) {
+}
+
+static inline void bw_delay_reset_state(const bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state) {
+ bw_buf_fill(state->buf, 0.f, size->len);
+ state->idx = 0;
+}
+
+static inline void bw_delay_update_coeffs_ctrl(bw_delay_coeffs *BW_RESTRICT coeffs) {
+}
+
+static inline void bw_delay_update_coeffs_audio(bw_delay_coeffs *BW_RESTRICT coeffs) {
+}
+
+static inline float bw_delay_process1(const bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, float x) {
+ // XXX optim, coeffs
+ const float s = coeffs->delay * coeffs->fs;
+ const float f = bw_floorf(s);
+ const float d = coeffs->delay - f;
+ const BW_SIZE_T j = (BW_SIZE_T)d;
+ const BW_SIZE_T l = (state->idx >= d ? state->idx : state->idx + state->len) - d;
+ const BW_SIZE_T h = l == state->len - 1 ? 0 : l + 1;
+ const BW_SIZE_T n = state->idx == state->len - 1 ? 0 : state->idx + 1;
+ state->buf[idx] = x;
+ const float y = state->buf[state->idx] + d * (state->buf[n] - state->buf[state->idx]);
+ state->idx = n;
+ return y;
+}
+
+static inline void bw_delay_process(bw_delay_coeffs *BW_RESTRICT coeffs, bw_delay_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
+ for (int i = 0; i < n_samples; i++)
+ y[i] = bw_delay_process1(coeffs, state, x[i];
+}
+
+static inline void bw_delay_set_delay(bw_delay_coeffs *BW_RESTRICT coeffs, float value) {
+ coeffs->delay = value;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/bw_math.h b/include/bw_math.h
index fef2005..d5e7be2 100644
--- a/include/bw_math.h
+++ b/include/bw_math.h
@@ -70,19 +70,22 @@
* }}}
* changelog {{{
*
+ * - Version 0.4.0:
+ *
+ * - Added `bw_ceilf()`.
+ *
+ *
* - Version 0.3.0:
*
- * - Added
bw_log10f_3()
, bw_pow10f_3()
,
- * bw_dB2linf_3()
, and
- * bw_lin2dBf_3()
.
- * - Fixed computation bug in
bw_sqrtf_2()
.
+ * - Added `bw_log10f_3()`, `bw_pow10f_3()`, `bw_dB2linf_3()`, and
+ * `bw_lin2dBf_3()`.
+ * - Fixed computation bug in `bw_sqrtf_2()`.
*
*
* - Version 0.2.0:
*
- * - Added
bw_sin2pif_3()
, bw_cos2pif_3()
,
- * bw_tan2pif_3()
, bw_omega_3lognr()
, and
- * bw_tanhf_3()
.
+ * - Added `bw_sin2pif_3()`, `bw_cos2pif_3()`, `bw_tan2pif_3()`,
+ * `bw_omega_3lognr()`, and `bw_tanhf_3()`.
*
*
* - Version 0.1.0:
@@ -227,9 +230,16 @@ static inline float bw_roundf(float x);
* ```>>> */
static inline float bw_floorf(float x);
/*! <<<```
- * Returns the biggest integer lower or equal than `x` (i.e., `x` is rounded
+ * Returns the biggest integer less or equal than `x` (i.e., `x` is rounded
* down).
*
+ * #### bw_ceilf()
+ * ```>>> */
+static inline float bw_ceilf(float x);
+/*! <<<```
+ * Returns the smallest integer greater or equal than `x` (i.e., `x` is
+ * rounded up).
+ *
* #### bw_rcpf_2()
* ```>>> */
static inline float bw_rcpf_2(float x);
@@ -525,6 +535,14 @@ static inline float bw_floorf(float x) {
return t.f - s.f;
}
+static inline float bw_ceilf(float x) {
+ _bw_floatint t = {.f = bw_truncf(x)}; // first bit set when t < 0
+ _bw_floatint y = {.f = x - t.f}; // first bit set when t > x
+ _bw_floatint s = {.f = 1.f};
+ s.i &= bw_signfilli32(~t.i & y.i);
+ return t.f + s.f;
+}
+
static inline float bw_rcpf_2(float x) {
_bw_floatint v = {.f = x};
v.i = 0x7ef0e840 - v.i;
diff --git a/include/bw_wah.h b/include/bw_wah.h
index 87c1bd5..10e2b2a 100644
--- a/include/bw_wah.h
+++ b/include/bw_wah.h
@@ -20,7 +20,7 @@
/*!
* module_type {{{ dsp }}}
- * version {{{ 0.3.0 }}}
+ * version {{{ 0.4.0 }}}
* requires {{{ bw_config bw_common bw_one_pole bw_math bw_svf }}}
* description {{{
* Wah effect.
@@ -29,6 +29,11 @@
* }}}
* changelog {{{
*
+ * - Version 0.4.0:
+ *
+ * - Fixed documentation for `bw_wah_state` and `bw_wah_reset_state()`.
+ *
+ *
* - Version 0.3.0:
*
* - Use bandpass SVF output rather than lowpass.
@@ -59,7 +64,7 @@ typedef struct _bw_wah_coeffs bw_wah_coeffs;
/*! <<<```
* Coefficients and related.
*
- * ### bw_svf_state
+ * ### bw_wah_state
* ```>>> */
typedef struct _bw_wah_state bw_wah_state;
/*! <<<```
@@ -77,7 +82,7 @@ static inline void bw_wah_set_sample_rate(bw_wah_coeffs *BW_RESTRICT coeffs, flo
/*! <<<```
* Sets the `sample_rate` (Hz) value in `coeffs`.
*
- * #### bw_wah_reset_state()
+ * #### bw_wah_reset_coeffs()
* ```>>> */
static inline void bw_wah_reset_coeffs(bw_wah_coeffs *BW_RESTRICT coeffs);
/*! <<<```