introduced BW_NULL

This commit is contained in:
Stefano D'Angelo 2024-01-02 11:20:52 +01:00
parent 4ee0c0d0cc
commit 2ba9b443c1
58 changed files with 2086 additions and 1812 deletions

View File

@ -11,7 +11,7 @@ You can find information and documentation [on the official web page](https://ww
## Legal ## Legal
Copyright (C) 2021-2023 Orastron Srl unipersonale. Copyright (C) 2021-2024 Orastron Srl unipersonale.
Authors: Stefano D'Angelo, Paolo Marrone. Authors: Stefano D'Angelo, Paolo Marrone.

View File

@ -1,5 +1,8 @@
We wish to thank and give credit to: We wish to thank and give credit to:
- the adopters of this software, of which at the moment we can only publicly mention our friends at [Elk Audio](https://www.elk.audio/); - the adopters of this software, of which at the moment we can publicly mention, in alphabetical order:
- [Elk Audio](https://www.elk.audio/);
- [Faselunare](http://faselunare.com/);
- Kevin Molcard for finding compilation warnings that needed fixing in Brickworks 1.0.0;
- users participating to [this thread on the KVR Audio forum](https://www.kvraudio.com/forum/viewtopic.php?f=33&t=589519) for providing useful feedback; - users participating to [this thread on the KVR Audio forum](https://www.kvraudio.com/forum/viewtopic.php?f=33&t=589519) for providing useful feedback;
- [Mads Kjeldgaard](https://madskjeldgaard.dk/) for publishing [instructions to build for the Daisy Seed and uploading the firmware](https://madskjeldgaard.dk/posts/daisy-setup/); - [Mads Kjeldgaard](https://madskjeldgaard.dk/) for publishing [instructions to build for the Daisy Seed and uploading the firmware](https://madskjeldgaard.dk/posts/daisy-setup/);
- [Hereket](https://hereket.github.io/) for providing instructions on [how to build an Android app without Android Studio or Gradle](https://hereket.github.io/posts/android_from_command_line/); - [Hereket](https://hereket.github.io/) for providing instructions on [how to build an Android app without Android Studio or Gradle](https://hereket.github.io/posts/android_from_command_line/);

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_lp1 bw_math bw_one_pole }}} * requires {{{ bw_common bw_lp1 bw_math bw_one_pole }}}
* description {{{ * description {{{
* First-order allpass filter (90° shift at cutoff, approaching 180° shift * First-order allpass filter (90° shift at cutoff, approaching 180° shift
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_ap1_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_ap1_reset_state_multi()</code> and updated C++
@ -149,7 +154,7 @@ static inline void bw_ap1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_ap1_update_coeffs_ctrl() * #### bw_ap1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -263,8 +268,8 @@ static inline char bw_ap1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_ap1_state`. * than or equal to that of `bw_ap1_state`.
@ -317,7 +322,7 @@ struct bw_ap1_state {
static inline void bw_ap1_init( static inline void bw_ap1_init(
bw_ap1_coeffs * BW_RESTRICT coeffs) { bw_ap1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_lp1_init(&coeffs->lp1_coeffs); bw_lp1_init(&coeffs->lp1_coeffs);
@ -333,7 +338,7 @@ static inline void bw_ap1_init(
static inline void bw_ap1_set_sample_rate( static inline void bw_ap1_set_sample_rate(
bw_ap1_coeffs * BW_RESTRICT coeffs, bw_ap1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -349,7 +354,7 @@ static inline void bw_ap1_set_sample_rate(
static inline void bw_ap1_reset_coeffs( static inline void bw_ap1_reset_coeffs(
bw_ap1_coeffs * BW_RESTRICT coeffs) { bw_ap1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_set_sample_rate);
@ -367,10 +372,10 @@ static inline float bw_ap1_reset_state(
const bw_ap1_coeffs * BW_RESTRICT coeffs, const bw_ap1_coeffs * BW_RESTRICT coeffs,
bw_ap1_state * BW_RESTRICT state, bw_ap1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0); const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0);
@ -394,18 +399,18 @@ static inline void bw_ap1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_ap1_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_ap1_reset_state(coeffs, state[i], x_0[i]);
else else
@ -414,12 +419,12 @@ static inline void bw_ap1_reset_state_multi(
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_ap1_update_coeffs_ctrl( static inline void bw_ap1_update_coeffs_ctrl(
bw_ap1_coeffs * BW_RESTRICT coeffs) { bw_ap1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
@ -431,7 +436,7 @@ static inline void bw_ap1_update_coeffs_ctrl(
static inline void bw_ap1_update_coeffs_audio( static inline void bw_ap1_update_coeffs_audio(
bw_ap1_coeffs * BW_RESTRICT coeffs) { bw_ap1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
@ -445,10 +450,10 @@ static inline float bw_ap1_process1(
const bw_ap1_coeffs * BW_RESTRICT coeffs, const bw_ap1_coeffs * BW_RESTRICT coeffs,
bw_ap1_state * BW_RESTRICT state, bw_ap1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ap1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -469,14 +474,14 @@ static inline void bw_ap1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ap1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_ap1_update_coeffs_ctrl(coeffs); bw_ap1_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -497,17 +502,17 @@ static inline void bw_ap1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -528,7 +533,7 @@ static inline void bw_ap1_process_multi(
static inline void bw_ap1_set_cutoff( static inline void bw_ap1_set_cutoff(
bw_ap1_coeffs * BW_RESTRICT coeffs, bw_ap1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -543,7 +548,7 @@ static inline void bw_ap1_set_cutoff(
static inline void bw_ap1_set_prewarp_at_cutoff( static inline void bw_ap1_set_prewarp_at_cutoff(
bw_ap1_coeffs * BW_RESTRICT coeffs, bw_ap1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init);
@ -556,7 +561,7 @@ static inline void bw_ap1_set_prewarp_at_cutoff(
static inline void bw_ap1_set_prewarp_freq( static inline void bw_ap1_set_prewarp_freq(
bw_ap1_coeffs * BW_RESTRICT coeffs, bw_ap1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -570,7 +575,7 @@ static inline void bw_ap1_set_prewarp_freq(
static inline char bw_ap1_coeffs_is_valid( static inline char bw_ap1_coeffs_is_valid(
const bw_ap1_coeffs * BW_RESTRICT coeffs) { const bw_ap1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ap1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ap1_coeffs"))
@ -585,17 +590,17 @@ static inline char bw_ap1_coeffs_is_valid(
static inline char bw_ap1_state_is_valid( static inline char bw_ap1_state_is_valid(
const bw_ap1_coeffs * BW_RESTRICT coeffs, const bw_ap1_coeffs * BW_RESTRICT coeffs,
const bw_ap1_state * BW_RESTRICT state) { const bw_ap1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_ap1_state")) if (state->hash != bw_hash_sdbm("bw_ap1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : NULL, &state->lp1_state); return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : BW_NULL, &state->lp1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole bw_svf }}} * requires {{{ bw_common bw_math bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Second-order allpass filter (180° shift at cutoff, approaching 360° shift * Second-order allpass filter (180° shift at cutoff, approaching 360° shift
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_ap2_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_ap2_reset_state_multi()</code> and updated C++
@ -146,7 +151,7 @@ static inline void bw_ap2_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_ap2_update_coeffs_ctrl() * #### bw_ap2_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -272,8 +277,8 @@ static inline char bw_ap2_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_ap2_state`. * than or equal to that of `bw_ap2_state`.
@ -326,7 +331,7 @@ struct bw_ap2_state {
static inline void bw_ap2_init( static inline void bw_ap2_init(
bw_ap2_coeffs * BW_RESTRICT coeffs) { bw_ap2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->svf_coeffs); bw_svf_init(&coeffs->svf_coeffs);
@ -342,7 +347,7 @@ static inline void bw_ap2_init(
static inline void bw_ap2_set_sample_rate( static inline void bw_ap2_set_sample_rate(
bw_ap2_coeffs * BW_RESTRICT coeffs, bw_ap2_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -358,7 +363,7 @@ static inline void bw_ap2_set_sample_rate(
static inline void bw_ap2_reset_coeffs( static inline void bw_ap2_reset_coeffs(
bw_ap2_coeffs * BW_RESTRICT coeffs) { bw_ap2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_set_sample_rate);
@ -376,10 +381,10 @@ static inline float bw_ap2_reset_state(
const bw_ap2_coeffs * BW_RESTRICT coeffs, const bw_ap2_coeffs * BW_RESTRICT coeffs,
bw_ap2_state * BW_RESTRICT state, bw_ap2_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float lp, bp, hp; float lp, bp, hp;
@ -405,18 +410,18 @@ static inline void bw_ap2_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_ap2_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_ap2_reset_state(coeffs, state[i], x_0[i]);
else else
@ -425,12 +430,12 @@ static inline void bw_ap2_reset_state_multi(
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_ap2_update_coeffs_ctrl( static inline void bw_ap2_update_coeffs_ctrl(
bw_ap2_coeffs * BW_RESTRICT coeffs) { bw_ap2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
@ -442,7 +447,7 @@ static inline void bw_ap2_update_coeffs_ctrl(
static inline void bw_ap2_update_coeffs_audio( static inline void bw_ap2_update_coeffs_audio(
bw_ap2_coeffs * BW_RESTRICT coeffs) { bw_ap2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
@ -456,10 +461,10 @@ static inline float bw_ap2_process1(
const bw_ap2_coeffs * BW_RESTRICT coeffs, const bw_ap2_coeffs * BW_RESTRICT coeffs,
bw_ap2_state * BW_RESTRICT state, bw_ap2_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ap2_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -482,14 +487,14 @@ static inline void bw_ap2_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ap2_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_ap2_update_coeffs_ctrl(coeffs); bw_ap2_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -510,17 +515,17 @@ static inline void bw_ap2_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -541,7 +546,7 @@ static inline void bw_ap2_process_multi(
static inline void bw_ap2_set_cutoff( static inline void bw_ap2_set_cutoff(
bw_ap2_coeffs * BW_RESTRICT coeffs, bw_ap2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -556,7 +561,7 @@ static inline void bw_ap2_set_cutoff(
static inline void bw_ap2_set_Q( static inline void bw_ap2_set_Q(
bw_ap2_coeffs * BW_RESTRICT coeffs, bw_ap2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -571,7 +576,7 @@ static inline void bw_ap2_set_Q(
static inline void bw_ap2_set_prewarp_at_cutoff( static inline void bw_ap2_set_prewarp_at_cutoff(
bw_ap2_coeffs * BW_RESTRICT coeffs, bw_ap2_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init);
@ -584,7 +589,7 @@ static inline void bw_ap2_set_prewarp_at_cutoff(
static inline void bw_ap2_set_prewarp_freq( static inline void bw_ap2_set_prewarp_freq(
bw_ap2_coeffs * BW_RESTRICT coeffs, bw_ap2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ap2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ap2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -598,7 +603,7 @@ static inline void bw_ap2_set_prewarp_freq(
static inline char bw_ap2_coeffs_is_valid( static inline char bw_ap2_coeffs_is_valid(
const bw_ap2_coeffs * BW_RESTRICT coeffs) { const bw_ap2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ap2_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ap2_coeffs"))
@ -613,17 +618,17 @@ static inline char bw_ap2_coeffs_is_valid(
static inline char bw_ap2_state_is_valid( static inline char bw_ap2_state_is_valid(
const bw_ap2_coeffs * BW_RESTRICT coeffs, const bw_ap2_coeffs * BW_RESTRICT coeffs,
const bw_ap2_state * BW_RESTRICT state) { const bw_ap2_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_ap2_state")) if (state->hash != bw_hash_sdbm("bw_ap2_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : NULL, &state->svf_state); return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : BW_NULL, &state->svf_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_one_pole }}} * requires {{{ bw_common bw_gain bw_math bw_one_pole }}}
* description {{{ * description {{{
* Stereo balance. * Stereo balance.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li><code>bw_balance_process()</code> and * <li><code>bw_balance_process()</code> and
@ -229,7 +234,7 @@ struct bw_balance_coeffs {
static inline void bw_balance_init( static inline void bw_balance_init(
bw_balance_coeffs * BW_RESTRICT coeffs) { bw_balance_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_gain_init(&coeffs->l_coeffs); bw_gain_init(&coeffs->l_coeffs);
bw_gain_init(&coeffs->r_coeffs); bw_gain_init(&coeffs->r_coeffs);
@ -246,7 +251,7 @@ static inline void bw_balance_init(
static inline void bw_balance_set_sample_rate( static inline void bw_balance_set_sample_rate(
bw_balance_coeffs * BW_RESTRICT coeffs, bw_balance_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -273,7 +278,7 @@ static inline void bw_balance_do_update_coeffs(
static inline void bw_balance_reset_coeffs( static inline void bw_balance_reset_coeffs(
bw_balance_coeffs * BW_RESTRICT coeffs) { bw_balance_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_set_sample_rate);
@ -290,7 +295,7 @@ static inline void bw_balance_reset_coeffs(
static inline void bw_balance_update_coeffs_ctrl( static inline void bw_balance_update_coeffs_ctrl(
bw_balance_coeffs * BW_RESTRICT coeffs) { bw_balance_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs);
@ -304,7 +309,7 @@ static inline void bw_balance_update_coeffs_ctrl(
static inline void bw_balance_update_coeffs_audio( static inline void bw_balance_update_coeffs_audio(
bw_balance_coeffs * BW_RESTRICT coeffs) { bw_balance_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs);
@ -321,7 +326,7 @@ static inline void bw_balance_process1(
float x_r, float x_r,
float * BW_RESTRICT y_l, float * BW_RESTRICT y_l,
float * BW_RESTRICT y_r) { float * BW_RESTRICT y_r) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x_l)); BW_ASSERT(bw_is_finite(x_l));
@ -344,15 +349,15 @@ static inline void bw_balance_process(
float * y_l, float * y_l,
float * y_r, float * y_r,
size_t n_samples){ size_t n_samples){
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs);
BW_ASSERT(x_l != NULL); BW_ASSERT(x_l != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_l, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_l, n_samples));
BW_ASSERT(x_r != NULL); BW_ASSERT(x_r != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_r, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_r, n_samples));
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
bw_balance_update_coeffs_ctrl(coeffs); bw_balance_update_coeffs_ctrl(coeffs);
@ -375,13 +380,13 @@ static inline void bw_balance_process_multi(
float * const * y_r, float * const * y_r,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_reset_coeffs);
BW_ASSERT(x_l != NULL); BW_ASSERT(x_l != BW_NULL);
BW_ASSERT(x_r != NULL); BW_ASSERT(x_r != BW_NULL);
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -408,7 +413,7 @@ static inline void bw_balance_process_multi(
static inline void bw_balance_set_balance( static inline void bw_balance_set_balance(
bw_balance_coeffs * BW_RESTRICT coeffs, bw_balance_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_balance_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_balance_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -422,7 +427,7 @@ static inline void bw_balance_set_balance(
static inline char bw_balance_coeffs_is_valid( static inline char bw_balance_coeffs_is_valid(
const bw_balance_coeffs * BW_RESTRICT coeffs) { const bw_balance_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_balance_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_balance_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Bit depth reducer. * Bit depth reducer.
@ -31,6 +31,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_bd_reduce_set_sample_rate()</code>.</li> * <li>Added <code>bw_bd_reduce_set_sample_rate()</code>.</li>
@ -225,7 +230,7 @@ struct bw_bd_reduce_coeffs {
static inline void bw_bd_reduce_init( static inline void bw_bd_reduce_init(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs) { bw_bd_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->bit_depth = 16; coeffs->bit_depth = 16;
@ -240,7 +245,7 @@ static inline void bw_bd_reduce_init(
static inline void bw_bd_reduce_set_sample_rate( static inline void bw_bd_reduce_set_sample_rate(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs, bw_bd_reduce_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -267,7 +272,7 @@ static inline void bw_bd_reduce_do_update_coeffs_ctrl(
static inline void bw_bd_reduce_reset_coeffs( static inline void bw_bd_reduce_reset_coeffs(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs) { bw_bd_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_set_sample_rate);
@ -283,7 +288,7 @@ static inline void bw_bd_reduce_reset_coeffs(
static inline void bw_bd_reduce_update_coeffs_ctrl( static inline void bw_bd_reduce_update_coeffs_ctrl(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs) { bw_bd_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs);
@ -295,7 +300,7 @@ static inline void bw_bd_reduce_update_coeffs_ctrl(
static inline void bw_bd_reduce_update_coeffs_audio( static inline void bw_bd_reduce_update_coeffs_audio(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs) { bw_bd_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs);
@ -305,7 +310,7 @@ static inline void bw_bd_reduce_update_coeffs_audio(
static inline float bw_bd_reduce_process1( static inline float bw_bd_reduce_process1(
const bw_bd_reduce_coeffs * BW_RESTRICT coeffs, const bw_bd_reduce_coeffs * BW_RESTRICT coeffs,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -324,12 +329,12 @@ static inline void bw_bd_reduce_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_bd_reduce_update_coeffs_ctrl(coeffs); bw_bd_reduce_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -346,11 +351,11 @@ static inline void bw_bd_reduce_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -369,7 +374,7 @@ static inline void bw_bd_reduce_process_multi(
static inline void bw_bd_reduce_set_bit_depth( static inline void bw_bd_reduce_set_bit_depth(
bw_bd_reduce_coeffs * BW_RESTRICT coeffs, bw_bd_reduce_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_bd_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_bd_reduce_coeffs_state_init);
BW_ASSERT(value >= 1 && value <= 64); BW_ASSERT(value >= 1 && value <= 64);
@ -382,7 +387,7 @@ static inline void bw_bd_reduce_set_bit_depth(
static inline char bw_bd_reduce_coeffs_is_valid( static inline char bw_bd_reduce_coeffs_is_valid(
const bw_bd_reduce_coeffs * BW_RESTRICT coeffs) { const bw_bd_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_bd_reduce_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_bd_reduce_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ utility }}} * module_type {{{ utility }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* Common operations on buffers. * Common operations on buffers.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Now using <code>size_t</code> instead of * <li>Now using <code>size_t</code> instead of
@ -240,7 +245,7 @@ static inline void bw_buf_fill(
float * BW_RESTRICT dest, float * BW_RESTRICT dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = k; dest[i] = k;
@ -252,9 +257,9 @@ static inline void bw_buf_neg(
const float * src, const float * src,
float * dest, float * dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src, n_elems));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = -src[i]; dest[i] = -src[i];
@ -267,10 +272,10 @@ static inline void bw_buf_add(
float k, float k,
float * dest, float * dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src, n_elems));
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = k + src[i]; dest[i] = k + src[i];
@ -283,10 +288,10 @@ static inline void bw_buf_scale(
float k, float k,
float * dest, float * dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src, n_elems));
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = k * src[i]; dest[i] = k * src[i];
@ -299,11 +304,11 @@ static inline void bw_buf_mix(
const float * src2, const float * src2,
float * dest, float * dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src1 != NULL); BW_ASSERT(src1 != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src1, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src1, n_elems));
BW_ASSERT(src2 != NULL); BW_ASSERT(src2 != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src2, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src2, n_elems));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = src1[i] + src2[i]; dest[i] = src1[i] + src2[i];
@ -316,11 +321,11 @@ static inline void bw_buf_mul(
const float * src2, const float * src2,
float * dest, float * dest,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src1 != NULL); BW_ASSERT(src1 != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src1, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src1, n_elems));
BW_ASSERT(src2 != NULL); BW_ASSERT(src2 != BW_NULL);
BW_ASSERT_DEEP(!bw_has_nan(src2, n_elems)); BW_ASSERT_DEEP(!bw_has_nan(src2, n_elems));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
for (size_t i = 0; i < n_elems; i++) for (size_t i = 0; i < n_elems; i++)
dest[i] = src1[i] * src2[i]; dest[i] = src1[i] * src2[i];
@ -334,7 +339,7 @@ static inline void bw_buf_fill_multi(
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -350,8 +355,8 @@ static inline void bw_buf_neg_multi(
float * const * dest, float * const * dest,
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -368,9 +373,9 @@ static inline void bw_buf_add_multi(
float * const * dest, float * const * dest,
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -387,9 +392,9 @@ static inline void bw_buf_scale_multi(
float * const * dest, float * const * dest,
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src != NULL); BW_ASSERT(src != BW_NULL);
BW_ASSERT(!bw_is_nan(k)); BW_ASSERT(!bw_is_nan(k));
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -406,9 +411,9 @@ static inline void bw_buf_mix_multi(
float * const * dest, float * const * dest,
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src1 != NULL); BW_ASSERT(src1 != BW_NULL);
BW_ASSERT(src2 != NULL); BW_ASSERT(src2 != BW_NULL);
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -425,9 +430,9 @@ static inline void bw_buf_mul_multi(
float * const * dest, float * const * dest,
size_t n_channels, size_t n_channels,
size_t n_elems) { size_t n_elems) {
BW_ASSERT(src1 != NULL); BW_ASSERT(src1 != BW_NULL);
BW_ASSERT(src2 != NULL); BW_ASSERT(src2 != BW_NULL);
BW_ASSERT(dest != NULL); BW_ASSERT(dest != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -109,7 +109,7 @@ static inline void bw_cab_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_cab_update_coeffs_ctrl() * #### bw_cab_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -222,7 +222,7 @@ static inline char bw_cab_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed (`state`
* is supposed to be associated to `coeffs`). * is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
@ -285,7 +285,7 @@ struct bw_cab_state {
static inline void bw_cab_init( static inline void bw_cab_init(
bw_cab_coeffs * BW_RESTRICT coeffs) { bw_cab_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->lp_coeffs); bw_svf_init(&coeffs->lp_coeffs);
bw_svf_init(&coeffs->hp_coeffs); bw_svf_init(&coeffs->hp_coeffs);
@ -313,7 +313,7 @@ static inline void bw_cab_init(
static inline void bw_cab_set_sample_rate( static inline void bw_cab_set_sample_rate(
bw_cab_coeffs * BW_RESTRICT coeffs, bw_cab_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -334,7 +334,7 @@ static inline void bw_cab_set_sample_rate(
static inline void bw_cab_reset_coeffs( static inline void bw_cab_reset_coeffs(
bw_cab_coeffs * BW_RESTRICT coeffs) { bw_cab_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_set_sample_rate);
@ -357,10 +357,10 @@ static inline float bw_cab_reset_state(
const bw_cab_coeffs * BW_RESTRICT coeffs, const bw_cab_coeffs * BW_RESTRICT coeffs,
bw_cab_state * BW_RESTRICT state, bw_cab_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float v_lp, v_hp, v_bp; float v_lp, v_hp, v_bp;
@ -392,18 +392,18 @@ static inline void bw_cab_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_cab_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_cab_reset_state(coeffs, state[i], x_0[i]);
else else
@ -412,12 +412,12 @@ static inline void bw_cab_reset_state_multi(
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_cab_update_coeffs_ctrl( static inline void bw_cab_update_coeffs_ctrl(
bw_cab_coeffs * BW_RESTRICT coeffs) { bw_cab_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
@ -434,7 +434,7 @@ static inline void bw_cab_update_coeffs_ctrl(
static inline void bw_cab_update_coeffs_audio( static inline void bw_cab_update_coeffs_audio(
bw_cab_coeffs * BW_RESTRICT coeffs) { bw_cab_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
@ -453,10 +453,10 @@ static inline float bw_cab_process1(
const bw_cab_coeffs * BW_RESTRICT coeffs, const bw_cab_coeffs * BW_RESTRICT coeffs,
bw_cab_state * BW_RESTRICT state, bw_cab_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_cab_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_cab_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -485,14 +485,14 @@ static inline void bw_cab_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_cab_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_cab_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_cab_update_coeffs_ctrl(coeffs); bw_cab_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -513,17 +513,17 @@ static inline void bw_cab_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -544,7 +544,7 @@ static inline void bw_cab_process_multi(
static inline void bw_cab_set_cutoff_low( static inline void bw_cab_set_cutoff_low(
bw_cab_coeffs * BW_RESTRICT coeffs, bw_cab_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -561,7 +561,7 @@ static inline void bw_cab_set_cutoff_low(
static inline void bw_cab_set_cutoff_high( static inline void bw_cab_set_cutoff_high(
bw_cab_coeffs * BW_RESTRICT coeffs, bw_cab_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -578,7 +578,7 @@ static inline void bw_cab_set_cutoff_high(
static inline void bw_cab_set_tone( static inline void bw_cab_set_tone(
bw_cab_coeffs * BW_RESTRICT coeffs, bw_cab_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_cab_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_cab_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -593,7 +593,7 @@ static inline void bw_cab_set_tone(
static inline char bw_cab_coeffs_is_valid( static inline char bw_cab_coeffs_is_valid(
const bw_cab_coeffs * BW_RESTRICT coeffs) { const bw_cab_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_cab_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_cab_coeffs"))
@ -613,20 +613,20 @@ static inline char bw_cab_coeffs_is_valid(
static inline char bw_cab_state_is_valid( static inline char bw_cab_state_is_valid(
const bw_cab_coeffs * BW_RESTRICT coeffs, const bw_cab_coeffs * BW_RESTRICT coeffs,
const bw_cab_state * BW_RESTRICT state) { const bw_cab_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_cab_state")) if (state->hash != bw_hash_sdbm("bw_cab_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->lp_coeffs : NULL, &state->lp_state) return bw_svf_state_is_valid(coeffs ? &coeffs->lp_coeffs : BW_NULL, &state->lp_state)
&& bw_svf_state_is_valid(coeffs ? &coeffs->hp_coeffs : NULL, &state->hp_state) && bw_svf_state_is_valid(coeffs ? &coeffs->hp_coeffs : BW_NULL, &state->hp_state)
&& bw_svf_state_is_valid(coeffs ? &coeffs->bpl_coeffs : NULL, &state->bpl_state) && bw_svf_state_is_valid(coeffs ? &coeffs->bpl_coeffs : BW_NULL, &state->bpl_state)
&& bw_svf_state_is_valid(coeffs ? &coeffs->bph_coeffs : NULL, &state->bph_state); && bw_svf_state_is_valid(coeffs ? &coeffs->bph_coeffs : BW_NULL, &state->bph_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_buf bw_comb bw_common bw_delay bw_gain bw_math bw_one_pole bw_osc_sin * bw_buf bw_comb bw_common bw_delay bw_gain bw_math bw_one_pole bw_osc_sin
* bw_phase_gen * bw_phase_gen
@ -36,6 +36,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial value argument in * <li>Added initial value argument in
@ -178,7 +183,7 @@ static inline void bw_chorus_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* If parameter `coeff_fb` has value `-1.f` or `1.f`, then `x_0` must only * If parameter `coeff_fb` has value `-1.f` or `1.f`, then `x_0` must only
* contain `0.f`. * contain `0.f`.
@ -335,8 +340,8 @@ static inline char bw_chorus_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_chorus_state`. * than or equal to that of `bw_chorus_state`.
@ -407,7 +412,7 @@ struct bw_chorus_state {
static inline void bw_chorus_init( static inline void bw_chorus_init(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float max_delay) { float max_delay) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(bw_is_finite(max_delay)); BW_ASSERT(bw_is_finite(max_delay));
BW_ASSERT(max_delay >= 0.f); BW_ASSERT(max_delay >= 0.f);
@ -428,7 +433,7 @@ static inline void bw_chorus_init(
static inline void bw_chorus_set_sample_rate( static inline void bw_chorus_set_sample_rate(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -445,7 +450,7 @@ static inline void bw_chorus_set_sample_rate(
static inline size_t bw_chorus_mem_req( static inline size_t bw_chorus_mem_req(
const bw_chorus_coeffs * BW_RESTRICT coeffs) { const bw_chorus_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate);
@ -456,11 +461,11 @@ static inline void bw_chorus_mem_set(
const bw_chorus_coeffs * BW_RESTRICT coeffs, const bw_chorus_coeffs * BW_RESTRICT coeffs,
bw_chorus_state * BW_RESTRICT state, bw_chorus_state * BW_RESTRICT state,
void * BW_RESTRICT mem) { void * BW_RESTRICT mem) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(mem != NULL); BW_ASSERT(mem != BW_NULL);
bw_comb_mem_set(&coeffs->comb_coeffs, &state->comb_state, mem); bw_comb_mem_set(&coeffs->comb_coeffs, &state->comb_state, mem);
@ -476,7 +481,7 @@ static inline void bw_chorus_mem_set(
static inline void bw_chorus_reset_coeffs( static inline void bw_chorus_reset_coeffs(
bw_chorus_coeffs * BW_RESTRICT coeffs) { bw_chorus_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_set_sample_rate);
@ -499,10 +504,10 @@ static inline float bw_chorus_reset_state(
const bw_chorus_coeffs * BW_RESTRICT coeffs, const bw_chorus_coeffs * BW_RESTRICT coeffs,
bw_chorus_state * BW_RESTRICT state, bw_chorus_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_mem_set); BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_mem_set);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
@ -528,18 +533,18 @@ static inline void bw_chorus_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_chorus_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_chorus_reset_state(coeffs, state[i], x_0[i]);
else else
@ -548,12 +553,12 @@ static inline void bw_chorus_reset_state_multi(
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_chorus_update_coeffs_ctrl( static inline void bw_chorus_update_coeffs_ctrl(
bw_chorus_coeffs * BW_RESTRICT coeffs) { bw_chorus_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
@ -566,7 +571,7 @@ static inline void bw_chorus_update_coeffs_ctrl(
static inline void bw_chorus_update_coeffs_audio( static inline void bw_chorus_update_coeffs_audio(
bw_chorus_coeffs * BW_RESTRICT coeffs) { bw_chorus_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
@ -586,10 +591,10 @@ static inline float bw_chorus_process1(
const bw_chorus_coeffs * BW_RESTRICT coeffs, const bw_chorus_coeffs * BW_RESTRICT coeffs,
bw_chorus_state * BW_RESTRICT state, bw_chorus_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_reset_state);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -611,15 +616,15 @@ static inline void bw_chorus_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_chorus_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_chorus_state_state_reset_state);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_chorus_update_coeffs_ctrl(coeffs); bw_chorus_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -641,17 +646,17 @@ static inline void bw_chorus_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -672,7 +677,7 @@ static inline void bw_chorus_process_multi(
static inline void bw_chorus_set_rate( static inline void bw_chorus_set_rate(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -686,7 +691,7 @@ static inline void bw_chorus_set_rate(
static inline void bw_chorus_set_delay( static inline void bw_chorus_set_delay(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -701,7 +706,7 @@ static inline void bw_chorus_set_delay(
static inline void bw_chorus_set_amount( static inline void bw_chorus_set_amount(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -712,7 +717,7 @@ static inline void bw_chorus_set_amount(
static inline void bw_chorus_set_coeff_x( static inline void bw_chorus_set_coeff_x(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -726,7 +731,7 @@ static inline void bw_chorus_set_coeff_x(
static inline void bw_chorus_set_coeff_mod( static inline void bw_chorus_set_coeff_mod(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -740,7 +745,7 @@ static inline void bw_chorus_set_coeff_mod(
static inline void bw_chorus_set_coeff_fb( static inline void bw_chorus_set_coeff_fb(
bw_chorus_coeffs * BW_RESTRICT coeffs, bw_chorus_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_chorus_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_chorus_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -754,7 +759,7 @@ static inline void bw_chorus_set_coeff_fb(
static inline char bw_chorus_coeffs_is_valid( static inline char bw_chorus_coeffs_is_valid(
const bw_chorus_coeffs * BW_RESTRICT coeffs) { const bw_chorus_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_chorus_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_chorus_coeffs"))
@ -782,7 +787,7 @@ static inline char bw_chorus_coeffs_is_valid(
static inline char bw_chorus_state_is_valid( static inline char bw_chorus_state_is_valid(
const bw_chorus_coeffs * BW_RESTRICT coeffs, const bw_chorus_coeffs * BW_RESTRICT coeffs,
const bw_chorus_state * BW_RESTRICT state) { const bw_chorus_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_chorus_state")) if (state->hash != bw_hash_sdbm("bw_chorus_state"))
@ -790,11 +795,11 @@ static inline char bw_chorus_state_is_valid(
if (state->state < bw_chorus_state_state_mem_set || state->state > bw_chorus_state_state_reset_state) if (state->state < bw_chorus_state_state_mem_set || state->state > bw_chorus_state_state_reset_state)
return 0; return 0;
if (state->state >= bw_chorus_state_state_reset_state && coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (state->state >= bw_chorus_state_state_reset_state && coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_comb_state_is_valid(coeffs ? &coeffs->comb_coeffs : NULL, &state->comb_state); return bw_comb_state_is_valid(coeffs ? &coeffs->comb_coeffs : BW_NULL, &state->comb_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Antialiased hard clipper with parametric bias and gain * Antialiased hard clipper with parametric bias and gain
@ -45,6 +45,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Changed default value for gain compensation to off.</li> * <li>Changed default value for gain compensation to off.</li>
@ -153,7 +158,7 @@ static inline void bw_clip_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_clip_update_coeffs_ctrl() * #### bw_clip_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -275,8 +280,8 @@ static inline char bw_clip_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_clip_state`. * than or equal to that of `bw_clip_state`.
@ -342,7 +347,7 @@ struct bw_clip_state {
static inline void bw_clip_init( static inline void bw_clip_init(
bw_clip_coeffs * BW_RESTRICT coeffs) { bw_clip_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -363,7 +368,7 @@ static inline void bw_clip_init(
static inline void bw_clip_set_sample_rate( static inline void bw_clip_set_sample_rate(
bw_clip_coeffs * BW_RESTRICT coeffs, bw_clip_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -395,7 +400,7 @@ static inline void bw_clip_do_update_coeffs(
static inline void bw_clip_reset_coeffs( static inline void bw_clip_reset_coeffs(
bw_clip_coeffs * BW_RESTRICT coeffs) { bw_clip_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_set_sample_rate);
@ -415,10 +420,10 @@ static inline float bw_clip_reset_state(
const bw_clip_coeffs * BW_RESTRICT coeffs, const bw_clip_coeffs * BW_RESTRICT coeffs,
bw_clip_state * BW_RESTRICT state, bw_clip_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float x = bw_one_pole_get_y_z1(&coeffs->smooth_gain_state) * x_0 + bw_one_pole_get_y_z1(&coeffs->smooth_bias_state); const float x = bw_one_pole_get_y_z1(&coeffs->smooth_gain_state) * x_0 + bw_one_pole_get_y_z1(&coeffs->smooth_bias_state);
@ -447,18 +452,18 @@ static inline void bw_clip_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_clip_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_clip_reset_state(coeffs, state[i], x_0[i]);
else else
@ -467,12 +472,12 @@ static inline void bw_clip_reset_state_multi(
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_clip_update_coeffs_ctrl( static inline void bw_clip_update_coeffs_ctrl(
bw_clip_coeffs * BW_RESTRICT coeffs) { bw_clip_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
@ -481,7 +486,7 @@ static inline void bw_clip_update_coeffs_ctrl(
static inline void bw_clip_update_coeffs_audio( static inline void bw_clip_update_coeffs_audio(
bw_clip_coeffs * BW_RESTRICT coeffs) { bw_clip_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
@ -495,10 +500,10 @@ static inline float bw_clip_process1(
const bw_clip_coeffs * BW_RESTRICT coeffs, const bw_clip_coeffs * BW_RESTRICT coeffs,
bw_clip_state * BW_RESTRICT state, bw_clip_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -523,10 +528,10 @@ static inline float bw_clip_process1_comp(
const bw_clip_coeffs * BW_RESTRICT coeffs, const bw_clip_coeffs * BW_RESTRICT coeffs,
bw_clip_state * BW_RESTRICT state, bw_clip_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -546,14 +551,14 @@ static inline void bw_clip_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_clip_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->gain_compensation) if (coeffs->gain_compensation)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -579,17 +584,17 @@ static inline void bw_clip_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -616,7 +621,7 @@ static inline void bw_clip_process_multi(
static inline void bw_clip_set_bias( static inline void bw_clip_set_bias(
bw_clip_coeffs * BW_RESTRICT coeffs, bw_clip_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -631,7 +636,7 @@ static inline void bw_clip_set_bias(
static inline void bw_clip_set_gain( static inline void bw_clip_set_gain(
bw_clip_coeffs * BW_RESTRICT coeffs, bw_clip_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -646,7 +651,7 @@ static inline void bw_clip_set_gain(
static inline void bw_clip_set_gain_compensation( static inline void bw_clip_set_gain_compensation(
bw_clip_coeffs * BW_RESTRICT coeffs, bw_clip_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_clip_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_clip_coeffs_state_init);
@ -658,7 +663,7 @@ static inline void bw_clip_set_gain_compensation(
static inline char bw_clip_coeffs_is_valid( static inline char bw_clip_coeffs_is_valid(
const bw_clip_coeffs * BW_RESTRICT coeffs) { const bw_clip_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_clip_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_clip_coeffs"))
@ -695,13 +700,13 @@ static inline char bw_clip_coeffs_is_valid(
static inline char bw_clip_state_is_valid( static inline char bw_clip_state_is_valid(
const bw_clip_coeffs * BW_RESTRICT coeffs, const bw_clip_coeffs * BW_RESTRICT coeffs,
const bw_clip_state * BW_RESTRICT state) { const bw_clip_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_clip_state")) if (state->hash != bw_hash_sdbm("bw_clip_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_buf bw_common bw_delay bw_gain bw_math bw_one_pole * bw_buf bw_common bw_delay bw_gain bw_math bw_one_pole
* }}} * }}}
@ -37,6 +37,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial value argument in * <li>Added initial value argument in
@ -179,7 +184,7 @@ static inline void bw_comb_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* If parameter `coeff_fb` has value `-1.f` or `1.f`, then `x_0` must only * If parameter `coeff_fb` has value `-1.f` or `1.f`, then `x_0` must only
* contain `0.f`. * contain `0.f`.
@ -322,8 +327,8 @@ static inline char bw_comb_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_comb_state`. * than or equal to that of `bw_comb_state`.
@ -407,7 +412,7 @@ struct bw_comb_state {
static inline void bw_comb_init( static inline void bw_comb_init(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float max_delay) { float max_delay) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(bw_is_finite(max_delay)); BW_ASSERT(bw_is_finite(max_delay));
BW_ASSERT(max_delay >= 0.f); BW_ASSERT(max_delay >= 0.f);
@ -435,7 +440,7 @@ static inline void bw_comb_init(
static inline void bw_comb_set_sample_rate( static inline void bw_comb_set_sample_rate(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -457,7 +462,7 @@ static inline void bw_comb_set_sample_rate(
static inline size_t bw_comb_mem_req( static inline size_t bw_comb_mem_req(
const bw_comb_coeffs * BW_RESTRICT coeffs) { const bw_comb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate);
@ -468,11 +473,11 @@ static inline void bw_comb_mem_set(
const bw_comb_coeffs * BW_RESTRICT coeffs, const bw_comb_coeffs * BW_RESTRICT coeffs,
bw_comb_state * BW_RESTRICT state, bw_comb_state * BW_RESTRICT state,
void * BW_RESTRICT mem) { void * BW_RESTRICT mem) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(mem != NULL); BW_ASSERT(mem != BW_NULL);
bw_delay_mem_set(&coeffs->delay_coeffs, &state->delay_state, mem); bw_delay_mem_set(&coeffs->delay_coeffs, &state->delay_state, mem);
@ -519,7 +524,7 @@ static inline void bw_comb_do_update_coeffs(
static inline void bw_comb_reset_coeffs( static inline void bw_comb_reset_coeffs(
bw_comb_coeffs * BW_RESTRICT coeffs) { bw_comb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_set_sample_rate);
@ -543,10 +548,10 @@ static inline float bw_comb_reset_state(
const bw_comb_coeffs * BW_RESTRICT coeffs, const bw_comb_coeffs * BW_RESTRICT coeffs,
bw_comb_state * BW_RESTRICT state, bw_comb_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_comb_state_state_mem_set); BW_ASSERT_DEEP(state->state >= bw_comb_state_state_mem_set);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
@ -582,18 +587,18 @@ static inline void bw_comb_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_comb_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_comb_reset_state(coeffs, state[i], x_0[i]);
else else
@ -602,12 +607,12 @@ static inline void bw_comb_reset_state_multi(
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_comb_update_coeffs_ctrl( static inline void bw_comb_update_coeffs_ctrl(
bw_comb_coeffs * BW_RESTRICT coeffs) { bw_comb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
@ -621,7 +626,7 @@ static inline void bw_comb_update_coeffs_ctrl(
static inline void bw_comb_update_coeffs_audio( static inline void bw_comb_update_coeffs_audio(
bw_comb_coeffs * BW_RESTRICT coeffs) { bw_comb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
@ -638,10 +643,10 @@ static inline float bw_comb_process1(
const bw_comb_coeffs * BW_RESTRICT coeffs, const bw_comb_coeffs * BW_RESTRICT coeffs,
bw_comb_state * BW_RESTRICT state, bw_comb_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_comb_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_comb_state_state_reset_state);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -667,15 +672,15 @@ static inline void bw_comb_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_comb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_comb_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_comb_state_state_reset_state);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_comb_update_coeffs_ctrl(coeffs); bw_comb_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -697,17 +702,17 @@ static inline void bw_comb_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -728,7 +733,7 @@ static inline void bw_comb_process_multi(
static inline void bw_comb_set_delay_ff( static inline void bw_comb_set_delay_ff(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -742,7 +747,7 @@ static inline void bw_comb_set_delay_ff(
static inline void bw_comb_set_delay_fb( static inline void bw_comb_set_delay_fb(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -756,7 +761,7 @@ static inline void bw_comb_set_delay_fb(
static inline void bw_comb_set_coeff_blend( static inline void bw_comb_set_coeff_blend(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -770,7 +775,7 @@ static inline void bw_comb_set_coeff_blend(
static inline void bw_comb_set_coeff_ff( static inline void bw_comb_set_coeff_ff(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -784,7 +789,7 @@ static inline void bw_comb_set_coeff_ff(
static inline void bw_comb_set_coeff_fb( static inline void bw_comb_set_coeff_fb(
bw_comb_coeffs * BW_RESTRICT coeffs, bw_comb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -798,7 +803,7 @@ static inline void bw_comb_set_coeff_fb(
static inline char bw_comb_coeffs_is_valid( static inline char bw_comb_coeffs_is_valid(
const bw_comb_coeffs * BW_RESTRICT coeffs) { const bw_comb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_comb_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_comb_coeffs"))
@ -849,7 +854,7 @@ static inline char bw_comb_coeffs_is_valid(
static inline char bw_comb_state_is_valid( static inline char bw_comb_state_is_valid(
const bw_comb_coeffs * BW_RESTRICT coeffs, const bw_comb_coeffs * BW_RESTRICT coeffs,
const bw_comb_state * BW_RESTRICT state) { const bw_comb_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_comb_state")) if (state->hash != bw_hash_sdbm("bw_comb_state"))
@ -857,11 +862,11 @@ static inline char bw_comb_state_is_valid(
if (state->state < bw_comb_state_state_mem_set || state->state > bw_comb_state_state_reset_state) if (state->state < bw_comb_state_state_mem_set || state->state > bw_comb_state_state_reset_state)
return 0; return 0;
if (state->state >= bw_comb_state_state_reset_state && coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (state->state >= bw_comb_state_state_reset_state && coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_delay_state_is_valid(coeffs ? &coeffs->delay_coeffs : NULL, &state->delay_state); return bw_delay_state_is_valid(coeffs ? &coeffs->delay_coeffs : BW_NULL, &state->delay_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,19 @@
/*! /*!
* module_type {{{ foundation }}} * module_type {{{ foundation }}}
* version {{{ 1.0.0 }}} * version {{{ 1.1.0 }}}
* description {{{ * description {{{
* A common header to make sure that a bunch of basic definitions are * A common header to make sure that a bunch of basic definitions are
* available and consistent for all Brickworks modules. * available and consistent for all Brickworks modules.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.1.0</strong>:
* <ul>
* <li>Added <code>BW_NULL</code> and relaxed <code>NULL</code> definition
* requirement in C++.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Removed <code>BW_SIZE_T</code> and went for <code>size_t</code> * <li>Removed <code>BW_SIZE_T</code> and went for <code>size_t</code>
@ -91,7 +97,7 @@
* *
* Brickworks requires definitions of: * Brickworks requires definitions of:
* *
* * `NULL` and `size_t`, normally supplied by `stddef.h`; * * `NULL` (C only) and `size_t`, normally supplied by `stddef.h`;
* * `(u)int{8,16,32,64}_t`, `INT{8,16,32,64}_{MIN,MAX}`, and * * `(u)int{8,16,32,64}_t`, `INT{8,16,32,64}_{MIN,MAX}`, and
* `UINT{8,16,32,64}_MAX`, normally supplied by `stdint.h`; * `UINT{8,16,32,64}_MAX`, normally supplied by `stdint.h`;
* * `INFINITY`, normally supplied by `math.h`. * * `INFINITY`, normally supplied by `math.h`.
@ -106,13 +112,20 @@
* * if `BW_NO_STDLIB` or `BW_NO_MATH_H` is defined, then `math.h` is not * * if `BW_NO_STDLIB` or `BW_NO_MATH_H` is defined, then `math.h` is not
* `#include`d. * `#include`d.
* *
* A `BW_NULL` macro is defined whose value is either `NULL` (C) or `nullptr`
* (C++).
* >>> */ * >>> */
#if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDDEF_H) #if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDDEF_H)
# include <stddef.h> # include <stddef.h>
#endif #endif
#ifndef NULL #ifdef __cplusplus
# error NULL not defined # define BW_NULL nullptr
#else
# ifndef NULL
# error NULL not defined
# endif
# define BW_NULL NULL
#endif #endif
#if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDINT_H) #if !defined(BW_NO_STDLIB) && !defined(BW_NO_STDINT_H)

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_common bw_env_follow bw_gain bw_math bw_one_pole * bw_common bw_env_follow bw_gain bw_math bw_one_pole
* }}} * }}}
@ -29,6 +29,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input values to * <li>Added initial input values to
@ -150,7 +155,7 @@ static inline void bw_comp_reset_state_multi(
* array and sidechain input value in the `x_sc_0` array. * array and sidechain input value in the `x_sc_0` array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_comp_update_coeffs_ctrl() * #### bw_comp_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -319,8 +324,8 @@ static inline char bw_comp_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_comp_state`. * than or equal to that of `bw_comp_state`.
@ -388,7 +393,7 @@ struct bw_comp_state {
static inline void bw_comp_init( static inline void bw_comp_init(
bw_comp_coeffs * BW_RESTRICT coeffs) { bw_comp_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_env_follow_init(&coeffs->env_follow_coeffs); bw_env_follow_init(&coeffs->env_follow_coeffs);
bw_gain_init(&coeffs->gain_coeffs); bw_gain_init(&coeffs->gain_coeffs);
@ -409,7 +414,7 @@ static inline void bw_comp_init(
static inline void bw_comp_set_sample_rate( static inline void bw_comp_set_sample_rate(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -437,7 +442,7 @@ static inline void bw_comp_do_update_coeffs_audio(
static inline void bw_comp_reset_coeffs( static inline void bw_comp_reset_coeffs(
bw_comp_coeffs * BW_RESTRICT coeffs) { bw_comp_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_set_sample_rate);
@ -460,10 +465,10 @@ static inline float bw_comp_reset_state(
bw_comp_state * BW_RESTRICT state, bw_comp_state * BW_RESTRICT state,
float x_0, float x_0,
float x_sc_0) { float x_sc_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
BW_ASSERT(bw_is_finite(x_sc_0)); BW_ASSERT(bw_is_finite(x_sc_0));
@ -490,19 +495,19 @@ static inline void bw_comp_reset_state_multi(
const float * x_sc_0, const float * x_sc_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
BW_ASSERT(x_sc_0 != NULL); BW_ASSERT(x_sc_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_comp_reset_state(coeffs, state[i], x_0[i], x_sc_0[i]); y_0[i] = bw_comp_reset_state(coeffs, state[i], x_0[i], x_sc_0[i]);
else else
@ -512,12 +517,12 @@ static inline void bw_comp_reset_state_multi(
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_has_only_finite(y_0, n_channels)); BW_ASSERT_DEEP(bw_has_only_finite(y_0, n_channels));
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_comp_update_coeffs_ctrl( static inline void bw_comp_update_coeffs_ctrl(
bw_comp_coeffs * BW_RESTRICT coeffs) { bw_comp_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
@ -530,7 +535,7 @@ static inline void bw_comp_update_coeffs_ctrl(
static inline void bw_comp_update_coeffs_audio( static inline void bw_comp_update_coeffs_audio(
bw_comp_coeffs * BW_RESTRICT coeffs) { bw_comp_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
@ -549,10 +554,10 @@ static inline float bw_comp_process1(
bw_comp_state * BW_RESTRICT state, bw_comp_state * BW_RESTRICT state,
float x, float x,
float x_sc) { float x_sc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_comp_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_comp_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(bw_is_finite(x_sc)); BW_ASSERT(bw_is_finite(x_sc));
@ -576,16 +581,16 @@ static inline void bw_comp_process(
const float * x_sc, const float * x_sc,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_comp_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_comp_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(x_sc != NULL); BW_ASSERT(x_sc != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_sc, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_sc, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_comp_update_coeffs_ctrl(coeffs); bw_comp_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -607,18 +612,18 @@ static inline void bw_comp_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(x_sc != NULL); BW_ASSERT(x_sc != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -639,7 +644,7 @@ static inline void bw_comp_process_multi(
static inline void bw_comp_set_thresh_lin( static inline void bw_comp_set_thresh_lin(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -654,7 +659,7 @@ static inline void bw_comp_set_thresh_lin(
static inline void bw_comp_set_thresh_dBFS( static inline void bw_comp_set_thresh_dBFS(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -669,7 +674,7 @@ static inline void bw_comp_set_thresh_dBFS(
static inline void bw_comp_set_ratio( static inline void bw_comp_set_ratio(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -684,7 +689,7 @@ static inline void bw_comp_set_ratio(
static inline void bw_comp_set_attack_tau( static inline void bw_comp_set_attack_tau(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -699,7 +704,7 @@ static inline void bw_comp_set_attack_tau(
static inline void bw_comp_set_release_tau( static inline void bw_comp_set_release_tau(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -714,7 +719,7 @@ static inline void bw_comp_set_release_tau(
static inline void bw_comp_set_gain_lin( static inline void bw_comp_set_gain_lin(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -728,7 +733,7 @@ static inline void bw_comp_set_gain_lin(
static inline void bw_comp_set_gain_dB( static inline void bw_comp_set_gain_dB(
bw_comp_coeffs * BW_RESTRICT coeffs, bw_comp_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_comp_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_comp_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -742,7 +747,7 @@ static inline void bw_comp_set_gain_dB(
static inline char bw_comp_coeffs_is_valid( static inline char bw_comp_coeffs_is_valid(
const bw_comp_coeffs * BW_RESTRICT coeffs) { const bw_comp_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_comp_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_comp_coeffs"))
@ -780,17 +785,17 @@ static inline char bw_comp_coeffs_is_valid(
static inline char bw_comp_state_is_valid( static inline char bw_comp_state_is_valid(
const bw_comp_coeffs * BW_RESTRICT coeffs, const bw_comp_coeffs * BW_RESTRICT coeffs,
const bw_comp_state * BW_RESTRICT state) { const bw_comp_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_comp_state")) if (state->hash != bw_hash_sdbm("bw_comp_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : NULL, &state->env_follow_state); return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : BW_NULL, &state->env_follow_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_buf bw_common bw_math }}} * requires {{{ bw_buf bw_common bw_math }}}
* description {{{ * description {{{
* Interpolated delay line, not smoothed. * Interpolated delay line, not smoothed.
@ -31,6 +31,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Removed <code>read()</code> and <code>write()</code> from C++ * <li>Removed <code>read()</code> and <code>write()</code> from C++
@ -171,7 +176,7 @@ static inline void bw_delay_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_delay_read() * #### bw_delay_read()
* ```>>> */ * ```>>> */
@ -292,8 +297,8 @@ static inline char bw_delay_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_delay_state`. * than or equal to that of `bw_delay_state`.
@ -367,7 +372,7 @@ struct bw_delay_state {
static inline void bw_delay_init( static inline void bw_delay_init(
bw_delay_coeffs * BW_RESTRICT coeffs, bw_delay_coeffs * BW_RESTRICT coeffs,
float max_delay) { float max_delay) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(bw_is_finite(max_delay)); BW_ASSERT(bw_is_finite(max_delay));
BW_ASSERT(max_delay >= 0.f); BW_ASSERT(max_delay >= 0.f);
@ -386,7 +391,7 @@ static inline void bw_delay_init(
static inline void bw_delay_set_sample_rate( static inline void bw_delay_set_sample_rate(
bw_delay_coeffs * BW_RESTRICT coeffs, bw_delay_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -403,7 +408,7 @@ static inline void bw_delay_set_sample_rate(
static inline size_t bw_delay_mem_req( static inline size_t bw_delay_mem_req(
const bw_delay_coeffs * BW_RESTRICT coeffs) { const bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate);
@ -414,11 +419,11 @@ static inline void bw_delay_mem_set(
const bw_delay_coeffs * BW_RESTRICT coeffs, const bw_delay_coeffs * BW_RESTRICT coeffs,
bw_delay_state * BW_RESTRICT state, bw_delay_state * BW_RESTRICT state,
void * BW_RESTRICT mem) { void * BW_RESTRICT mem) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(mem != NULL); BW_ASSERT(mem != BW_NULL);
(void)coeffs; (void)coeffs;
state->buf = (float *)mem; state->buf = (float *)mem;
@ -444,7 +449,7 @@ static inline void bw_delay_do_update_coeffs_ctrl(bw_delay_coeffs *BW_RESTRICT c
static inline void bw_delay_reset_coeffs( static inline void bw_delay_reset_coeffs(
bw_delay_coeffs * BW_RESTRICT coeffs) { bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate);
@ -463,10 +468,10 @@ static inline float bw_delay_reset_state(
const bw_delay_coeffs * BW_RESTRICT coeffs, const bw_delay_coeffs * BW_RESTRICT coeffs,
bw_delay_state * BW_RESTRICT state, bw_delay_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_delay_state_state_mem_set); BW_ASSERT_DEEP(state->state >= bw_delay_state_state_mem_set);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
@ -494,18 +499,18 @@ static inline void bw_delay_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_delay_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_delay_reset_state(coeffs, state[i], x_0[i]);
else else
@ -514,7 +519,7 @@ static inline void bw_delay_reset_state_multi(
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static float bw_delay_read( static float bw_delay_read(
@ -522,10 +527,10 @@ static float bw_delay_read(
const bw_delay_state * BW_RESTRICT state, const bw_delay_state * BW_RESTRICT state,
size_t di, size_t di,
float df) { float df) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state);
BW_ASSERT(bw_is_finite(df)); BW_ASSERT(bw_is_finite(df));
@ -549,10 +554,10 @@ static void bw_delay_write(
const bw_delay_coeffs * BW_RESTRICT coeffs, const bw_delay_coeffs * BW_RESTRICT coeffs,
bw_delay_state * BW_RESTRICT state, bw_delay_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -569,7 +574,7 @@ static void bw_delay_write(
static inline void bw_delay_update_coeffs_ctrl( static inline void bw_delay_update_coeffs_ctrl(
bw_delay_coeffs * BW_RESTRICT coeffs) { bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
@ -581,7 +586,7 @@ static inline void bw_delay_update_coeffs_ctrl(
static inline void bw_delay_update_coeffs_audio( static inline void bw_delay_update_coeffs_audio(
bw_delay_coeffs * BW_RESTRICT coeffs) { bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
@ -592,10 +597,10 @@ static inline float bw_delay_process1(
const bw_delay_coeffs * BW_RESTRICT coeffs, const bw_delay_coeffs * BW_RESTRICT coeffs,
bw_delay_state * BW_RESTRICT state, bw_delay_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -618,15 +623,15 @@ static inline void bw_delay_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_delay_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_delay_state_state_reset_state);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_delay_update_coeffs_ctrl(coeffs); bw_delay_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -646,17 +651,17 @@ static inline void bw_delay_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -675,7 +680,7 @@ static inline void bw_delay_process_multi(
static inline void bw_delay_set_delay( static inline void bw_delay_set_delay(
bw_delay_coeffs * BW_RESTRICT coeffs, bw_delay_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -691,7 +696,7 @@ static inline void bw_delay_set_delay(
static inline size_t bw_delay_get_length( static inline size_t bw_delay_get_length(
const bw_delay_coeffs * BW_RESTRICT coeffs) { const bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_delay_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_delay_coeffs_state_set_sample_rate);
@ -700,7 +705,7 @@ static inline size_t bw_delay_get_length(
static inline char bw_delay_coeffs_is_valid( static inline char bw_delay_coeffs_is_valid(
const bw_delay_coeffs * BW_RESTRICT coeffs) { const bw_delay_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_delay_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_delay_coeffs"))
@ -736,7 +741,7 @@ static inline char bw_delay_coeffs_is_valid(
static inline char bw_delay_state_is_valid( static inline char bw_delay_state_is_valid(
const bw_delay_coeffs * BW_RESTRICT coeffs, const bw_delay_coeffs * BW_RESTRICT coeffs,
const bw_delay_state * BW_RESTRICT state) { const bw_delay_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_delay_state")) if (state->hash != bw_hash_sdbm("bw_delay_state"))
@ -747,11 +752,11 @@ static inline char bw_delay_state_is_valid(
(void)coeffs; (void)coeffs;
if (state->buf == NULL) if (state->buf == BW_NULL)
return 0; return 0;
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->state >= bw_delay_state_state_reset_state && coeffs != NULL) { if (state->state >= bw_delay_state_state_reset_state && coeffs != BW_NULL) {
if (coeffs->reset_id != state->coeffs_reset_id) if (coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_clip bw_common bw_gain bw_hp1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak * bw_clip bw_common bw_gain bw_hp1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak
* bw_satur bw_svf * bw_satur bw_svf
@ -32,6 +32,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Adjusted internal peak cutoff to more sensible value.</li> * <li>Adjusted internal peak cutoff to more sensible value.</li>
@ -140,7 +145,7 @@ static inline void bw_dist_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_dist_update_coeffs_ctrl() * #### bw_dist_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -253,8 +258,8 @@ static inline char bw_dist_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_dist_state`. * than or equal to that of `bw_dist_state`.
@ -321,7 +326,7 @@ struct bw_dist_state {
static inline void bw_dist_init( static inline void bw_dist_init(
bw_dist_coeffs * BW_RESTRICT coeffs) { bw_dist_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_hp1_init(&coeffs->hp1_coeffs); bw_hp1_init(&coeffs->hp1_coeffs);
bw_peak_init(&coeffs->peak_coeffs); bw_peak_init(&coeffs->peak_coeffs);
@ -351,7 +356,7 @@ static inline void bw_dist_init(
static inline void bw_dist_set_sample_rate( static inline void bw_dist_set_sample_rate(
bw_dist_coeffs * BW_RESTRICT coeffs, bw_dist_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -375,7 +380,7 @@ static inline void bw_dist_set_sample_rate(
static inline void bw_dist_reset_coeffs( static inline void bw_dist_reset_coeffs(
bw_dist_coeffs * BW_RESTRICT coeffs) { bw_dist_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_set_sample_rate);
@ -395,10 +400,10 @@ static inline float bw_dist_reset_state(
const bw_dist_coeffs * BW_RESTRICT coeffs, const bw_dist_coeffs * BW_RESTRICT coeffs,
bw_dist_state * BW_RESTRICT state, bw_dist_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float y = bw_hp1_reset_state(&coeffs->hp1_coeffs, &state->hp1_state, x_0); float y = bw_hp1_reset_state(&coeffs->hp1_coeffs, &state->hp1_state, x_0);
@ -426,18 +431,18 @@ static inline void bw_dist_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_dist_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_dist_reset_state(coeffs, state[i], x_0[i]);
else else
@ -446,12 +451,12 @@ static inline void bw_dist_reset_state_multi(
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_dist_update_coeffs_ctrl( static inline void bw_dist_update_coeffs_ctrl(
bw_dist_coeffs * BW_RESTRICT coeffs) { bw_dist_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
@ -465,7 +470,7 @@ static inline void bw_dist_update_coeffs_ctrl(
static inline void bw_dist_update_coeffs_audio( static inline void bw_dist_update_coeffs_audio(
bw_dist_coeffs * BW_RESTRICT coeffs) { bw_dist_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
@ -481,10 +486,10 @@ static inline float bw_dist_process1(
const bw_dist_coeffs * BW_RESTRICT coeffs, const bw_dist_coeffs * BW_RESTRICT coeffs,
bw_dist_state * BW_RESTRICT state, bw_dist_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_dist_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_dist_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -509,14 +514,14 @@ static inline void bw_dist_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_dist_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_dist_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_dist_update_coeffs_ctrl(coeffs); bw_dist_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -537,17 +542,17 @@ static inline void bw_dist_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -568,7 +573,7 @@ static inline void bw_dist_process_multi(
static inline void bw_dist_set_distortion( static inline void bw_dist_set_distortion(
bw_dist_coeffs * BW_RESTRICT coeffs, bw_dist_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -583,7 +588,7 @@ static inline void bw_dist_set_distortion(
static inline void bw_dist_set_tone( static inline void bw_dist_set_tone(
bw_dist_coeffs * BW_RESTRICT coeffs, bw_dist_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -598,7 +603,7 @@ static inline void bw_dist_set_tone(
static inline void bw_dist_set_volume( static inline void bw_dist_set_volume(
bw_dist_coeffs * BW_RESTRICT coeffs, bw_dist_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dist_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dist_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -612,7 +617,7 @@ static inline void bw_dist_set_volume(
static inline char bw_dist_coeffs_is_valid( static inline char bw_dist_coeffs_is_valid(
const bw_dist_coeffs * BW_RESTRICT coeffs) { const bw_dist_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_dist_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_dist_coeffs"))
@ -632,21 +637,21 @@ static inline char bw_dist_coeffs_is_valid(
static inline char bw_dist_state_is_valid( static inline char bw_dist_state_is_valid(
const bw_dist_coeffs * BW_RESTRICT coeffs, const bw_dist_coeffs * BW_RESTRICT coeffs,
const bw_dist_state * BW_RESTRICT state) { const bw_dist_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_dist_state")) if (state->hash != bw_hash_sdbm("bw_dist_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_coeffs : NULL, &state->hp1_state) return bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_coeffs : BW_NULL, &state->hp1_state)
&& bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : NULL, &state->peak_state) && bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : BW_NULL, &state->peak_state)
&& bw_clip_state_is_valid(coeffs ? &coeffs->clip_coeffs : NULL, &state->clip_state) && bw_clip_state_is_valid(coeffs ? &coeffs->clip_coeffs : BW_NULL, &state->clip_state)
&& bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : NULL, &state->satur_state) && bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : BW_NULL, &state->satur_state)
&& bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : NULL, &state->lp1_state); && bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : BW_NULL, &state->lp1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_common bw_gain bw_hs1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak * bw_common bw_gain bw_hs1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak
* bw_satur bw_svf * bw_satur bw_svf
@ -32,6 +32,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Improved algorithm to be a bit more faithful to the * <li>Improved algorithm to be a bit more faithful to the
@ -141,7 +146,7 @@ static inline void bw_drive_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_drive_update_coeffs_ctrl() * #### bw_drive_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -254,8 +259,8 @@ static inline char bw_drive_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_drive_state`. * than or equal to that of `bw_drive_state`.
@ -322,7 +327,7 @@ struct bw_drive_state {
static inline void bw_drive_init( static inline void bw_drive_init(
bw_drive_coeffs * BW_RESTRICT coeffs) { bw_drive_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->hp2_coeffs); bw_svf_init(&coeffs->hp2_coeffs);
bw_hs1_init(&coeffs->hs1_coeffs); bw_hs1_init(&coeffs->hs1_coeffs);
@ -352,7 +357,7 @@ static inline void bw_drive_init(
static inline void bw_drive_set_sample_rate( static inline void bw_drive_set_sample_rate(
bw_drive_coeffs * BW_RESTRICT coeffs, bw_drive_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -376,7 +381,7 @@ static inline void bw_drive_set_sample_rate(
static inline void bw_drive_reset_coeffs( static inline void bw_drive_reset_coeffs(
bw_drive_coeffs * BW_RESTRICT coeffs) { bw_drive_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_set_sample_rate);
@ -396,10 +401,10 @@ static inline float bw_drive_reset_state(
const bw_drive_coeffs * BW_RESTRICT coeffs, const bw_drive_coeffs * BW_RESTRICT coeffs,
bw_drive_state * BW_RESTRICT state, bw_drive_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float v_lp, v_hp, v_bp; float v_lp, v_hp, v_bp;
@ -428,18 +433,18 @@ static inline void bw_drive_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_drive_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_drive_reset_state(coeffs, state[i], x_0[i]);
else else
@ -448,12 +453,12 @@ static inline void bw_drive_reset_state_multi(
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_drive_update_coeffs_ctrl( static inline void bw_drive_update_coeffs_ctrl(
bw_drive_coeffs * BW_RESTRICT coeffs) { bw_drive_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
@ -467,7 +472,7 @@ static inline void bw_drive_update_coeffs_ctrl(
static inline void bw_drive_update_coeffs_audio( static inline void bw_drive_update_coeffs_audio(
bw_drive_coeffs * BW_RESTRICT coeffs) { bw_drive_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
@ -483,10 +488,10 @@ static inline float bw_drive_process1(
const bw_drive_coeffs * BW_RESTRICT coeffs, const bw_drive_coeffs * BW_RESTRICT coeffs,
bw_drive_state * BW_RESTRICT state, bw_drive_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_drive_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_drive_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -512,14 +517,14 @@ static inline void bw_drive_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_drive_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_drive_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_drive_update_coeffs_ctrl(coeffs); bw_drive_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -540,17 +545,17 @@ static inline void bw_drive_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -571,7 +576,7 @@ static inline void bw_drive_process_multi(
static inline void bw_drive_set_drive( static inline void bw_drive_set_drive(
bw_drive_coeffs * BW_RESTRICT coeffs, bw_drive_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -586,7 +591,7 @@ static inline void bw_drive_set_drive(
static inline void bw_drive_set_tone( static inline void bw_drive_set_tone(
bw_drive_coeffs * BW_RESTRICT coeffs, bw_drive_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -601,7 +606,7 @@ static inline void bw_drive_set_tone(
static inline void bw_drive_set_volume( static inline void bw_drive_set_volume(
bw_drive_coeffs * BW_RESTRICT coeffs, bw_drive_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_drive_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_drive_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -615,7 +620,7 @@ static inline void bw_drive_set_volume(
static inline char bw_drive_coeffs_is_valid( static inline char bw_drive_coeffs_is_valid(
const bw_drive_coeffs * BW_RESTRICT coeffs) { const bw_drive_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_drive_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_drive_coeffs"))
@ -635,21 +640,21 @@ static inline char bw_drive_coeffs_is_valid(
static inline char bw_drive_state_is_valid( static inline char bw_drive_state_is_valid(
const bw_drive_coeffs * BW_RESTRICT coeffs, const bw_drive_coeffs * BW_RESTRICT coeffs,
const bw_drive_state * BW_RESTRICT state) { const bw_drive_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_drive_state")) if (state->hash != bw_hash_sdbm("bw_drive_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->hp2_coeffs : NULL, &state->hp2_state) return bw_svf_state_is_valid(coeffs ? &coeffs->hp2_coeffs : BW_NULL, &state->hp2_state)
&& bw_hs1_state_is_valid(coeffs ? &coeffs->hs1_coeffs : NULL, &state->hs1_state) && bw_hs1_state_is_valid(coeffs ? &coeffs->hs1_coeffs : BW_NULL, &state->hs1_state)
&& bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : NULL, &state->peak_state) && bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : BW_NULL, &state->peak_state)
&& bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : NULL, &state->satur_state) && bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : BW_NULL, &state->satur_state)
&& bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : NULL, &state->lp1_state); && bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : BW_NULL, &state->lp1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_one_pole }}} * requires {{{ bw_common bw_gain bw_math bw_one_pole }}}
* description {{{ * description {{{
* Dry/wet mixer. * Dry/wet mixer.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Module renamed as bw_dry_wet.</li> * <li>Module renamed as bw_dry_wet.</li>
@ -220,7 +225,7 @@ struct bw_dry_wet_coeffs {
static inline void bw_dry_wet_init( static inline void bw_dry_wet_init(
bw_dry_wet_coeffs * BW_RESTRICT coeffs) { bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_gain_init(&coeffs->gain_coeffs); bw_gain_init(&coeffs->gain_coeffs);
@ -235,7 +240,7 @@ static inline void bw_dry_wet_init(
static inline void bw_dry_wet_set_sample_rate( static inline void bw_dry_wet_set_sample_rate(
bw_dry_wet_coeffs * BW_RESTRICT coeffs, bw_dry_wet_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -251,7 +256,7 @@ static inline void bw_dry_wet_set_sample_rate(
static inline void bw_dry_wet_reset_coeffs( static inline void bw_dry_wet_reset_coeffs(
bw_dry_wet_coeffs * BW_RESTRICT coeffs) { bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_set_sample_rate);
@ -266,7 +271,7 @@ static inline void bw_dry_wet_reset_coeffs(
static inline void bw_dry_wet_update_coeffs_ctrl( static inline void bw_dry_wet_update_coeffs_ctrl(
bw_dry_wet_coeffs * BW_RESTRICT coeffs) { bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
@ -278,7 +283,7 @@ static inline void bw_dry_wet_update_coeffs_ctrl(
static inline void bw_dry_wet_update_coeffs_audio( static inline void bw_dry_wet_update_coeffs_audio(
bw_dry_wet_coeffs * BW_RESTRICT coeffs) { bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
@ -292,7 +297,7 @@ static inline float bw_dry_wet_process1(
const bw_dry_wet_coeffs * BW_RESTRICT coeffs, const bw_dry_wet_coeffs * BW_RESTRICT coeffs,
float x_dry, float x_dry,
float x_wet) { float x_wet) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x_dry)); BW_ASSERT(bw_is_finite(x_dry));
@ -313,14 +318,14 @@ static inline void bw_dry_wet_process(
const float * x_wet, const float * x_wet,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
BW_ASSERT(x_dry != NULL); BW_ASSERT(x_dry != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_dry, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_dry, n_samples));
BW_ASSERT(x_wet != NULL); BW_ASSERT(x_wet != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_wet, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_wet, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_dry_wet_update_coeffs_ctrl(coeffs); bw_dry_wet_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -340,12 +345,12 @@ static inline void bw_dry_wet_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_reset_coeffs);
BW_ASSERT(x_dry != NULL); BW_ASSERT(x_dry != BW_NULL);
BW_ASSERT(x_wet != NULL); BW_ASSERT(x_wet != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -366,7 +371,7 @@ static inline void bw_dry_wet_process_multi(
static inline void bw_dry_wet_set_wet( static inline void bw_dry_wet_set_wet(
bw_dry_wet_coeffs * BW_RESTRICT coeffs, bw_dry_wet_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -381,7 +386,7 @@ static inline void bw_dry_wet_set_wet(
static inline void bw_dry_wet_set_smooth_tau( static inline void bw_dry_wet_set_smooth_tau(
bw_dry_wet_coeffs * BW_RESTRICT coeffs, bw_dry_wet_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_dry_wet_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_dry_wet_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -395,7 +400,7 @@ static inline void bw_dry_wet_set_smooth_tau(
static inline char bw_dry_wet_coeffs_is_valid( static inline char bw_dry_wet_coeffs_is_valid(
const bw_dry_wet_coeffs * BW_RESTRICT coeffs) { const bw_dry_wet_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_dry_wet_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_dry_wet_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Envelope follower made of a full-wave rectifier followed by * Envelope follower made of a full-wave rectifier followed by
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input value to * <li>Added initial input value to
@ -151,7 +156,7 @@ static inline void bw_env_follow_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_env_follow_update_coeffs_ctrl() * #### bw_env_follow_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -190,7 +195,7 @@ static inline void bw_env_follow_process(
* first `n_samples` of the output buffer `y`, while using and updating both * first `n_samples` of the output buffer `y`, while using and updating both
* `coeffs` and `state` (control and audio rate). * `coeffs` and `state` (control and audio rate).
* *
* `y` may be `NULL`. * `y` may be `BW_NULL`.
* *
* #### bw_env_follow_process_multi() * #### bw_env_follow_process_multi()
* ```>>> */ * ```>>> */
@ -207,7 +212,7 @@ static inline void bw_env_follow_process_multi(
* using and updating both the common `coeffs` and each of the `n_channels` * using and updating both the common `coeffs` and each of the `n_channels`
* `state`s (control and audio rate). * `state`s (control and audio rate).
* *
* `y` or any element of `y` may be `NULL`. * `y` or any element of `y` may be `BW_NULL`.
* *
* #### bw_env_follow_set_attack_tau() * #### bw_env_follow_set_attack_tau()
* ```>>> */ * ```>>> */
@ -264,8 +269,8 @@ static inline char bw_env_follow_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_env_follow_state`. * than or equal to that of `bw_env_follow_state`.
@ -319,7 +324,7 @@ struct bw_env_follow_state {
static inline void bw_env_follow_init( static inline void bw_env_follow_init(
bw_env_follow_coeffs * BW_RESTRICT coeffs) { bw_env_follow_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->one_pole_coeffs); bw_one_pole_init(&coeffs->one_pole_coeffs);
@ -335,7 +340,7 @@ static inline void bw_env_follow_init(
static inline void bw_env_follow_set_sample_rate( static inline void bw_env_follow_set_sample_rate(
bw_env_follow_coeffs * BW_RESTRICT coeffs, bw_env_follow_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -351,7 +356,7 @@ static inline void bw_env_follow_set_sample_rate(
static inline void bw_env_follow_reset_coeffs( static inline void bw_env_follow_reset_coeffs(
bw_env_follow_coeffs * BW_RESTRICT coeffs) { bw_env_follow_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_set_sample_rate);
@ -369,10 +374,10 @@ static inline float bw_env_follow_reset_state(
const bw_env_follow_coeffs * BW_RESTRICT coeffs, const bw_env_follow_coeffs * BW_RESTRICT coeffs,
bw_env_follow_state * BW_RESTRICT state, bw_env_follow_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float x = bw_absf(x_0); const float x = bw_absf(x_0);
@ -396,18 +401,18 @@ static inline void bw_env_follow_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_env_follow_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_env_follow_reset_state(coeffs, state[i], x_0[i]);
else else
@ -416,12 +421,12 @@ static inline void bw_env_follow_reset_state_multi(
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_env_follow_update_coeffs_ctrl( static inline void bw_env_follow_update_coeffs_ctrl(
bw_env_follow_coeffs * BW_RESTRICT coeffs) { bw_env_follow_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
@ -433,7 +438,7 @@ static inline void bw_env_follow_update_coeffs_ctrl(
static inline void bw_env_follow_update_coeffs_audio( static inline void bw_env_follow_update_coeffs_audio(
bw_env_follow_coeffs * BW_RESTRICT coeffs) { bw_env_follow_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
@ -447,10 +452,10 @@ static inline float bw_env_follow_process1(
const bw_env_follow_coeffs * BW_RESTRICT coeffs, const bw_env_follow_coeffs * BW_RESTRICT coeffs,
bw_env_follow_state * BW_RESTRICT state, bw_env_follow_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -471,16 +476,16 @@ static inline void bw_env_follow_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
bw_env_follow_update_coeffs_ctrl(coeffs); bw_env_follow_update_coeffs_ctrl(coeffs);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_env_follow_update_coeffs_audio(coeffs); bw_env_follow_update_coeffs_audio(coeffs);
y[i] = bw_env_follow_process1(coeffs, state, x[i]); y[i] = bw_env_follow_process1(coeffs, state, x[i]);
@ -494,7 +499,7 @@ static inline void bw_env_follow_process(
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_follow_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
} }
static inline void bw_env_follow_process_multi( static inline void bw_env_follow_process_multi(
@ -504,30 +509,30 @@ static inline void bw_env_follow_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] == NULL || y[j] == NULL || y[i] != y[j]); BW_ASSERT(y[i] == BW_NULL || y[j] == BW_NULL || y[i] != y[j]);
#endif #endif
bw_env_follow_update_coeffs_ctrl(coeffs); bw_env_follow_update_coeffs_ctrl(coeffs);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_env_follow_update_coeffs_audio(coeffs); bw_env_follow_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
const float v = bw_env_follow_process1(coeffs, state[j], x[j][i]); const float v = bw_env_follow_process1(coeffs, state[j], x[j][i]);
if (y[j] != NULL) if (y[j] != BW_NULL)
y[j][i] = v; y[j][i] = v;
} }
} }
@ -545,7 +550,7 @@ static inline void bw_env_follow_process_multi(
static inline void bw_env_follow_set_attack_tau( static inline void bw_env_follow_set_attack_tau(
bw_env_follow_coeffs * BW_RESTRICT coeffs, bw_env_follow_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -560,7 +565,7 @@ static inline void bw_env_follow_set_attack_tau(
static inline void bw_env_follow_set_release_tau( static inline void bw_env_follow_set_release_tau(
bw_env_follow_coeffs * BW_RESTRICT coeffs, bw_env_follow_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_follow_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_follow_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -574,15 +579,15 @@ static inline void bw_env_follow_set_release_tau(
static inline float bw_env_follow_get_y_z1( static inline float bw_env_follow_get_y_z1(
const bw_env_follow_state * BW_RESTRICT state) { const bw_env_follow_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_follow_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_env_follow_state_is_valid(BW_NULL, state));
return bw_one_pole_get_y_z1(&state->one_pole_state); return bw_one_pole_get_y_z1(&state->one_pole_state);
} }
static inline char bw_env_follow_coeffs_is_valid( static inline char bw_env_follow_coeffs_is_valid(
const bw_env_follow_coeffs * BW_RESTRICT coeffs) { const bw_env_follow_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_env_follow_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_env_follow_coeffs"))
@ -597,17 +602,17 @@ static inline char bw_env_follow_coeffs_is_valid(
static inline char bw_env_follow_state_is_valid( static inline char bw_env_follow_state_is_valid(
const bw_env_follow_coeffs * BW_RESTRICT coeffs, const bw_env_follow_coeffs * BW_RESTRICT coeffs,
const bw_env_follow_state * BW_RESTRICT state) { const bw_env_follow_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_env_follow_state")) if (state->hash != bw_hash_sdbm("bw_env_follow_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_one_pole_state_is_valid(coeffs ? &coeffs->one_pole_coeffs : NULL, &state->one_pole_state); return bw_one_pole_state_is_valid(coeffs ? &coeffs->one_pole_coeffs : BW_NULL, &state->one_pole_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -43,6 +43,7 @@
* <li>Version <strong>1.1.0</strong>: * <li>Version <strong>1.1.0</strong>:
* <ul> * <ul>
* <li>Added skip_sustain and always_reach_sustain parameters.</li> * <li>Added skip_sustain and always_reach_sustain parameters.</li>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul> * </ul>
* </li> * </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
@ -200,7 +201,7 @@ static inline void bw_env_gen_reset_state_multi(
* non-`0` for on) in the `gate_0` array. * non-`0` for on) in the `gate_0` array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_env_gen_update_coeffs_ctrl() * #### bw_env_gen_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -248,7 +249,7 @@ static inline void bw_env_gen_process(
* the given `gate` value (`0` for off, non-`0` for on), while using and * the given `gate` value (`0` for off, non-`0` for on), while using and
* updating both `coeffs` and `state` (control and audio rate). * updating both `coeffs` and `state` (control and audio rate).
* *
* `y` may be `NULL`. * `y` may be `BW_NULL`.
* *
* #### bw_env_gen_process_multi() * #### bw_env_gen_process_multi()
* ```>>> */ * ```>>> */
@ -265,7 +266,7 @@ static inline void bw_env_gen_process_multi(
* non-`0` for on), while using and updating both the common `coeffs` and * non-`0` for on), while using and updating both the common `coeffs` and
* each of the `n_channels` `state`s (control and audio rate). * each of the `n_channels` `state`s (control and audio rate).
* *
* `y` or any element of `y` may be `NULL`. * `y` or any element of `y` may be `BW_NULL`.
* *
* #### bw_env_gen_set_attack() * #### bw_env_gen_set_attack()
* ```>>> */ * ```>>> */
@ -372,8 +373,8 @@ static inline char bw_env_gen_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_env_gen_state`. * than or equal to that of `bw_env_gen_state`.
@ -452,7 +453,7 @@ struct bw_env_gen_state {
static inline void bw_env_gen_init( static inline void bw_env_gen_init(
bw_env_gen_coeffs * BW_RESTRICT coeffs) { bw_env_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
@ -475,7 +476,7 @@ static inline void bw_env_gen_init(
static inline void bw_env_gen_set_sample_rate( static inline void bw_env_gen_set_sample_rate(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -509,7 +510,7 @@ static inline void bw_env_gen_do_update_coeffs_ctrl(
static inline void bw_env_gen_reset_coeffs( static inline void bw_env_gen_reset_coeffs(
bw_env_gen_coeffs * BW_RESTRICT coeffs) { bw_env_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_set_sample_rate);
@ -528,10 +529,10 @@ static inline float bw_env_gen_reset_state(
const bw_env_gen_coeffs * BW_RESTRICT coeffs, const bw_env_gen_coeffs * BW_RESTRICT coeffs,
bw_env_gen_state * BW_RESTRICT state, bw_env_gen_state * BW_RESTRICT state,
char gate_0) { char gate_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &state->smooth_state, coeffs->sustain); bw_one_pole_reset_state(&coeffs->smooth_coeffs, &state->smooth_state, coeffs->sustain);
if (gate_0) { if (gate_0) {
@ -561,18 +562,18 @@ static inline void bw_env_gen_reset_state_multi(
const char * BW_RESTRICT gate_0, const char * BW_RESTRICT gate_0,
float * BW_RESTRICT y_0, float * BW_RESTRICT y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(gate_0 != NULL); BW_ASSERT(gate_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_env_gen_reset_state(coeffs, state[i], gate_0[i]); y_0[i] = bw_env_gen_reset_state(coeffs, state[i], gate_0[i]);
else else
@ -581,12 +582,12 @@ static inline void bw_env_gen_reset_state_multi(
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_env_gen_update_coeffs_ctrl( static inline void bw_env_gen_update_coeffs_ctrl(
bw_env_gen_coeffs * BW_RESTRICT coeffs) { bw_env_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
@ -598,7 +599,7 @@ static inline void bw_env_gen_update_coeffs_ctrl(
static inline void bw_env_gen_update_coeffs_audio( static inline void bw_env_gen_update_coeffs_audio(
bw_env_gen_coeffs * BW_RESTRICT coeffs) { bw_env_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
@ -609,10 +610,10 @@ static inline void bw_env_gen_process_ctrl(
const bw_env_gen_coeffs * BW_RESTRICT coeffs, const bw_env_gen_coeffs * BW_RESTRICT coeffs,
bw_env_gen_state * BW_RESTRICT state, bw_env_gen_state * BW_RESTRICT state,
char gate) { char gate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state));
if (gate) { if (gate) {
@ -631,10 +632,10 @@ static inline void bw_env_gen_process_ctrl(
static inline float bw_env_gen_process1( static inline float bw_env_gen_process1(
const bw_env_gen_coeffs * BW_RESTRICT coeffs, const bw_env_gen_coeffs * BW_RESTRICT coeffs,
bw_env_gen_state * BW_RESTRICT state) { bw_env_gen_state * BW_RESTRICT state) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state));
uint32_t v = 0; uint32_t v = 0;
@ -686,15 +687,15 @@ static inline void bw_env_gen_process(
char gate, char gate,
float * BW_RESTRICT y, float * BW_RESTRICT y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state));
bw_env_gen_update_coeffs_ctrl(coeffs); bw_env_gen_update_coeffs_ctrl(coeffs);
bw_env_gen_process_ctrl(coeffs, state, gate); bw_env_gen_process_ctrl(coeffs, state, gate);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[i] = bw_env_gen_process1(coeffs, state); y[i] = bw_env_gen_process1(coeffs, state);
else else
@ -704,7 +705,7 @@ static inline void bw_env_gen_process(
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
} }
static inline void bw_env_gen_process_multi( static inline void bw_env_gen_process_multi(
@ -714,31 +715,31 @@ static inline void bw_env_gen_process_multi(
float * BW_RESTRICT const * BW_RESTRICT y, float * BW_RESTRICT const * BW_RESTRICT y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(gate != NULL); BW_ASSERT(gate != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] == NULL || y[j] == NULL || y[i] != y[j]); BW_ASSERT(y[i] == BW_NULL || y[j] == BW_NULL || y[i] != y[j]);
#endif #endif
bw_env_gen_update_coeffs_ctrl(coeffs); bw_env_gen_update_coeffs_ctrl(coeffs);
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
bw_env_gen_process_ctrl(coeffs, state[j], gate[j]); bw_env_gen_process_ctrl(coeffs, state[j], gate[j]);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
const float v = bw_env_gen_process1(coeffs, state[j]); const float v = bw_env_gen_process1(coeffs, state[j]);
if (y[j] != NULL) if (y[j] != BW_NULL)
y[j][i] = v; y[j][i] = v;
} }
else else
@ -753,7 +754,7 @@ static inline void bw_env_gen_process_multi(
static inline void bw_env_gen_set_attack( static inline void bw_env_gen_set_attack(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -774,7 +775,7 @@ static inline void bw_env_gen_set_attack(
static inline void bw_env_gen_set_decay( static inline void bw_env_gen_set_decay(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -795,7 +796,7 @@ static inline void bw_env_gen_set_decay(
static inline void bw_env_gen_set_sustain( static inline void bw_env_gen_set_sustain(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -816,7 +817,7 @@ static inline void bw_env_gen_set_sustain(
static inline void bw_env_gen_set_release( static inline void bw_env_gen_set_release(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -837,7 +838,7 @@ static inline void bw_env_gen_set_release(
static inline void bw_env_gen_set_skip_sustain( static inline void bw_env_gen_set_skip_sustain(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
@ -850,7 +851,7 @@ static inline void bw_env_gen_set_skip_sustain(
static inline void bw_env_gen_set_always_reach_sustain( static inline void bw_env_gen_set_always_reach_sustain(
bw_env_gen_coeffs * BW_RESTRICT coeffs, bw_env_gen_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_env_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_env_gen_coeffs_state_init);
@ -862,16 +863,16 @@ static inline void bw_env_gen_set_always_reach_sustain(
static inline bw_env_gen_phase bw_env_gen_get_phase( static inline bw_env_gen_phase bw_env_gen_get_phase(
const bw_env_gen_state * BW_RESTRICT state) { const bw_env_gen_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(BW_NULL, state));
return state->phase; return state->phase;
} }
static inline float bw_env_gen_get_y_z1( static inline float bw_env_gen_get_y_z1(
const bw_env_gen_state * BW_RESTRICT state) { const bw_env_gen_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_env_gen_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_env_gen_state_is_valid(BW_NULL, state));
const float y = (1.f / (float)BW_ENV_V_MAX) * state->v; const float y = (1.f / (float)BW_ENV_V_MAX) * state->v;
@ -882,7 +883,7 @@ static inline float bw_env_gen_get_y_z1(
static inline char bw_env_gen_coeffs_is_valid( static inline char bw_env_gen_coeffs_is_valid(
const bw_env_gen_coeffs * BW_RESTRICT coeffs) { const bw_env_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_env_gen_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_env_gen_coeffs"))
@ -911,18 +912,18 @@ static inline char bw_env_gen_coeffs_is_valid(
static inline char bw_env_gen_state_is_valid( static inline char bw_env_gen_state_is_valid(
const bw_env_gen_coeffs * BW_RESTRICT coeffs, const bw_env_gen_coeffs * BW_RESTRICT coeffs,
const bw_env_gen_state * BW_RESTRICT state) { const bw_env_gen_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_env_gen_state")) if (state->hash != bw_hash_sdbm("bw_env_gen_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return state->phase >= bw_env_gen_phase_off && state->phase <= bw_env_gen_phase_release return state->phase >= bw_env_gen_phase_off && state->phase <= bw_env_gen_phase_release
&& bw_one_pole_state_is_valid(coeffs ? &coeffs->smooth_coeffs : NULL, &state->smooth_state); && bw_one_pole_state_is_valid(coeffs ? &coeffs->smooth_coeffs : BW_NULL, &state->smooth_state);
} }
#undef BW_ENV_GEN_PARAM_ATTACK #undef BW_ENV_GEN_PARAM_ATTACK

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_common bw_gain bw_hp1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak * bw_common bw_gain bw_hp1 bw_lp1 bw_math bw_mm2 bw_one_pole bw_peak
* bw_satur bw_svf * bw_satur bw_svf
@ -32,6 +32,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Improved algorithm to be a bit more faithful to the * <li>Improved algorithm to be a bit more faithful to the
@ -141,7 +146,7 @@ static inline void bw_fuzz_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_fuzz_update_coeffs_ctrl() * #### bw_fuzz_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -242,8 +247,8 @@ static inline char bw_fuzz_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_fuzz_state`. * than or equal to that of `bw_fuzz_state`.
@ -311,7 +316,7 @@ struct bw_fuzz_state {
static inline void bw_fuzz_init( static inline void bw_fuzz_init(
bw_fuzz_coeffs * BW_RESTRICT coeffs) { bw_fuzz_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_hp1_init(&coeffs->hp1_in_coeffs); bw_hp1_init(&coeffs->hp1_in_coeffs);
bw_svf_init(&coeffs->lp2_coeffs); bw_svf_init(&coeffs->lp2_coeffs);
@ -338,7 +343,7 @@ static inline void bw_fuzz_init(
static inline void bw_fuzz_set_sample_rate( static inline void bw_fuzz_set_sample_rate(
bw_fuzz_coeffs * BW_RESTRICT coeffs, bw_fuzz_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -363,7 +368,7 @@ static inline void bw_fuzz_set_sample_rate(
static inline void bw_fuzz_reset_coeffs( static inline void bw_fuzz_reset_coeffs(
bw_fuzz_coeffs * BW_RESTRICT coeffs) { bw_fuzz_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_set_sample_rate);
@ -382,10 +387,10 @@ static inline float bw_fuzz_reset_state(
const bw_fuzz_coeffs * BW_RESTRICT coeffs, const bw_fuzz_coeffs * BW_RESTRICT coeffs,
bw_fuzz_state * BW_RESTRICT state, bw_fuzz_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float y = bw_hp1_reset_state(&coeffs->hp1_in_coeffs, &state->hp1_in_state, x_0); float y = bw_hp1_reset_state(&coeffs->hp1_in_coeffs, &state->hp1_in_state, x_0);
@ -415,18 +420,18 @@ static inline void bw_fuzz_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_fuzz_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_fuzz_reset_state(coeffs, state[i], x_0[i]);
else else
@ -435,12 +440,12 @@ static inline void bw_fuzz_reset_state_multi(
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_fuzz_update_coeffs_ctrl( static inline void bw_fuzz_update_coeffs_ctrl(
bw_fuzz_coeffs * BW_RESTRICT coeffs) { bw_fuzz_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
@ -453,7 +458,7 @@ static inline void bw_fuzz_update_coeffs_ctrl(
static inline void bw_fuzz_update_coeffs_audio( static inline void bw_fuzz_update_coeffs_audio(
bw_fuzz_coeffs * BW_RESTRICT coeffs) { bw_fuzz_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
@ -468,10 +473,10 @@ static inline float bw_fuzz_process1(
const bw_fuzz_coeffs * BW_RESTRICT coeffs, const bw_fuzz_coeffs * BW_RESTRICT coeffs,
bw_fuzz_state * BW_RESTRICT state, bw_fuzz_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_fuzz_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -498,14 +503,14 @@ static inline void bw_fuzz_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_fuzz_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_fuzz_update_coeffs_ctrl(coeffs); bw_fuzz_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -526,17 +531,17 @@ static inline void bw_fuzz_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -557,7 +562,7 @@ static inline void bw_fuzz_process_multi(
static inline void bw_fuzz_set_fuzz( static inline void bw_fuzz_set_fuzz(
bw_fuzz_coeffs * BW_RESTRICT coeffs, bw_fuzz_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -572,7 +577,7 @@ static inline void bw_fuzz_set_fuzz(
static inline void bw_fuzz_set_volume( static inline void bw_fuzz_set_volume(
bw_fuzz_coeffs * BW_RESTRICT coeffs, bw_fuzz_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_fuzz_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_fuzz_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -586,7 +591,7 @@ static inline void bw_fuzz_set_volume(
static inline char bw_fuzz_coeffs_is_valid( static inline char bw_fuzz_coeffs_is_valid(
const bw_fuzz_coeffs * BW_RESTRICT coeffs) { const bw_fuzz_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_fuzz_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_fuzz_coeffs"))
@ -606,22 +611,22 @@ static inline char bw_fuzz_coeffs_is_valid(
static inline char bw_fuzz_state_is_valid( static inline char bw_fuzz_state_is_valid(
const bw_fuzz_coeffs * BW_RESTRICT coeffs, const bw_fuzz_coeffs * BW_RESTRICT coeffs,
const bw_fuzz_state * BW_RESTRICT state) { const bw_fuzz_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_fuzz_state")) if (state->hash != bw_hash_sdbm("bw_fuzz_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_in_coeffs : NULL, &state->hp1_in_state) return bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_in_coeffs : BW_NULL, &state->hp1_in_state)
&& bw_svf_state_is_valid(coeffs ? &coeffs->lp2_coeffs : NULL, &state->lp2_1_state) && bw_svf_state_is_valid(coeffs ? &coeffs->lp2_coeffs : BW_NULL, &state->lp2_1_state)
&& bw_svf_state_is_valid(coeffs ? &coeffs->lp2_coeffs : NULL, &state->lp2_2_state) && bw_svf_state_is_valid(coeffs ? &coeffs->lp2_coeffs : BW_NULL, &state->lp2_2_state)
&& bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : NULL, &state->peak_state) && bw_peak_state_is_valid(coeffs ? &coeffs->peak_coeffs : BW_NULL, &state->peak_state)
&& bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : NULL, &state->satur_state) && bw_satur_state_is_valid(coeffs ? &coeffs->satur_coeffs : BW_NULL, &state->satur_state)
&& bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_out_coeffs : NULL, &state->hp1_out_state); && bw_hp1_state_is_valid(coeffs ? &coeffs->hp1_out_coeffs : BW_NULL, &state->hp1_out_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Gain. * Gain.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_gain_get_gain_lin()</code>.</li> * <li>Added <code>bw_gain_get_gain_lin()</code>.</li>
@ -272,7 +277,7 @@ struct bw_gain_coeffs {
static inline void bw_gain_init( static inline void bw_gain_init(
bw_gain_coeffs * BW_RESTRICT coeffs) { bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
@ -289,7 +294,7 @@ static inline void bw_gain_init(
static inline void bw_gain_set_sample_rate( static inline void bw_gain_set_sample_rate(
bw_gain_coeffs * BW_RESTRICT coeffs, bw_gain_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -305,7 +310,7 @@ static inline void bw_gain_set_sample_rate(
static inline void bw_gain_reset_coeffs( static inline void bw_gain_reset_coeffs(
bw_gain_coeffs * BW_RESTRICT coeffs) { bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_set_sample_rate);
@ -321,7 +326,7 @@ static inline void bw_gain_reset_coeffs(
static inline void bw_gain_update_coeffs_ctrl( static inline void bw_gain_update_coeffs_ctrl(
bw_gain_coeffs * BW_RESTRICT coeffs) { bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
@ -333,7 +338,7 @@ static inline void bw_gain_update_coeffs_ctrl(
static inline void bw_gain_update_coeffs_audio( static inline void bw_gain_update_coeffs_audio(
bw_gain_coeffs * BW_RESTRICT coeffs) { bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
@ -347,7 +352,7 @@ static inline void bw_gain_update_coeffs_audio(
static inline float bw_gain_process1( static inline float bw_gain_process1(
const bw_gain_coeffs * BW_RESTRICT coeffs, const bw_gain_coeffs * BW_RESTRICT coeffs,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -366,12 +371,12 @@ static inline void bw_gain_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_gain_update_coeffs_ctrl(coeffs); bw_gain_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -390,11 +395,11 @@ static inline void bw_gain_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -415,7 +420,7 @@ static inline void bw_gain_process_multi(
static inline void bw_gain_set_gain_lin( static inline void bw_gain_set_gain_lin(
bw_gain_coeffs * BW_RESTRICT coeffs, bw_gain_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -429,7 +434,7 @@ static inline void bw_gain_set_gain_lin(
static inline void bw_gain_set_gain_dB( static inline void bw_gain_set_gain_dB(
bw_gain_coeffs * BW_RESTRICT coeffs, bw_gain_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -444,7 +449,7 @@ static inline void bw_gain_set_gain_dB(
static inline void bw_gain_set_smooth_tau( static inline void bw_gain_set_smooth_tau(
bw_gain_coeffs * BW_RESTRICT coeffs, bw_gain_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -458,7 +463,7 @@ static inline void bw_gain_set_smooth_tau(
static inline float bw_gain_get_gain_lin( static inline float bw_gain_get_gain_lin(
const bw_gain_coeffs * BW_RESTRICT coeffs) { const bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
return coeffs->gain; return coeffs->gain;
@ -466,7 +471,7 @@ static inline float bw_gain_get_gain_lin(
static inline float bw_gain_get_gain_cur( static inline float bw_gain_get_gain_cur(
const bw_gain_coeffs * BW_RESTRICT coeffs) { const bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_gain_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_gain_coeffs_state_reset_coeffs);
@ -475,7 +480,7 @@ static inline float bw_gain_get_gain_cur(
static inline char bw_gain_coeffs_is_valid( static inline char bw_gain_coeffs_is_valid(
const bw_gain_coeffs * BW_RESTRICT coeffs) { const bw_gain_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_gain_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_gain_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_lp1 bw_math bw_one_pole }}} * requires {{{ bw_common bw_lp1 bw_math bw_one_pole }}}
* description {{{ * description {{{
* First-order highpass filter (6 dB/oct) with gain asymptotically * First-order highpass filter (6 dB/oct) with gain asymptotically
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_hp1_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_hp1_reset_state_multi()</code> and updated C++
@ -146,7 +151,7 @@ static inline void bw_hp1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_hp1_update_coeffs_ctrl() * #### bw_hp1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -260,8 +265,8 @@ static inline char bw_hp1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_hp1_state`. * than or equal to that of `bw_hp1_state`.
@ -314,7 +319,7 @@ struct bw_hp1_state {
static inline void bw_hp1_init( static inline void bw_hp1_init(
bw_hp1_coeffs * BW_RESTRICT coeffs) { bw_hp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_lp1_init(&coeffs->lp1_coeffs); bw_lp1_init(&coeffs->lp1_coeffs);
@ -330,7 +335,7 @@ static inline void bw_hp1_init(
static inline void bw_hp1_set_sample_rate( static inline void bw_hp1_set_sample_rate(
bw_hp1_coeffs * BW_RESTRICT coeffs, bw_hp1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -346,7 +351,7 @@ static inline void bw_hp1_set_sample_rate(
static inline void bw_hp1_reset_coeffs( static inline void bw_hp1_reset_coeffs(
bw_hp1_coeffs * BW_RESTRICT coeffs) { bw_hp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_set_sample_rate);
@ -364,10 +369,10 @@ static inline float bw_hp1_reset_state(
const bw_hp1_coeffs * BW_RESTRICT coeffs, const bw_hp1_coeffs * BW_RESTRICT coeffs,
bw_hp1_state * BW_RESTRICT state, bw_hp1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0); const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0);
@ -391,31 +396,31 @@ static inline void bw_hp1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_hp1_reset_state(coeffs, state[i], x_0[i]); bw_hp1_reset_state(coeffs, state[i], x_0[i]);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = 0.f; y_0[i] = 0.f;
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_hp1_update_coeffs_ctrl( static inline void bw_hp1_update_coeffs_ctrl(
bw_hp1_coeffs * BW_RESTRICT coeffs) { bw_hp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
@ -427,7 +432,7 @@ static inline void bw_hp1_update_coeffs_ctrl(
static inline void bw_hp1_update_coeffs_audio( static inline void bw_hp1_update_coeffs_audio(
bw_hp1_coeffs * BW_RESTRICT coeffs) { bw_hp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
@ -441,10 +446,10 @@ static inline float bw_hp1_process1(
const bw_hp1_coeffs * BW_RESTRICT coeffs, const bw_hp1_coeffs * BW_RESTRICT coeffs,
bw_hp1_state * BW_RESTRICT state, bw_hp1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hp1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -465,14 +470,14 @@ static inline void bw_hp1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hp1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_hp1_update_coeffs_ctrl(coeffs); bw_hp1_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -493,17 +498,17 @@ static inline void bw_hp1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -524,7 +529,7 @@ static inline void bw_hp1_process_multi(
static inline void bw_hp1_set_cutoff( static inline void bw_hp1_set_cutoff(
bw_hp1_coeffs * BW_RESTRICT coeffs, bw_hp1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -539,7 +544,7 @@ static inline void bw_hp1_set_cutoff(
static inline void bw_hp1_set_prewarp_at_cutoff( static inline void bw_hp1_set_prewarp_at_cutoff(
bw_hp1_coeffs * BW_RESTRICT coeffs, bw_hp1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init);
@ -552,7 +557,7 @@ static inline void bw_hp1_set_prewarp_at_cutoff(
static inline void bw_hp1_set_prewarp_freq( static inline void bw_hp1_set_prewarp_freq(
bw_hp1_coeffs * BW_RESTRICT coeffs, bw_hp1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -566,7 +571,7 @@ static inline void bw_hp1_set_prewarp_freq(
static inline char bw_hp1_coeffs_is_valid( static inline char bw_hp1_coeffs_is_valid(
const bw_hp1_coeffs * BW_RESTRICT coeffs) { const bw_hp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_hp1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_hp1_coeffs"))
@ -581,17 +586,17 @@ static inline char bw_hp1_coeffs_is_valid(
static inline char bw_hp1_state_is_valid( static inline char bw_hp1_state_is_valid(
const bw_hp1_coeffs * BW_RESTRICT coeffs, const bw_hp1_coeffs * BW_RESTRICT coeffs,
const bw_hp1_state * BW_RESTRICT state) { const bw_hp1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_hp1_state")) if (state->hash != bw_hash_sdbm("bw_hp1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : NULL, &state->lp1_state); return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : BW_NULL, &state->lp1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_lp1 bw_math bw_mm1 bw_one_pole }}} * requires {{{ bw_common bw_gain bw_lp1 bw_math bw_mm1 bw_one_pole }}}
* description {{{ * description {{{
* First-order high shelf filter (6 dB/oct) with unitary DC gain. * First-order high shelf filter (6 dB/oct) with unitary DC gain.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_hs1_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_hs1_reset_state_multi()</code> and updated C++
@ -147,7 +152,7 @@ static inline void bw_hs1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_hs1_update_coeffs_ctrl() * #### bw_hs1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -302,8 +307,8 @@ static inline char bw_hs1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_hs1_state`. * than or equal to that of `bw_hs1_state`.
@ -364,7 +369,7 @@ struct bw_hs1_state {
static inline void bw_hs1_init( static inline void bw_hs1_init(
bw_hs1_coeffs * BW_RESTRICT coeffs) { bw_hs1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_mm1_init(&coeffs->mm1_coeffs); bw_mm1_init(&coeffs->mm1_coeffs);
bw_mm1_set_prewarp_at_cutoff(&coeffs->mm1_coeffs, 0); bw_mm1_set_prewarp_at_cutoff(&coeffs->mm1_coeffs, 0);
@ -387,7 +392,7 @@ static inline void bw_hs1_init(
static inline void bw_hs1_set_sample_rate( static inline void bw_hs1_set_sample_rate(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -414,7 +419,7 @@ static inline void bw_hs1_update_mm1_params(
static inline void bw_hs1_reset_coeffs( static inline void bw_hs1_reset_coeffs(
bw_hs1_coeffs * BW_RESTRICT coeffs) { bw_hs1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
@ -435,10 +440,10 @@ static inline float bw_hs1_reset_state(
const bw_hs1_coeffs * BW_RESTRICT coeffs, const bw_hs1_coeffs * BW_RESTRICT coeffs,
bw_hs1_state * BW_RESTRICT state, bw_hs1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float y = bw_mm1_reset_state(&coeffs->mm1_coeffs, &state->mm1_state, x_0); const float y = bw_mm1_reset_state(&coeffs->mm1_coeffs, &state->mm1_state, x_0);
@ -461,18 +466,18 @@ static inline void bw_hs1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_hs1_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_hs1_reset_state(coeffs, state[i], x_0[i]);
else else
@ -481,12 +486,12 @@ static inline void bw_hs1_reset_state_multi(
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_hs1_update_coeffs_ctrl( static inline void bw_hs1_update_coeffs_ctrl(
bw_hs1_coeffs * BW_RESTRICT coeffs) { bw_hs1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
@ -500,7 +505,7 @@ static inline void bw_hs1_update_coeffs_ctrl(
static inline void bw_hs1_update_coeffs_audio( static inline void bw_hs1_update_coeffs_audio(
bw_hs1_coeffs * BW_RESTRICT coeffs) { bw_hs1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
@ -515,11 +520,11 @@ static inline float bw_hs1_process1(
const bw_hs1_coeffs * BW_RESTRICT coeffs, const bw_hs1_coeffs * BW_RESTRICT coeffs,
bw_hs1_state * BW_RESTRICT state, bw_hs1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hs1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -539,15 +544,15 @@ static inline void bw_hs1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hs1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_hs1_update_coeffs_ctrl(coeffs); bw_hs1_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -568,18 +573,18 @@ static inline void bw_hs1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(coeffs->high_gain) >= 1e-6f && coeffs->cutoff * bw_sqrtf(coeffs->high_gain) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -600,7 +605,7 @@ static inline void bw_hs1_process_multi(
static inline void bw_hs1_set_cutoff( static inline void bw_hs1_set_cutoff(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -618,7 +623,7 @@ static inline void bw_hs1_set_cutoff(
static inline void bw_hs1_set_prewarp_at_cutoff( static inline void bw_hs1_set_prewarp_at_cutoff(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
@ -631,7 +636,7 @@ static inline void bw_hs1_set_prewarp_at_cutoff(
static inline void bw_hs1_set_prewarp_freq( static inline void bw_hs1_set_prewarp_freq(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -646,7 +651,7 @@ static inline void bw_hs1_set_prewarp_freq(
static inline void bw_hs1_set_high_gain_lin( static inline void bw_hs1_set_high_gain_lin(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -664,7 +669,7 @@ static inline void bw_hs1_set_high_gain_lin(
static inline void bw_hs1_set_high_gain_dB( static inline void bw_hs1_set_high_gain_dB(
bw_hs1_coeffs * BW_RESTRICT coeffs, bw_hs1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -678,7 +683,7 @@ static inline void bw_hs1_set_high_gain_dB(
static inline char bw_hs1_coeffs_is_valid( static inline char bw_hs1_coeffs_is_valid(
const bw_hs1_coeffs * BW_RESTRICT coeffs) { const bw_hs1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_hs1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_hs1_coeffs"))
@ -702,17 +707,17 @@ static inline char bw_hs1_coeffs_is_valid(
static inline char bw_hs1_state_is_valid( static inline char bw_hs1_state_is_valid(
const bw_hs1_coeffs * BW_RESTRICT coeffs, const bw_hs1_coeffs * BW_RESTRICT coeffs,
const bw_hs1_state * BW_RESTRICT state) { const bw_hs1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_hs1_state")) if (state->hash != bw_hash_sdbm("bw_hs1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_mm1_state_is_valid(coeffs ? &coeffs->mm1_coeffs : NULL, &state->mm1_state); return bw_mm1_state_is_valid(coeffs ? &coeffs->mm1_coeffs : BW_NULL, &state->mm1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_mm2 bw_one_pole bw_svf }}} * requires {{{ bw_common bw_gain bw_math bw_mm2 bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Second-order high shelf filter (12 dB/oct) with unitary DC gain. * Second-order high shelf filter (12 dB/oct) with unitary DC gain.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_hs2_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_hs2_reset_state_multi()</code> and updated C++
@ -149,7 +154,7 @@ static inline void bw_hs2_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_hs2_update_coeffs_ctrl() * #### bw_hs2_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -316,8 +321,8 @@ static inline char bw_hs2_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_hs2_state`. * than or equal to that of `bw_hs2_state`.
@ -385,7 +390,7 @@ struct bw_hs2_state {
static inline void bw_hs2_init( static inline void bw_hs2_init(
bw_hs2_coeffs * BW_RESTRICT coeffs) { bw_hs2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_mm2_init(&coeffs->mm2_coeffs); bw_mm2_init(&coeffs->mm2_coeffs);
bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0); bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0);
@ -406,7 +411,7 @@ static inline void bw_hs2_init(
static inline void bw_hs2_set_sample_rate( static inline void bw_hs2_set_sample_rate(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -438,7 +443,7 @@ static inline void bw_hs2_update_mm2_params(
static inline void bw_hs2_reset_coeffs( static inline void bw_hs2_reset_coeffs(
bw_hs2_coeffs * BW_RESTRICT coeffs) { bw_hs2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
@ -459,10 +464,10 @@ static inline float bw_hs2_reset_state(
const bw_hs2_coeffs * BW_RESTRICT coeffs, const bw_hs2_coeffs * BW_RESTRICT coeffs,
bw_hs2_state * BW_RESTRICT state, bw_hs2_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0); const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0);
@ -485,18 +490,18 @@ static inline void bw_hs2_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_hs2_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_hs2_reset_state(coeffs, state[i], x_0[i]);
else else
@ -505,12 +510,12 @@ static inline void bw_hs2_reset_state_multi(
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_hs2_update_coeffs_ctrl( static inline void bw_hs2_update_coeffs_ctrl(
bw_hs2_coeffs * BW_RESTRICT coeffs) { bw_hs2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
@ -524,7 +529,7 @@ static inline void bw_hs2_update_coeffs_ctrl(
static inline void bw_hs2_update_coeffs_audio( static inline void bw_hs2_update_coeffs_audio(
bw_hs2_coeffs * BW_RESTRICT coeffs) { bw_hs2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
@ -539,11 +544,11 @@ static inline float bw_hs2_process1(
const bw_hs2_coeffs * BW_RESTRICT coeffs, const bw_hs2_coeffs * BW_RESTRICT coeffs,
bw_hs2_state * BW_RESTRICT state, bw_hs2_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hs2_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -563,15 +568,15 @@ static inline void bw_hs2_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_hs2_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_hs2_update_coeffs_ctrl(coeffs); bw_hs2_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -592,18 +597,18 @@ static inline void bw_hs2_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) >= 1e-6f && coeffs->cutoff * bw_sqrtf(bw_sqrtf(coeffs->high_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -624,7 +629,7 @@ static inline void bw_hs2_process_multi(
static inline void bw_hs2_set_cutoff( static inline void bw_hs2_set_cutoff(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -645,7 +650,7 @@ static inline void bw_hs2_set_cutoff(
static inline void bw_hs2_set_Q( static inline void bw_hs2_set_Q(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -660,7 +665,7 @@ static inline void bw_hs2_set_Q(
static inline void bw_hs2_set_prewarp_at_cutoff( static inline void bw_hs2_set_prewarp_at_cutoff(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
@ -673,7 +678,7 @@ static inline void bw_hs2_set_prewarp_at_cutoff(
static inline void bw_hs2_set_prewarp_freq( static inline void bw_hs2_set_prewarp_freq(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -688,7 +693,7 @@ static inline void bw_hs2_set_prewarp_freq(
static inline void bw_hs2_set_high_gain_lin( static inline void bw_hs2_set_high_gain_lin(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -709,7 +714,7 @@ static inline void bw_hs2_set_high_gain_lin(
static inline void bw_hs2_set_high_gain_dB( static inline void bw_hs2_set_high_gain_dB(
bw_hs2_coeffs * BW_RESTRICT coeffs, bw_hs2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_hs2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_hs2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -723,7 +728,7 @@ static inline void bw_hs2_set_high_gain_dB(
static inline char bw_hs2_coeffs_is_valid( static inline char bw_hs2_coeffs_is_valid(
const bw_hs2_coeffs * BW_RESTRICT coeffs) { const bw_hs2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_hs2_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_hs2_coeffs"))
@ -756,17 +761,17 @@ static inline char bw_hs2_coeffs_is_valid(
static inline char bw_hs2_state_is_valid( static inline char bw_hs2_state_is_valid(
const bw_hs2_coeffs * BW_RESTRICT coeffs, const bw_hs2_coeffs * BW_RESTRICT coeffs,
const bw_hs2_state * BW_RESTRICT state) { const bw_hs2_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_hs2_state")) if (state->hash != bw_hash_sdbm("bw_hs2_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : NULL, &state->mm2_state); return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : BW_NULL, &state->mm2_state);
} }
#undef BW_HS2_PARAM_CUTOFF #undef BW_HS2_PARAM_CUTOFF

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* First-order lowpass filter (6 dB/oct) with unitary DC gain. * First-order lowpass filter (6 dB/oct) with unitary DC gain.
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Limited actual prewarping frequency to prevent instability.</li> * <li>Limited actual prewarping frequency to prevent instability.</li>
@ -147,7 +152,7 @@ static inline void bw_lp1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_lp1_update_coeffs_ctrl() * #### bw_lp1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -261,8 +266,8 @@ static inline char bw_lp1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_lp1_state`. * than or equal to that of `bw_lp1_state`.
@ -332,7 +337,7 @@ struct bw_lp1_state {
static inline void bw_lp1_init( static inline void bw_lp1_init(
bw_lp1_coeffs * BW_RESTRICT coeffs) { bw_lp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -353,7 +358,7 @@ static inline void bw_lp1_init(
static inline void bw_lp1_set_sample_rate( static inline void bw_lp1_set_sample_rate(
bw_lp1_coeffs * BW_RESTRICT coeffs, bw_lp1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -394,7 +399,7 @@ static inline void bw_lp1_do_update_coeffs(
static inline void bw_lp1_reset_coeffs( static inline void bw_lp1_reset_coeffs(
bw_lp1_coeffs * BW_RESTRICT coeffs) { bw_lp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_set_sample_rate);
@ -414,10 +419,10 @@ static inline float bw_lp1_reset_state(
const bw_lp1_coeffs * BW_RESTRICT coeffs, const bw_lp1_coeffs * BW_RESTRICT coeffs,
bw_lp1_state * BW_RESTRICT state, bw_lp1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
(void)coeffs; (void)coeffs;
@ -443,18 +448,18 @@ static inline void bw_lp1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_lp1_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_lp1_reset_state(coeffs, state[i], x_0[i]);
else else
@ -463,12 +468,12 @@ static inline void bw_lp1_reset_state_multi(
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_lp1_update_coeffs_ctrl( static inline void bw_lp1_update_coeffs_ctrl(
bw_lp1_coeffs * BW_RESTRICT coeffs) { bw_lp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
@ -477,7 +482,7 @@ static inline void bw_lp1_update_coeffs_ctrl(
static inline void bw_lp1_update_coeffs_audio( static inline void bw_lp1_update_coeffs_audio(
bw_lp1_coeffs * BW_RESTRICT coeffs) { bw_lp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
@ -491,10 +496,10 @@ static inline float bw_lp1_process1(
const bw_lp1_coeffs * BW_RESTRICT coeffs, const bw_lp1_coeffs * BW_RESTRICT coeffs,
bw_lp1_state * BW_RESTRICT state, bw_lp1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_lp1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -517,14 +522,14 @@ static inline void bw_lp1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_lp1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_lp1_update_coeffs_audio(coeffs); bw_lp1_update_coeffs_audio(coeffs);
@ -544,17 +549,17 @@ static inline void bw_lp1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -574,7 +579,7 @@ static inline void bw_lp1_process_multi(
static inline void bw_lp1_set_cutoff( static inline void bw_lp1_set_cutoff(
bw_lp1_coeffs * BW_RESTRICT coeffs, bw_lp1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -589,7 +594,7 @@ static inline void bw_lp1_set_cutoff(
static inline void bw_lp1_set_prewarp_at_cutoff( static inline void bw_lp1_set_prewarp_at_cutoff(
bw_lp1_coeffs * BW_RESTRICT coeffs, bw_lp1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init);
@ -602,7 +607,7 @@ static inline void bw_lp1_set_prewarp_at_cutoff(
static inline void bw_lp1_set_prewarp_freq( static inline void bw_lp1_set_prewarp_freq(
bw_lp1_coeffs * BW_RESTRICT coeffs, bw_lp1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_lp1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_lp1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -616,7 +621,7 @@ static inline void bw_lp1_set_prewarp_freq(
static inline char bw_lp1_coeffs_is_valid( static inline char bw_lp1_coeffs_is_valid(
const bw_lp1_coeffs * BW_RESTRICT coeffs) { const bw_lp1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_lp1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_lp1_coeffs"))
@ -664,13 +669,13 @@ static inline char bw_lp1_coeffs_is_valid(
static inline char bw_lp1_state_is_valid( static inline char bw_lp1_state_is_valid(
const bw_lp1_coeffs * BW_RESTRICT coeffs, const bw_lp1_coeffs * BW_RESTRICT coeffs,
const bw_lp1_state * BW_RESTRICT state) { const bw_lp1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_lp1_state")) if (state->hash != bw_hash_sdbm("bw_lp1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_lp1 bw_math bw_mm1 bw_one_pole }}} * requires {{{ bw_common bw_gain bw_lp1 bw_math bw_mm1 bw_one_pole }}}
* description {{{ * description {{{
* First-order low shelf filter (6 dB/oct) with gain asymptotically * First-order low shelf filter (6 dB/oct) with gain asymptotically
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_ls1_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_ls1_reset_state_multi()</code> and updated C++
@ -148,7 +153,7 @@ static inline void bw_ls1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_ls1_update_coeffs_ctrl() * #### bw_ls1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -301,8 +306,8 @@ static inline char bw_ls1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_ls1_state`. * than or equal to that of `bw_ls1_state`.
@ -363,7 +368,7 @@ struct bw_ls1_state {
static inline void bw_ls1_init( static inline void bw_ls1_init(
bw_ls1_coeffs * BW_RESTRICT coeffs) { bw_ls1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_mm1_init(&coeffs->mm1_coeffs); bw_mm1_init(&coeffs->mm1_coeffs);
bw_mm1_set_prewarp_at_cutoff(&coeffs->mm1_coeffs, 0); bw_mm1_set_prewarp_at_cutoff(&coeffs->mm1_coeffs, 0);
@ -386,7 +391,7 @@ static inline void bw_ls1_init(
static inline void bw_ls1_set_sample_rate( static inline void bw_ls1_set_sample_rate(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -412,7 +417,7 @@ static inline void bw_ls1_update_mm1_params(
static inline void bw_ls1_reset_coeffs( static inline void bw_ls1_reset_coeffs(
bw_ls1_coeffs * BW_RESTRICT coeffs) { bw_ls1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
@ -433,10 +438,10 @@ static inline float bw_ls1_reset_state(
const bw_ls1_coeffs * BW_RESTRICT coeffs, const bw_ls1_coeffs * BW_RESTRICT coeffs,
bw_ls1_state * BW_RESTRICT state, bw_ls1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float y = bw_mm1_reset_state(&coeffs->mm1_coeffs, &state->mm1_state, x_0); const float y = bw_mm1_reset_state(&coeffs->mm1_coeffs, &state->mm1_state, x_0);
@ -459,18 +464,18 @@ static inline void bw_ls1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_ls1_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_ls1_reset_state(coeffs, state[i], x_0[i]);
else else
@ -479,12 +484,12 @@ static inline void bw_ls1_reset_state_multi(
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_ls1_update_coeffs_ctrl( static inline void bw_ls1_update_coeffs_ctrl(
bw_ls1_coeffs * BW_RESTRICT coeffs) { bw_ls1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
@ -498,7 +503,7 @@ static inline void bw_ls1_update_coeffs_ctrl(
static inline void bw_ls1_update_coeffs_audio( static inline void bw_ls1_update_coeffs_audio(
bw_ls1_coeffs * BW_RESTRICT coeffs) { bw_ls1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
@ -513,11 +518,11 @@ static inline float bw_ls1_process1(
const bw_ls1_coeffs * BW_RESTRICT coeffs, const bw_ls1_coeffs * BW_RESTRICT coeffs,
bw_ls1_state * BW_RESTRICT state, bw_ls1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ls1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -537,15 +542,15 @@ static inline void bw_ls1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ls1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_ls1_update_coeffs_ctrl(coeffs); bw_ls1_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -566,18 +571,18 @@ static inline void bw_ls1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(coeffs->dc_gain)) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -598,7 +603,7 @@ static inline void bw_ls1_process_multi(
static inline void bw_ls1_set_cutoff( static inline void bw_ls1_set_cutoff(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -616,7 +621,7 @@ static inline void bw_ls1_set_cutoff(
static inline void bw_ls1_set_prewarp_at_cutoff( static inline void bw_ls1_set_prewarp_at_cutoff(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
@ -629,7 +634,7 @@ static inline void bw_ls1_set_prewarp_at_cutoff(
static inline void bw_ls1_set_prewarp_freq( static inline void bw_ls1_set_prewarp_freq(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -644,7 +649,7 @@ static inline void bw_ls1_set_prewarp_freq(
static inline void bw_ls1_set_dc_gain_lin( static inline void bw_ls1_set_dc_gain_lin(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -662,7 +667,7 @@ static inline void bw_ls1_set_dc_gain_lin(
static inline void bw_ls1_set_dc_gain_dB( static inline void bw_ls1_set_dc_gain_dB(
bw_ls1_coeffs * BW_RESTRICT coeffs, bw_ls1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -676,7 +681,7 @@ static inline void bw_ls1_set_dc_gain_dB(
static inline char bw_ls1_coeffs_is_valid( static inline char bw_ls1_coeffs_is_valid(
const bw_ls1_coeffs * BW_RESTRICT coeffs) { const bw_ls1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ls1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ls1_coeffs"))
@ -700,17 +705,17 @@ static inline char bw_ls1_coeffs_is_valid(
static inline char bw_ls1_state_is_valid( static inline char bw_ls1_state_is_valid(
const bw_ls1_coeffs * BW_RESTRICT coeffs, const bw_ls1_coeffs * BW_RESTRICT coeffs,
const bw_ls1_state * BW_RESTRICT state) { const bw_ls1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_ls1_state")) if (state->hash != bw_hash_sdbm("bw_ls1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_mm1_state_is_valid(coeffs ? &coeffs->mm1_coeffs : NULL, &state->mm1_state); return bw_mm1_state_is_valid(coeffs ? &coeffs->mm1_coeffs : BW_NULL, &state->mm1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>: * <li>Version <strong>1.0.1</strong>:
* <ul> * <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* <li>Fixed typos in documentation of * <li>Fixed typos in documentation of
* <code>bw_ls2_set_cutoff()</code>, * <code>bw_ls2_set_cutoff()</code>,
* <code>bw_ls2_set_dc_gain_lin()</code>, and * <code>bw_ls2_set_dc_gain_lin()</code>, and
@ -158,7 +159,7 @@ static inline void bw_ls2_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_ls2_update_coeffs_ctrl() * #### bw_ls2_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -326,8 +327,8 @@ static inline char bw_ls2_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_ls2_state`. * than or equal to that of `bw_ls2_state`.
@ -395,7 +396,7 @@ struct bw_ls2_state {
static inline void bw_ls2_init( static inline void bw_ls2_init(
bw_ls2_coeffs * BW_RESTRICT coeffs) { bw_ls2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_mm2_init(&coeffs->mm2_coeffs); bw_mm2_init(&coeffs->mm2_coeffs);
bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0); bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0);
@ -416,7 +417,7 @@ static inline void bw_ls2_init(
static inline void bw_ls2_set_sample_rate( static inline void bw_ls2_set_sample_rate(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -448,7 +449,7 @@ static inline void bw_ls2_update_mm2_params(
static inline void bw_ls2_reset_coeffs( static inline void bw_ls2_reset_coeffs(
bw_ls2_coeffs * BW_RESTRICT coeffs) { bw_ls2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
@ -469,10 +470,10 @@ static inline float bw_ls2_reset_state(
const bw_ls2_coeffs * BW_RESTRICT coeffs, const bw_ls2_coeffs * BW_RESTRICT coeffs,
bw_ls2_state * BW_RESTRICT state, bw_ls2_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0); const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0);
@ -495,18 +496,18 @@ static inline void bw_ls2_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_ls2_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_ls2_reset_state(coeffs, state[i], x_0[i]);
else else
@ -515,12 +516,12 @@ static inline void bw_ls2_reset_state_multi(
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_ls2_update_coeffs_ctrl( static inline void bw_ls2_update_coeffs_ctrl(
bw_ls2_coeffs * BW_RESTRICT coeffs) { bw_ls2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
@ -534,7 +535,7 @@ static inline void bw_ls2_update_coeffs_ctrl(
static inline void bw_ls2_update_coeffs_audio( static inline void bw_ls2_update_coeffs_audio(
bw_ls2_coeffs * BW_RESTRICT coeffs) { bw_ls2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
@ -549,11 +550,11 @@ static inline float bw_ls2_process1(
const bw_ls2_coeffs * BW_RESTRICT coeffs, const bw_ls2_coeffs * BW_RESTRICT coeffs,
bw_ls2_state * BW_RESTRICT state, bw_ls2_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ls2_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -573,15 +574,15 @@ static inline void bw_ls2_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ls2_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_ls2_update_coeffs_ctrl(coeffs); bw_ls2_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -602,18 +603,18 @@ static inline void bw_ls2_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f); BW_ASSERT_DEEP(coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) >= 1e-6f && coeffs->cutoff * bw_rcpf(bw_sqrtf(bw_sqrtf(coeffs->dc_gain))) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -634,7 +635,7 @@ static inline void bw_ls2_process_multi(
static inline void bw_ls2_set_cutoff( static inline void bw_ls2_set_cutoff(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -655,7 +656,7 @@ static inline void bw_ls2_set_cutoff(
static inline void bw_ls2_set_Q( static inline void bw_ls2_set_Q(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -670,7 +671,7 @@ static inline void bw_ls2_set_Q(
static inline void bw_ls2_set_prewarp_at_cutoff( static inline void bw_ls2_set_prewarp_at_cutoff(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
@ -683,7 +684,7 @@ static inline void bw_ls2_set_prewarp_at_cutoff(
static inline void bw_ls2_set_prewarp_freq( static inline void bw_ls2_set_prewarp_freq(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -698,7 +699,7 @@ static inline void bw_ls2_set_prewarp_freq(
static inline void bw_ls2_set_dc_gain_lin( static inline void bw_ls2_set_dc_gain_lin(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -719,7 +720,7 @@ static inline void bw_ls2_set_dc_gain_lin(
static inline void bw_ls2_set_dc_gain_dB( static inline void bw_ls2_set_dc_gain_dB(
bw_ls2_coeffs * BW_RESTRICT coeffs, bw_ls2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ls2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ls2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -733,7 +734,7 @@ static inline void bw_ls2_set_dc_gain_dB(
static inline char bw_ls2_coeffs_is_valid( static inline char bw_ls2_coeffs_is_valid(
const bw_ls2_coeffs * BW_RESTRICT coeffs) { const bw_ls2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ls2_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ls2_coeffs"))
@ -766,17 +767,17 @@ static inline char bw_ls2_coeffs_is_valid(
static inline char bw_ls2_state_is_valid( static inline char bw_ls2_state_is_valid(
const bw_ls2_coeffs * BW_RESTRICT coeffs, const bw_ls2_coeffs * BW_RESTRICT coeffs,
const bw_ls2_state * BW_RESTRICT state) { const bw_ls2_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_ls2_state")) if (state->hash != bw_hash_sdbm("bw_ls2_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : NULL, &state->mm2_state); return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : BW_NULL, &state->mm2_state);
} }
#undef BW_LS2_PARAM_CUTOFF #undef BW_LS2_PARAM_CUTOFF

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2021-2023 Orastron Srl unipersonale * Copyright (C) 2021-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ utility }}} * module_type {{{ utility }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* A collection of mathematical routines that strive to be better suited to * A collection of mathematical routines that strive to be better suited to
@ -44,6 +44,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Renamed <code>bw_min0xf()</code> as <code>bw_min0f()</code> and * <li>Renamed <code>bw_min0xf()</code> as <code>bw_min0f()</code> and
@ -756,8 +761,8 @@ static inline void bw_intfracf(
float * BW_RESTRICT i, float * BW_RESTRICT i,
float * BW_RESTRICT f) { float * BW_RESTRICT f) {
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(i != NULL); BW_ASSERT(i != BW_NULL);
BW_ASSERT(f != NULL); BW_ASSERT(f != BW_NULL);
BW_ASSERT(i != f); BW_ASSERT(i != f);
*i = bw_floorf(x); *i = bw_floorf(x);
*f = x - *i; *f = x - *i;

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_lp1 bw_math bw_one_pole }}} * requires {{{ bw_common bw_gain bw_lp1 bw_math bw_one_pole }}}
* description {{{ * description {{{
* First-order multimode filter. * First-order multimode filter.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_mm1_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_mm1_reset_state_multi()</code> and updated C++
@ -144,7 +149,7 @@ static inline void bw_mm1_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_mm1_update_coeffs_ctrl() * #### bw_mm1_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -281,8 +286,8 @@ static inline char bw_mm1_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_mm1_state`. * than or equal to that of `bw_mm1_state`.
@ -338,7 +343,7 @@ struct bw_mm1_state {
static inline void bw_mm1_init( static inline void bw_mm1_init(
bw_mm1_coeffs * BW_RESTRICT coeffs) { bw_mm1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_lp1_init(&coeffs->lp1_coeffs); bw_lp1_init(&coeffs->lp1_coeffs);
bw_gain_init(&coeffs->gain_x_coeffs); bw_gain_init(&coeffs->gain_x_coeffs);
@ -360,7 +365,7 @@ static inline void bw_mm1_init(
static inline void bw_mm1_set_sample_rate( static inline void bw_mm1_set_sample_rate(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -378,7 +383,7 @@ static inline void bw_mm1_set_sample_rate(
static inline void bw_mm1_reset_coeffs( static inline void bw_mm1_reset_coeffs(
bw_mm1_coeffs * BW_RESTRICT coeffs) { bw_mm1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_set_sample_rate);
@ -398,10 +403,10 @@ static inline float bw_mm1_reset_state(
const bw_mm1_coeffs * BW_RESTRICT coeffs, const bw_mm1_coeffs * BW_RESTRICT coeffs,
bw_mm1_state * BW_RESTRICT state, bw_mm1_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0); const float lp = bw_lp1_reset_state(&coeffs->lp1_coeffs, &state->lp1_state, x_0);
@ -425,18 +430,18 @@ static inline void bw_mm1_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_mm1_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_mm1_reset_state(coeffs, state[i], x_0[i]);
else else
@ -445,12 +450,12 @@ static inline void bw_mm1_reset_state_multi(
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_mm1_update_coeffs_ctrl( static inline void bw_mm1_update_coeffs_ctrl(
bw_mm1_coeffs * BW_RESTRICT coeffs) { bw_mm1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
@ -464,7 +469,7 @@ static inline void bw_mm1_update_coeffs_ctrl(
static inline void bw_mm1_update_coeffs_audio( static inline void bw_mm1_update_coeffs_audio(
bw_mm1_coeffs * BW_RESTRICT coeffs) { bw_mm1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
@ -480,10 +485,10 @@ static inline float bw_mm1_process1(
const bw_mm1_coeffs * BW_RESTRICT coeffs, const bw_mm1_coeffs * BW_RESTRICT coeffs,
bw_mm1_state * BW_RESTRICT state, bw_mm1_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_mm1_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -506,14 +511,14 @@ static inline void bw_mm1_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_mm1_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_mm1_update_coeffs_ctrl(coeffs); bw_mm1_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -534,17 +539,17 @@ static inline void bw_mm1_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -565,7 +570,7 @@ static inline void bw_mm1_process_multi(
static inline void bw_mm1_set_cutoff( static inline void bw_mm1_set_cutoff(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -580,7 +585,7 @@ static inline void bw_mm1_set_cutoff(
static inline void bw_mm1_set_prewarp_at_cutoff( static inline void bw_mm1_set_prewarp_at_cutoff(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
@ -593,7 +598,7 @@ static inline void bw_mm1_set_prewarp_at_cutoff(
static inline void bw_mm1_set_prewarp_freq( static inline void bw_mm1_set_prewarp_freq(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -608,7 +613,7 @@ static inline void bw_mm1_set_prewarp_freq(
static inline void bw_mm1_set_coeff_x( static inline void bw_mm1_set_coeff_x(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -622,7 +627,7 @@ static inline void bw_mm1_set_coeff_x(
static inline void bw_mm1_set_coeff_lp( static inline void bw_mm1_set_coeff_lp(
bw_mm1_coeffs * BW_RESTRICT coeffs, bw_mm1_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm1_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm1_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -635,7 +640,7 @@ static inline void bw_mm1_set_coeff_lp(
static inline char bw_mm1_coeffs_is_valid( static inline char bw_mm1_coeffs_is_valid(
const bw_mm1_coeffs * BW_RESTRICT coeffs) { const bw_mm1_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_mm1_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_mm1_coeffs"))
@ -650,17 +655,17 @@ static inline char bw_mm1_coeffs_is_valid(
static inline char bw_mm1_state_is_valid( static inline char bw_mm1_state_is_valid(
const bw_mm1_coeffs * BW_RESTRICT coeffs, const bw_mm1_coeffs * BW_RESTRICT coeffs,
const bw_mm1_state * BW_RESTRICT state) { const bw_mm1_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_mm1_state")) if (state->hash != bw_hash_sdbm("bw_mm1_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : NULL, &state->lp1_state); return bw_lp1_state_is_valid(coeffs ? &coeffs->lp1_coeffs : BW_NULL, &state->lp1_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_one_pole bw_svf }}} * requires {{{ bw_common bw_gain bw_math bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Second-order multimode filter. * Second-order multimode filter.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_mm2_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_mm2_reset_state_multi()</code> and updated C++
@ -144,7 +149,7 @@ static inline void bw_mm2_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_mm2_update_coeffs_ctrl() * #### bw_mm2_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -318,8 +323,8 @@ static inline char bw_mm2_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_mm2_state`. * than or equal to that of `bw_mm2_state`.
@ -377,7 +382,7 @@ struct bw_mm2_state {
static inline void bw_mm2_init( static inline void bw_mm2_init(
bw_mm2_coeffs * BW_RESTRICT coeffs) { bw_mm2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->svf_coeffs); bw_svf_init(&coeffs->svf_coeffs);
bw_gain_init(&coeffs->gain_x_coeffs); bw_gain_init(&coeffs->gain_x_coeffs);
@ -405,7 +410,7 @@ static inline void bw_mm2_init(
static inline void bw_mm2_set_sample_rate( static inline void bw_mm2_set_sample_rate(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -425,7 +430,7 @@ static inline void bw_mm2_set_sample_rate(
static inline void bw_mm2_reset_coeffs( static inline void bw_mm2_reset_coeffs(
bw_mm2_coeffs * BW_RESTRICT coeffs) { bw_mm2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_set_sample_rate);
@ -447,10 +452,10 @@ static inline float bw_mm2_reset_state(
const bw_mm2_coeffs * BW_RESTRICT coeffs, const bw_mm2_coeffs * BW_RESTRICT coeffs,
bw_mm2_state * BW_RESTRICT state, bw_mm2_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float lp, bp, hp; float lp, bp, hp;
@ -479,18 +484,18 @@ static inline void bw_mm2_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_mm2_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_mm2_reset_state(coeffs, state[i], x_0[i]);
else else
@ -499,12 +504,12 @@ static inline void bw_mm2_reset_state_multi(
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_mm2_update_coeffs_ctrl( static inline void bw_mm2_update_coeffs_ctrl(
bw_mm2_coeffs * BW_RESTRICT coeffs) { bw_mm2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
@ -520,7 +525,7 @@ static inline void bw_mm2_update_coeffs_ctrl(
static inline void bw_mm2_update_coeffs_audio( static inline void bw_mm2_update_coeffs_audio(
bw_mm2_coeffs * BW_RESTRICT coeffs) { bw_mm2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
@ -538,10 +543,10 @@ static inline float bw_mm2_process1(
const bw_mm2_coeffs * BW_RESTRICT coeffs, const bw_mm2_coeffs * BW_RESTRICT coeffs,
bw_mm2_state * BW_RESTRICT state, bw_mm2_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_mm2_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -567,14 +572,14 @@ static inline void bw_mm2_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_mm2_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_mm2_update_coeffs_ctrl(coeffs); bw_mm2_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -595,17 +600,17 @@ static inline void bw_mm2_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -626,7 +631,7 @@ static inline void bw_mm2_process_multi(
static inline void bw_mm2_set_cutoff( static inline void bw_mm2_set_cutoff(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -641,7 +646,7 @@ static inline void bw_mm2_set_cutoff(
static inline void bw_mm2_set_Q( static inline void bw_mm2_set_Q(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -656,7 +661,7 @@ static inline void bw_mm2_set_Q(
static inline void bw_mm2_set_prewarp_at_cutoff( static inline void bw_mm2_set_prewarp_at_cutoff(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
@ -669,7 +674,7 @@ static inline void bw_mm2_set_prewarp_at_cutoff(
static inline void bw_mm2_set_prewarp_freq( static inline void bw_mm2_set_prewarp_freq(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -684,7 +689,7 @@ static inline void bw_mm2_set_prewarp_freq(
static inline void bw_mm2_set_coeff_x( static inline void bw_mm2_set_coeff_x(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -698,7 +703,7 @@ static inline void bw_mm2_set_coeff_x(
static inline void bw_mm2_set_coeff_lp( static inline void bw_mm2_set_coeff_lp(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -712,7 +717,7 @@ static inline void bw_mm2_set_coeff_lp(
static inline void bw_mm2_set_coeff_bp( static inline void bw_mm2_set_coeff_bp(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -726,7 +731,7 @@ static inline void bw_mm2_set_coeff_bp(
static inline void bw_mm2_set_coeff_hp( static inline void bw_mm2_set_coeff_hp(
bw_mm2_coeffs * BW_RESTRICT coeffs, bw_mm2_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_mm2_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_mm2_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -739,7 +744,7 @@ static inline void bw_mm2_set_coeff_hp(
static inline char bw_mm2_coeffs_is_valid( static inline char bw_mm2_coeffs_is_valid(
const bw_mm2_coeffs * BW_RESTRICT coeffs) { const bw_mm2_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_mm2_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_mm2_coeffs"))
@ -758,17 +763,17 @@ static inline char bw_mm2_coeffs_is_valid(
static inline char bw_mm2_state_is_valid( static inline char bw_mm2_state_is_valid(
const bw_mm2_coeffs * BW_RESTRICT coeffs, const bw_mm2_coeffs * BW_RESTRICT coeffs,
const bw_mm2_state * BW_RESTRICT state) { const bw_mm2_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_mm2_state")) if (state->hash != bw_hash_sdbm("bw_mm2_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : NULL, &state->svf_state); return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : BW_NULL, &state->svf_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_env_follow bw_math bw_one_pole }}} * requires {{{ bw_common bw_env_follow bw_math bw_one_pole }}}
* description {{{ * description {{{
* Noise gate with independent sidechain input. * Noise gate with independent sidechain input.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input values to * <li>Added initial input values to
@ -146,7 +151,7 @@ static inline void bw_noise_gate_reset_state_multi(
* array and sidechain input value in the `x_sc_0` array. * array and sidechain input value in the `x_sc_0` array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_noise_gate_update_coeffs_ctrl() * #### bw_noise_gate_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -291,8 +296,8 @@ static inline char bw_noise_gate_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_noise_gate_state`. * than or equal to that of `bw_noise_gate_state`.
@ -358,7 +363,7 @@ struct bw_noise_gate_state {
static inline void bw_noise_gate_init( static inline void bw_noise_gate_init(
bw_noise_gate_coeffs * BW_RESTRICT coeffs) { bw_noise_gate_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_env_follow_init(&coeffs->env_follow_coeffs); bw_env_follow_init(&coeffs->env_follow_coeffs);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
@ -378,7 +383,7 @@ static inline void bw_noise_gate_init(
static inline void bw_noise_gate_set_sample_rate( static inline void bw_noise_gate_set_sample_rate(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -405,7 +410,7 @@ static inline void bw_noise_gate_do_update_coeffs_audio(
static inline void bw_noise_gate_reset_coeffs( static inline void bw_noise_gate_reset_coeffs(
bw_noise_gate_coeffs * BW_RESTRICT coeffs) { bw_noise_gate_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_set_sample_rate);
@ -427,10 +432,10 @@ static inline float bw_noise_gate_reset_state(
bw_noise_gate_state * BW_RESTRICT state, bw_noise_gate_state * BW_RESTRICT state,
float x_0, float x_0,
float x_sc_0) { float x_sc_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
BW_ASSERT(bw_is_finite(x_sc_0)); BW_ASSERT(bw_is_finite(x_sc_0));
@ -456,19 +461,19 @@ static inline void bw_noise_gate_reset_state_multi(
const float * x_sc_0, const float * x_sc_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
BW_ASSERT(x_sc_0 != NULL); BW_ASSERT(x_sc_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_noise_gate_reset_state(coeffs, state[i], x_0[i], x_sc_0[i]); y_0[i] = bw_noise_gate_reset_state(coeffs, state[i], x_0[i], x_sc_0[i]);
else else
@ -478,12 +483,12 @@ static inline void bw_noise_gate_reset_state_multi(
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_has_only_finite(y_0, n_channels)); BW_ASSERT_DEEP(bw_has_only_finite(y_0, n_channels));
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_noise_gate_update_coeffs_ctrl( static inline void bw_noise_gate_update_coeffs_ctrl(
bw_noise_gate_coeffs * BW_RESTRICT coeffs) { bw_noise_gate_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
@ -495,7 +500,7 @@ static inline void bw_noise_gate_update_coeffs_ctrl(
static inline void bw_noise_gate_update_coeffs_audio( static inline void bw_noise_gate_update_coeffs_audio(
bw_noise_gate_coeffs * BW_RESTRICT coeffs) { bw_noise_gate_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
@ -510,10 +515,10 @@ static inline float bw_noise_gate_process1(
bw_noise_gate_state * BW_RESTRICT state, bw_noise_gate_state * BW_RESTRICT state,
float x, float x,
float x_sc) { float x_sc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_noise_gate_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(bw_is_finite(x_sc)); BW_ASSERT(bw_is_finite(x_sc));
@ -536,16 +541,16 @@ static inline void bw_noise_gate_process(
const float * x_sc, const float * x_sc,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_noise_gate_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(x_sc != NULL); BW_ASSERT(x_sc != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_sc, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_sc, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_noise_gate_update_coeffs_ctrl(coeffs); bw_noise_gate_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -566,18 +571,18 @@ static inline void bw_noise_gate_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(x_sc != NULL); BW_ASSERT(x_sc != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -598,7 +603,7 @@ static inline void bw_noise_gate_process_multi(
static inline void bw_noise_gate_set_thresh_lin( static inline void bw_noise_gate_set_thresh_lin(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -613,7 +618,7 @@ static inline void bw_noise_gate_set_thresh_lin(
static inline void bw_noise_gate_set_thresh_dBFS( static inline void bw_noise_gate_set_thresh_dBFS(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -628,7 +633,7 @@ static inline void bw_noise_gate_set_thresh_dBFS(
static inline void bw_noise_gate_set_ratio( static inline void bw_noise_gate_set_ratio(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -643,7 +648,7 @@ static inline void bw_noise_gate_set_ratio(
static inline void bw_noise_gate_set_attack_tau( static inline void bw_noise_gate_set_attack_tau(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -658,7 +663,7 @@ static inline void bw_noise_gate_set_attack_tau(
static inline void bw_noise_gate_set_release_tau( static inline void bw_noise_gate_set_release_tau(
bw_noise_gate_coeffs * BW_RESTRICT coeffs, bw_noise_gate_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gate_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gate_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -672,7 +677,7 @@ static inline void bw_noise_gate_set_release_tau(
static inline char bw_noise_gate_coeffs_is_valid( static inline char bw_noise_gate_coeffs_is_valid(
const bw_noise_gate_coeffs * BW_RESTRICT coeffs) { const bw_noise_gate_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_noise_gate_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_noise_gate_coeffs"))
@ -709,17 +714,17 @@ static inline char bw_noise_gate_coeffs_is_valid(
static inline char bw_noise_gate_state_is_valid( static inline char bw_noise_gate_state_is_valid(
const bw_noise_gate_coeffs * BW_RESTRICT coeffs, const bw_noise_gate_coeffs * BW_RESTRICT coeffs,
const bw_noise_gate_state * BW_RESTRICT state) { const bw_noise_gate_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_noise_gate_state")) if (state->hash != bw_hash_sdbm("bw_noise_gate_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : NULL, &state->env_follow_state); return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : BW_NULL, &state->env_follow_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_rand }}} * requires {{{ bw_common bw_math bw_rand }}}
* description {{{ * description {{{
* Generator of white noise with uniform distribution. * Generator of white noise with uniform distribution.
@ -31,6 +31,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_noise_gen_reset_coeffs()</code>, * <li>Added <code>bw_noise_gen_reset_coeffs()</code>,
@ -245,8 +250,8 @@ struct bw_noise_gen_coeffs {
static inline void bw_noise_gen_init( static inline void bw_noise_gen_init(
bw_noise_gen_coeffs * BW_RESTRICT coeffs, bw_noise_gen_coeffs * BW_RESTRICT coeffs,
uint64_t * BW_RESTRICT state) { uint64_t * BW_RESTRICT state) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
coeffs->rand_state = state; coeffs->rand_state = state;
coeffs->sample_rate_scaling = 0; coeffs->sample_rate_scaling = 0;
@ -262,7 +267,7 @@ static inline void bw_noise_gen_init(
static inline void bw_noise_gen_set_sample_rate( static inline void bw_noise_gen_set_sample_rate(
bw_noise_gen_coeffs * BW_RESTRICT coeffs, bw_noise_gen_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -278,7 +283,7 @@ static inline void bw_noise_gen_set_sample_rate(
static inline void bw_noise_gen_reset_coeffs( static inline void bw_noise_gen_reset_coeffs(
bw_noise_gen_coeffs * BW_RESTRICT coeffs) { bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_set_sample_rate);
@ -293,7 +298,7 @@ static inline void bw_noise_gen_reset_coeffs(
static inline void bw_noise_gen_update_coeffs_ctrl( static inline void bw_noise_gen_update_coeffs_ctrl(
bw_noise_gen_coeffs * BW_RESTRICT coeffs) { bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
@ -302,7 +307,7 @@ static inline void bw_noise_gen_update_coeffs_ctrl(
static inline void bw_noise_gen_update_coeffs_audio( static inline void bw_noise_gen_update_coeffs_audio(
bw_noise_gen_coeffs * BW_RESTRICT coeffs) { bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
@ -311,7 +316,7 @@ static inline void bw_noise_gen_update_coeffs_audio(
static inline float bw_noise_gen_process1( static inline float bw_noise_gen_process1(
const bw_noise_gen_coeffs * BW_RESTRICT coeffs) { const bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
@ -326,7 +331,7 @@ static inline float bw_noise_gen_process1(
static inline float bw_noise_gen_process1_scaling( static inline float bw_noise_gen_process1_scaling(
const bw_noise_gen_coeffs * BW_RESTRICT coeffs) { const bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
@ -343,10 +348,10 @@ static inline void bw_noise_gen_process(
bw_noise_gen_coeffs * BW_RESTRICT coeffs, bw_noise_gen_coeffs * BW_RESTRICT coeffs,
float * BW_RESTRICT y, float * BW_RESTRICT y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->sample_rate_scaling) if (coeffs->sample_rate_scaling)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -365,10 +370,10 @@ static inline void bw_noise_gen_process_multi(
float * BW_RESTRICT const * BW_RESTRICT y, float * BW_RESTRICT const * BW_RESTRICT y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_reset_coeffs);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -385,7 +390,7 @@ static inline void bw_noise_gen_process_multi(
static inline void bw_noise_gen_set_sample_rate_scaling( static inline void bw_noise_gen_set_sample_rate_scaling(
bw_noise_gen_coeffs * BW_RESTRICT coeffs, bw_noise_gen_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_init);
@ -397,7 +402,7 @@ static inline void bw_noise_gen_set_sample_rate_scaling(
static inline float bw_noise_gen_get_scaling_k( static inline float bw_noise_gen_get_scaling_k(
const bw_noise_gen_coeffs * BW_RESTRICT coeffs) { const bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_noise_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_noise_gen_coeffs_state_set_sample_rate);
@ -406,7 +411,7 @@ static inline float bw_noise_gen_get_scaling_k(
static inline char bw_noise_gen_coeffs_is_valid( static inline char bw_noise_gen_coeffs_is_valid(
const bw_noise_gen_coeffs * BW_RESTRICT coeffs) { const bw_noise_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_noise_gen_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_noise_gen_coeffs"))
@ -415,7 +420,7 @@ static inline char bw_noise_gen_coeffs_is_valid(
return 0; return 0;
#endif #endif
if (coeffs->rand_state == NULL) if (coeffs->rand_state == BW_NULL)
return 0; return 0;
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole bw_svf }}} * requires {{{ bw_common bw_math bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Second-order notch filter with unitary gain at DC and asymptotically as * Second-order notch filter with unitary gain at DC and asymptotically as
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_notch_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_notch_reset_state_multi()</code> and updated C++
@ -146,7 +151,7 @@ static inline void bw_notch_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_notch_update_coeffs_ctrl() * #### bw_notch_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -272,8 +277,8 @@ static inline char bw_notch_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_notch_state`. * than or equal to that of `bw_notch_state`.
@ -326,7 +331,7 @@ struct bw_notch_state {
static inline void bw_notch_init( static inline void bw_notch_init(
bw_notch_coeffs * BW_RESTRICT coeffs) { bw_notch_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->svf_coeffs); bw_svf_init(&coeffs->svf_coeffs);
@ -342,7 +347,7 @@ static inline void bw_notch_init(
static inline void bw_notch_set_sample_rate( static inline void bw_notch_set_sample_rate(
bw_notch_coeffs * BW_RESTRICT coeffs, bw_notch_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -358,7 +363,7 @@ static inline void bw_notch_set_sample_rate(
static inline void bw_notch_reset_coeffs( static inline void bw_notch_reset_coeffs(
bw_notch_coeffs * BW_RESTRICT coeffs) { bw_notch_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_set_sample_rate);
@ -376,10 +381,10 @@ static inline float bw_notch_reset_state(
const bw_notch_coeffs * BW_RESTRICT coeffs, const bw_notch_coeffs * BW_RESTRICT coeffs,
bw_notch_state * BW_RESTRICT state, bw_notch_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float lp, bp, hp; float lp, bp, hp;
@ -404,18 +409,18 @@ static inline void bw_notch_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_notch_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_notch_reset_state(coeffs, state[i], x_0[i]);
else else
@ -424,12 +429,12 @@ static inline void bw_notch_reset_state_multi(
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_notch_update_coeffs_ctrl( static inline void bw_notch_update_coeffs_ctrl(
bw_notch_coeffs * BW_RESTRICT coeffs) { bw_notch_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
@ -441,7 +446,7 @@ static inline void bw_notch_update_coeffs_ctrl(
static inline void bw_notch_update_coeffs_audio( static inline void bw_notch_update_coeffs_audio(
bw_notch_coeffs * BW_RESTRICT coeffs) { bw_notch_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
@ -455,10 +460,10 @@ static inline float bw_notch_process1(
const bw_notch_coeffs * BW_RESTRICT coeffs, const bw_notch_coeffs * BW_RESTRICT coeffs,
bw_notch_state * BW_RESTRICT state, bw_notch_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_notch_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_notch_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -480,14 +485,14 @@ static inline void bw_notch_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_notch_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_notch_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_notch_update_coeffs_ctrl(coeffs); bw_notch_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -508,17 +513,17 @@ static inline void bw_notch_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -539,7 +544,7 @@ static inline void bw_notch_process_multi(
static inline void bw_notch_set_cutoff( static inline void bw_notch_set_cutoff(
bw_notch_coeffs * BW_RESTRICT coeffs, bw_notch_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -554,7 +559,7 @@ static inline void bw_notch_set_cutoff(
static inline void bw_notch_set_Q( static inline void bw_notch_set_Q(
bw_notch_coeffs * BW_RESTRICT coeffs, bw_notch_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -569,7 +574,7 @@ static inline void bw_notch_set_Q(
static inline void bw_notch_set_prewarp_at_cutoff( static inline void bw_notch_set_prewarp_at_cutoff(
bw_notch_coeffs * BW_RESTRICT coeffs, bw_notch_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init);
@ -582,7 +587,7 @@ static inline void bw_notch_set_prewarp_at_cutoff(
static inline void bw_notch_set_prewarp_freq( static inline void bw_notch_set_prewarp_freq(
bw_notch_coeffs * BW_RESTRICT coeffs, bw_notch_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_notch_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_notch_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -596,7 +601,7 @@ static inline void bw_notch_set_prewarp_freq(
static inline char bw_notch_coeffs_is_valid( static inline char bw_notch_coeffs_is_valid(
const bw_notch_coeffs * BW_RESTRICT coeffs) { const bw_notch_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_notch_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_notch_coeffs"))
@ -611,17 +616,17 @@ static inline char bw_notch_coeffs_is_valid(
static inline char bw_notch_state_is_valid( static inline char bw_notch_state_is_valid(
const bw_notch_coeffs * BW_RESTRICT coeffs, const bw_notch_coeffs * BW_RESTRICT coeffs,
const bw_notch_state * BW_RESTRICT state) { const bw_notch_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_notch_state")) if (state->hash != bw_hash_sdbm("bw_notch_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : NULL, &state->svf_state); return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : BW_NULL, &state->svf_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ utility }}} * module_type {{{ utility }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* Simple data structure that helps keeping track of note on/off events and * Simple data structure that helps keeping track of note on/off events and
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Removed redundant <code>status</code> member from * <li>Removed redundant <code>status</code> member from
@ -172,7 +177,7 @@ extern "C" {
static inline void bw_note_queue_reset( static inline void bw_note_queue_reset(
bw_note_queue * BW_RESTRICT queue) { bw_note_queue * BW_RESTRICT queue) {
BW_ASSERT(queue != NULL); BW_ASSERT(queue != BW_NULL);
for (int i = 0; i < 128; i++) { for (int i = 0; i < 128; i++) {
queue->status[i].pressed = 0; queue->status[i].pressed = 0;
queue->status[i].velocity = 0.f; queue->status[i].velocity = 0.f;
@ -184,7 +189,7 @@ static inline void bw_note_queue_reset(
static inline void bw_note_queue_clear( static inline void bw_note_queue_clear(
bw_note_queue * BW_RESTRICT queue) { bw_note_queue * BW_RESTRICT queue) {
BW_ASSERT(queue != NULL); BW_ASSERT(queue != BW_NULL);
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue)); BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
queue->n_events = 0; queue->n_events = 0;
} }
@ -195,7 +200,7 @@ static inline void bw_note_queue_add(
char pressed, char pressed,
float velocity, float velocity,
char force_went_off) { char force_went_off) {
BW_ASSERT(queue != NULL); BW_ASSERT(queue != BW_NULL);
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue)); BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
BW_ASSERT(note < 128); BW_ASSERT(note < 128);
BW_ASSERT(bw_is_finite(velocity) && velocity <= 1.f); BW_ASSERT(bw_is_finite(velocity) && velocity <= 1.f);
@ -227,7 +232,7 @@ static inline void bw_note_queue_add(
static inline char bw_note_queue_is_valid( static inline char bw_note_queue_is_valid(
const bw_note_queue * BW_RESTRICT queue) { const bw_note_queue * BW_RESTRICT queue) {
BW_ASSERT(queue != NULL); BW_ASSERT(queue != BW_NULL);
if (queue->n_events >= 128 || queue->n_pressed >= 128) if (queue->n_events >= 128 || queue->n_pressed >= 128)
return 0; return 0;

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* One-pole (6 dB/oct) lowpass filter with unitary DC gain, separate attack * One-pole (6 dB/oct) lowpass filter with unitary DC gain, separate attack
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_one_pole_reset_state_multi()</code> and updated * <li>Added <code>bw_one_pole_reset_state_multi()</code> and updated
@ -174,7 +179,7 @@ static inline void bw_one_pole_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the * The corresponding initial output values are written into the
* `y_0` array, if not `NULL`. * `y_0` array, if not `BW_NULL`.
* *
* #### bw_one_pole_update_coeffs_ctrl() * #### bw_one_pole_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -262,7 +267,7 @@ static inline void bw_one_pole_process(
* first `n_samples` of the output buffer `y`, while using and updating both * first `n_samples` of the output buffer `y`, while using and updating both
* `coeffs` and `state` (control and audio rate). * `coeffs` and `state` (control and audio rate).
* *
* `y` may be `NULL`. * `y` may be `BW_NULL`.
* *
* #### bw_one_pole_process_multi() * #### bw_one_pole_process_multi()
* ```>>> */ * ```>>> */
@ -279,7 +284,7 @@ static inline void bw_one_pole_process_multi(
* using and updating both the common `coeffs` and each of the `n_channels` * using and updating both the common `coeffs` and each of the `n_channels`
* `state`s (control and audio rate). * `state`s (control and audio rate).
* *
* `y` or any element of `y` may be `NULL`. * `y` or any element of `y` may be `BW_NULL`.
* *
* #### bw_one_pole_set_cutoff() * #### bw_one_pole_set_cutoff()
* ```>>> */ * ```>>> */
@ -438,8 +443,8 @@ static inline char bw_one_pole_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_one_pole_state`. * than or equal to that of `bw_one_pole_state`.
@ -507,7 +512,7 @@ struct bw_one_pole_state {
static inline void bw_one_pole_init( static inline void bw_one_pole_init(
bw_one_pole_coeffs * BW_RESTRICT coeffs) { bw_one_pole_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->cutoff_up = INFINITY; coeffs->cutoff_up = INFINITY;
coeffs->cutoff_down = INFINITY; coeffs->cutoff_down = INFINITY;
@ -526,7 +531,7 @@ static inline void bw_one_pole_init(
static inline void bw_one_pole_set_sample_rate( static inline void bw_one_pole_set_sample_rate(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -557,7 +562,7 @@ static inline void bw_one_pole_do_update_coeffs_ctrl(
static inline void bw_one_pole_reset_coeffs( static inline void bw_one_pole_reset_coeffs(
bw_one_pole_coeffs * BW_RESTRICT coeffs) { bw_one_pole_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_set_sample_rate);
@ -576,10 +581,10 @@ static inline float bw_one_pole_reset_state(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
(void)coeffs; (void)coeffs;
@ -604,18 +609,18 @@ static inline void bw_one_pole_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_one_pole_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_one_pole_reset_state(coeffs, state[i], x_0[i]);
else else
@ -624,12 +629,12 @@ static inline void bw_one_pole_reset_state_multi(
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_one_pole_update_coeffs_ctrl( static inline void bw_one_pole_update_coeffs_ctrl(
bw_one_pole_coeffs * BW_RESTRICT coeffs) { bw_one_pole_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
@ -641,7 +646,7 @@ static inline void bw_one_pole_update_coeffs_ctrl(
static inline void bw_one_pole_update_coeffs_audio( static inline void bw_one_pole_update_coeffs_audio(
bw_one_pole_coeffs * BW_RESTRICT coeffs) { bw_one_pole_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
@ -652,10 +657,10 @@ static inline float bw_one_pole_process1(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -674,10 +679,10 @@ static inline float bw_one_pole_process1_sticky_abs(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -699,10 +704,10 @@ static inline float bw_one_pole_process1_sticky_rel(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -724,10 +729,10 @@ static inline float bw_one_pole_process1_asym(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -746,10 +751,10 @@ static inline float bw_one_pole_process1_asym_sticky_abs(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -771,10 +776,10 @@ static inline float bw_one_pole_process1_asym_sticky_rel(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_state * BW_RESTRICT state, bw_one_pole_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -798,16 +803,16 @@ static inline void bw_one_pole_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
bw_one_pole_update_coeffs_ctrl(coeffs); bw_one_pole_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (coeffs->mA1u != coeffs->mA1d) { if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) { if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs) if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
@ -870,7 +875,7 @@ static inline void bw_one_pole_process(
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
} }
static inline void bw_one_pole_process_multi( static inline void bw_one_pole_process_multi(
@ -880,30 +885,30 @@ static inline void bw_one_pole_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); 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(coeffs->state >= bw_one_pole_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] == NULL || y[j] == NULL || y[i] != y[j]); BW_ASSERT(y[i] == BW_NULL || y[j] == BW_NULL || y[i] != y[j]);
#endif #endif
bw_one_pole_update_coeffs_ctrl(coeffs); bw_one_pole_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (coeffs->mA1u != coeffs->mA1d) { if (coeffs->mA1u != coeffs->mA1d) {
if (coeffs->st2 != 0.f) { if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs) if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym_sticky_abs(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1_asym_sticky_abs(coeffs, state[j], x[j][i]);
else else
@ -912,7 +917,7 @@ static inline void bw_one_pole_process_multi(
else else
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym_sticky_rel(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1_asym_sticky_rel(coeffs, state[j], x[j][i]);
else else
@ -921,7 +926,7 @@ static inline void bw_one_pole_process_multi(
} }
else { else {
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_asym(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1_asym(coeffs, state[j], x[j][i]);
else else
@ -933,7 +938,7 @@ static inline void bw_one_pole_process_multi(
if (coeffs->st2 != 0.f) { if (coeffs->st2 != 0.f) {
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs) if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]);
else else
@ -941,7 +946,7 @@ static inline void bw_one_pole_process_multi(
bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]); bw_one_pole_process1_sticky_abs(coeffs, state[j], x[j][i]);
else else
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1_sticky_rel(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1_sticky_rel(coeffs, state[j], x[j][i]);
else else
@ -950,7 +955,7 @@ static inline void bw_one_pole_process_multi(
} }
else { else {
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_one_pole_process1(coeffs, state[j], x[j][i]); y[j][i] = bw_one_pole_process1(coeffs, state[j], x[j][i]);
else else
@ -1002,7 +1007,7 @@ static inline void bw_one_pole_process_multi(
static inline void bw_one_pole_set_cutoff( static inline void bw_one_pole_set_cutoff(
bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_coeffs *BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1018,7 +1023,7 @@ static inline void bw_one_pole_set_cutoff(
static inline void bw_one_pole_set_cutoff_up( static inline void bw_one_pole_set_cutoff_up(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1039,7 +1044,7 @@ static inline void bw_one_pole_set_cutoff_up(
static inline void bw_one_pole_set_cutoff_down( static inline void bw_one_pole_set_cutoff_down(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1060,7 +1065,7 @@ static inline void bw_one_pole_set_cutoff_down(
static inline void bw_one_pole_set_tau( static inline void bw_one_pole_set_tau(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1076,7 +1081,7 @@ static inline void bw_one_pole_set_tau(
static inline void bw_one_pole_set_tau_up( static inline void bw_one_pole_set_tau_up(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1092,7 +1097,7 @@ static inline void bw_one_pole_set_tau_up(
static inline void bw_one_pole_set_tau_down( static inline void bw_one_pole_set_tau_down(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1108,7 +1113,7 @@ static inline void bw_one_pole_set_tau_down(
static inline void bw_one_pole_set_sticky_thresh( static inline void bw_one_pole_set_sticky_thresh(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -1129,7 +1134,7 @@ static inline void bw_one_pole_set_sticky_thresh(
static inline void bw_one_pole_set_sticky_mode( static inline void bw_one_pole_set_sticky_mode(
bw_one_pole_coeffs * BW_RESTRICT coeffs, bw_one_pole_coeffs * BW_RESTRICT coeffs,
bw_one_pole_sticky_mode value) { bw_one_pole_sticky_mode value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_one_pole_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_one_pole_coeffs_state_init);
BW_ASSERT(value == bw_one_pole_sticky_mode_abs || value == bw_one_pole_sticky_mode_rel); BW_ASSERT(value == bw_one_pole_sticky_mode_abs || value == bw_one_pole_sticky_mode_rel);
@ -1142,15 +1147,15 @@ static inline void bw_one_pole_set_sticky_mode(
static inline float bw_one_pole_get_y_z1( static inline float bw_one_pole_get_y_z1(
const bw_one_pole_state * BW_RESTRICT state) { const bw_one_pole_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_one_pole_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_one_pole_state_is_valid(BW_NULL, state));
return state->y_z1; return state->y_z1;
} }
static inline char bw_one_pole_coeffs_is_valid( static inline char bw_one_pole_coeffs_is_valid(
const bw_one_pole_coeffs * BW_RESTRICT coeffs) { const bw_one_pole_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_one_pole_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_one_pole_coeffs"))
@ -1190,13 +1195,13 @@ static inline char bw_one_pole_coeffs_is_valid(
static inline char bw_one_pole_state_is_valid( static inline char bw_one_pole_state_is_valid(
const bw_one_pole_coeffs * BW_RESTRICT coeffs, const bw_one_pole_coeffs * BW_RESTRICT coeffs,
const bw_one_pole_state * BW_RESTRICT state) { const bw_one_pole_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_one_pole_state")) if (state->hash != bw_hash_sdbm("bw_one_pole_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* Post-filter to decolorate oscillator waveshapers when antialiasing is on. * Post-filter to decolorate oscillator waveshapers when antialiasing is on.
@ -33,6 +33,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input value to * <li>Added initial input value to
@ -120,7 +125,7 @@ static inline void bw_osc_filt_reset_state_multi(
* corresponding initial input value in the `x_0` array. * corresponding initial input value in the `x_0` array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_osc_filt_process1() * #### bw_osc_filt_process1()
* ```>>> */ * ```>>> */
@ -194,7 +199,7 @@ struct bw_osc_filt_state {
static inline float bw_osc_filt_reset_state( static inline float bw_osc_filt_reset_state(
bw_osc_filt_state * BW_RESTRICT state, bw_osc_filt_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
state->z1 = 0.f; state->z1 = 0.f;
@ -214,28 +219,28 @@ static inline void bw_osc_filt_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_osc_filt_reset_state(state[i], x_0[i]); y_0[i] = bw_osc_filt_reset_state(state[i], x_0[i]);
else else
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_osc_filt_reset_state(state[i], x_0[i]); bw_osc_filt_reset_state(state[i], x_0[i]);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline float bw_osc_filt_process1( static inline float bw_osc_filt_process1(
bw_osc_filt_state * BW_RESTRICT state, bw_osc_filt_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_osc_filt_state_is_valid(state)); BW_ASSERT_DEEP(bw_osc_filt_state_is_valid(state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -253,11 +258,11 @@ static inline void bw_osc_filt_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_osc_filt_state_is_valid(state)); BW_ASSERT_DEEP(bw_osc_filt_state_is_valid(state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[i] = bw_osc_filt_process1(state, x[i]); y[i] = bw_osc_filt_process1(state, x[i]);
@ -272,14 +277,14 @@ static inline void bw_osc_filt_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -292,7 +297,7 @@ static inline void bw_osc_filt_process_multi(
static inline char bw_osc_filt_state_is_valid( static inline char bw_osc_filt_state_is_valid(
const bw_osc_filt_state * BW_RESTRICT state) { const bw_osc_filt_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_osc_filt_state")) if (state->hash != bw_hash_sdbm("bw_osc_filt_state"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Pulse oscillator waveshaper with variable pulse width (actually, duty * Pulse oscillator waveshaper with variable pulse width (actually, duty
@ -37,6 +37,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li><code>bw_osc_pulse_process()</code> and * <li><code>bw_osc_pulse_process()</code> and
@ -177,7 +182,7 @@ static inline void bw_osc_pulse_process(
* buffer `y`, while using and updating `coeffs` (control and audio rate). * buffer `y`, while using and updating `coeffs` (control and audio rate).
* *
* If antialiasing is enabled, `x_inc` must contain phase increment * If antialiasing is enabled, `x_inc` must contain phase increment
* values, otherwise it is ignored and can be `NULL`. * values, otherwise it is ignored and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -200,7 +205,7 @@ static inline void bw_osc_pulse_process_multi(
* *
* If antialiasing is enabled, each of the `n_channels` buffers pointed by * If antialiasing is enabled, each of the `n_channels` buffers pointed by
* `x_inc` must contain phase increment values, otherwise `x_inc` is ignored * `x_inc` must contain phase increment values, otherwise `x_inc` is ignored
* and can be `NULL`. * and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -284,7 +289,7 @@ struct bw_osc_pulse_coeffs {
static inline void bw_osc_pulse_init( static inline void bw_osc_pulse_init(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs) { bw_osc_pulse_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -302,7 +307,7 @@ static inline void bw_osc_pulse_init(
static inline void bw_osc_pulse_set_sample_rate( static inline void bw_osc_pulse_set_sample_rate(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs, bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -319,7 +324,7 @@ static inline void bw_osc_pulse_set_sample_rate(
static inline void bw_osc_pulse_reset_coeffs( static inline void bw_osc_pulse_reset_coeffs(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs) { bw_osc_pulse_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_set_sample_rate);
@ -334,7 +339,7 @@ static inline void bw_osc_pulse_reset_coeffs(
static inline void bw_osc_pulse_update_coeffs_ctrl( static inline void bw_osc_pulse_update_coeffs_ctrl(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs) { bw_osc_pulse_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
@ -343,7 +348,7 @@ static inline void bw_osc_pulse_update_coeffs_ctrl(
static inline void bw_osc_pulse_update_coeffs_audio( static inline void bw_osc_pulse_update_coeffs_audio(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs) { bw_osc_pulse_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
@ -356,7 +361,7 @@ static inline void bw_osc_pulse_update_coeffs_audio(
static inline float bw_osc_pulse_process1( static inline float bw_osc_pulse_process1(
const bw_osc_pulse_coeffs * BW_RESTRICT coeffs, const bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -384,7 +389,7 @@ static inline float bw_osc_pulse_process1_antialias(
const bw_osc_pulse_coeffs * BW_RESTRICT coeffs, const bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float x, float x,
float x_inc) { float x_inc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -425,14 +430,14 @@ static inline void bw_osc_pulse_process(
const float * x_inc, const float * x_inc,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(coeffs->antialiasing ? x_inc != NULL : 1); BW_ASSERT(coeffs->antialiasing ? x_inc != BW_NULL : 1);
BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1); BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->antialiasing) if (coeffs->antialiasing)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -457,11 +462,11 @@ static inline void bw_osc_pulse_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -488,7 +493,7 @@ static inline void bw_osc_pulse_process_multi(
static inline void bw_osc_pulse_set_antialiasing( static inline void bw_osc_pulse_set_antialiasing(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs, bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init);
@ -501,7 +506,7 @@ static inline void bw_osc_pulse_set_antialiasing(
static inline void bw_osc_pulse_set_pulse_width( static inline void bw_osc_pulse_set_pulse_width(
bw_osc_pulse_coeffs * BW_RESTRICT coeffs, bw_osc_pulse_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_pulse_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_pulse_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -515,7 +520,7 @@ static inline void bw_osc_pulse_set_pulse_width(
static inline char bw_osc_pulse_coeffs_is_valid( static inline char bw_osc_pulse_coeffs_is_valid(
const bw_osc_pulse_coeffs * BW_RESTRICT coeffs) { const bw_osc_pulse_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_osc_pulse_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_osc_pulse_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Sawtooth oscillator waveshaper with PolyBLEP antialiasing. * Sawtooth oscillator waveshaper with PolyBLEP antialiasing.
@ -36,6 +36,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_osc_saw_set_sample_rate()</code>, * <li>Added <code>bw_osc_saw_set_sample_rate()</code>,
@ -180,7 +185,7 @@ static inline void bw_osc_saw_process(
* buffer `y`, while using `coeffs`. * buffer `y`, while using `coeffs`.
* *
* If antialiasing is enabled, `x_inc` must contain phase increment values, * If antialiasing is enabled, `x_inc` must contain phase increment values,
* otherwise it is ignored and can be `NULL`. * otherwise it is ignored and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -202,7 +207,7 @@ static inline void bw_osc_saw_process_multi(
* *
* If antialiasing is enabled, each of the `n_channels` buffers pointed by * If antialiasing is enabled, each of the `n_channels` buffers pointed by
* `x_inc` must contain phase increment values, otherwise `x_inc` is ignored * `x_inc` must contain phase increment values, otherwise `x_inc` is ignored
* and can be `NULL`. * and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -268,7 +273,7 @@ struct bw_osc_saw_coeffs {
static inline void bw_osc_saw_init( static inline void bw_osc_saw_init(
bw_osc_saw_coeffs * BW_RESTRICT coeffs) { bw_osc_saw_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->antialiasing = 0; coeffs->antialiasing = 0;
@ -283,7 +288,7 @@ static inline void bw_osc_saw_init(
static inline void bw_osc_saw_set_sample_rate( static inline void bw_osc_saw_set_sample_rate(
bw_osc_saw_coeffs * BW_RESTRICT coeffs, bw_osc_saw_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -300,7 +305,7 @@ static inline void bw_osc_saw_set_sample_rate(
static inline void bw_osc_saw_reset_coeffs( static inline void bw_osc_saw_reset_coeffs(
bw_osc_saw_coeffs * BW_RESTRICT coeffs) { bw_osc_saw_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_set_sample_rate);
@ -315,7 +320,7 @@ static inline void bw_osc_saw_reset_coeffs(
static inline void bw_osc_saw_update_coeffs_ctrl( static inline void bw_osc_saw_update_coeffs_ctrl(
bw_osc_saw_coeffs * BW_RESTRICT coeffs) { bw_osc_saw_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
@ -324,7 +329,7 @@ static inline void bw_osc_saw_update_coeffs_ctrl(
static inline void bw_osc_saw_update_coeffs_audio( static inline void bw_osc_saw_update_coeffs_audio(
bw_osc_saw_coeffs * BW_RESTRICT coeffs) { bw_osc_saw_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
@ -334,7 +339,7 @@ static inline void bw_osc_saw_update_coeffs_audio(
static inline float bw_osc_saw_process1( static inline float bw_osc_saw_process1(
const bw_osc_saw_coeffs * BW_RESTRICT coeffs, const bw_osc_saw_coeffs * BW_RESTRICT coeffs,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -362,7 +367,7 @@ static inline float bw_osc_saw_process1_antialias(
const bw_osc_saw_coeffs * BW_RESTRICT coeffs, const bw_osc_saw_coeffs * BW_RESTRICT coeffs,
float x, float x,
float x_inc) { float x_inc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -396,14 +401,14 @@ static inline void bw_osc_saw_process(
const float * x_inc, const float * x_inc,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(coeffs->antialiasing ? x_inc != NULL : 1); BW_ASSERT(coeffs->antialiasing ? x_inc != BW_NULL : 1);
BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1); BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->antialiasing) if (coeffs->antialiasing)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -424,23 +429,23 @@ static inline void bw_osc_saw_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] != y[j]); BW_ASSERT(y[i] != y[j]);
#endif #endif
if (x_inc != NULL) if (x_inc != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_osc_saw_process(coeffs, x[i], x_inc[i], y[i], n_samples); bw_osc_saw_process(coeffs, x[i], x_inc[i], y[i], n_samples);
else else
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_osc_saw_process(coeffs, x[i], NULL, y[i], n_samples); bw_osc_saw_process(coeffs, x[i], BW_NULL, y[i], n_samples);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_reset_coeffs);
@ -449,7 +454,7 @@ static inline void bw_osc_saw_process_multi(
static inline void bw_osc_saw_set_antialiasing( static inline void bw_osc_saw_set_antialiasing(
bw_osc_saw_coeffs * BW_RESTRICT coeffs, bw_osc_saw_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_saw_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_saw_coeffs_state_init);
@ -461,7 +466,7 @@ static inline void bw_osc_saw_set_antialiasing(
static inline char bw_osc_saw_coeffs_is_valid( static inline char bw_osc_saw_coeffs_is_valid(
const bw_osc_saw_coeffs * BW_RESTRICT coeffs) { const bw_osc_saw_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_osc_saw_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_osc_saw_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Sinusoidal oscillator waveshaper. * Sinusoidal oscillator waveshaper.
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li><code>bw_osc_sin_process()</code> and * <li><code>bw_osc_sin_process()</code> and
@ -149,9 +154,9 @@ static inline void bw_osc_sin_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[i] = bw_osc_sin_process1(x[i]); y[i] = bw_osc_sin_process1(x[i]);
@ -164,8 +169,8 @@ static inline void bw_osc_sin_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Triangle oscillator waveshaper with variable slope (increasing time over * Triangle oscillator waveshaper with variable slope (increasing time over
@ -37,6 +37,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li><code>bw_osc_tri_process()</code> and * <li><code>bw_osc_tri_process()</code> and
@ -179,7 +184,7 @@ static inline void bw_osc_tri_process(
* buffer `y`, while using and updating `coeffs`. * buffer `y`, while using and updating `coeffs`.
* *
* If antialiasing is enabled, `x_inc` must contain phase increment values, * If antialiasing is enabled, `x_inc` must contain phase increment values,
* otherwise it is ignored and can be `NULL`. * otherwise it is ignored and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -201,7 +206,7 @@ static inline void bw_osc_tri_process_multi(
* common `coeffs` (control and audio rate). * common `coeffs` (control and audio rate).
* *
* If antialiasing is enabled, `x_inc` must contain `n_channels` buffers of * If antialiasing is enabled, `x_inc` must contain `n_channels` buffers of
* phase increment values, otherwise it is ignored and can be `NULL`. * phase increment values, otherwise it is ignored and can be `BW_NULL`.
* *
* All samples in `x` must be in [`0.f`, `1.f`). * All samples in `x` must be in [`0.f`, `1.f`).
* *
@ -285,7 +290,7 @@ struct bw_osc_tri_coeffs {
static inline void bw_osc_tri_init( static inline void bw_osc_tri_init(
bw_osc_tri_coeffs * BW_RESTRICT coeffs) { bw_osc_tri_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -303,7 +308,7 @@ static inline void bw_osc_tri_init(
static inline void bw_osc_tri_set_sample_rate( static inline void bw_osc_tri_set_sample_rate(
bw_osc_tri_coeffs * BW_RESTRICT coeffs, bw_osc_tri_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -320,7 +325,7 @@ static inline void bw_osc_tri_set_sample_rate(
static inline void bw_osc_tri_reset_coeffs( static inline void bw_osc_tri_reset_coeffs(
bw_osc_tri_coeffs * BW_RESTRICT coeffs) { bw_osc_tri_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_set_sample_rate);
@ -335,7 +340,7 @@ static inline void bw_osc_tri_reset_coeffs(
static inline void bw_osc_tri_update_coeffs_ctrl( static inline void bw_osc_tri_update_coeffs_ctrl(
bw_osc_tri_coeffs * BW_RESTRICT coeffs) { bw_osc_tri_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
@ -344,7 +349,7 @@ static inline void bw_osc_tri_update_coeffs_ctrl(
static inline void bw_osc_tri_update_coeffs_audio( static inline void bw_osc_tri_update_coeffs_audio(
bw_osc_tri_coeffs * BW_RESTRICT coeffs) { bw_osc_tri_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
@ -357,7 +362,7 @@ static inline void bw_osc_tri_update_coeffs_audio(
static inline float bw_osc_tri_process1( static inline float bw_osc_tri_process1(
const bw_osc_tri_coeffs * BW_RESTRICT coeffs, const bw_osc_tri_coeffs * BW_RESTRICT coeffs,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -386,7 +391,7 @@ static inline float bw_osc_tri_process1_antialias(
const bw_osc_tri_coeffs * BW_RESTRICT coeffs, const bw_osc_tri_coeffs * BW_RESTRICT coeffs,
float x, float x,
float x_inc) { float x_inc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -432,14 +437,14 @@ static inline void bw_osc_tri_process(
const float * x_inc, const float * x_inc,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(coeffs->antialiasing ? x_inc != NULL : 1); BW_ASSERT(coeffs->antialiasing ? x_inc != BW_NULL : 1);
BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1); BW_ASSERT_DEEP(coeffs->antialiasing ? bw_has_only_finite(x_inc, n_samples) : 1);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->antialiasing) if (coeffs->antialiasing)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -464,11 +469,11 @@ static inline void bw_osc_tri_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -495,7 +500,7 @@ static inline void bw_osc_tri_process_multi(
static inline void bw_osc_tri_set_antialiasing( static inline void bw_osc_tri_set_antialiasing(
bw_osc_tri_coeffs * BW_RESTRICT coeffs, bw_osc_tri_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init);
@ -508,7 +513,7 @@ static inline void bw_osc_tri_set_antialiasing(
static inline void bw_osc_tri_set_slope( static inline void bw_osc_tri_set_slope(
bw_osc_tri_coeffs * BW_RESTRICT coeffs, bw_osc_tri_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_osc_tri_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_osc_tri_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -522,7 +527,7 @@ static inline void bw_osc_tri_set_slope(
static inline char bw_osc_tri_coeffs_is_valid( static inline char bw_osc_tri_coeffs_is_valid(
const bw_osc_tri_coeffs * BW_RESTRICT coeffs) { const bw_osc_tri_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_osc_tri_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_osc_tri_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_one_pole }}} * requires {{{ bw_common bw_gain bw_math bw_one_pole }}}
* description {{{ * description {{{
* Stereo panner with -3 dB center pan law. * Stereo panner with -3 dB center pan law.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Now using parabolic curves instead of trigonometric ones.</li> * <li>Now using parabolic curves instead of trigonometric ones.</li>
@ -225,7 +230,7 @@ struct bw_pan_coeffs {
static inline void bw_pan_init( static inline void bw_pan_init(
bw_pan_coeffs * BW_RESTRICT coeffs) { bw_pan_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_gain_init(&coeffs->l_coeffs); bw_gain_init(&coeffs->l_coeffs);
bw_gain_init(&coeffs->r_coeffs); bw_gain_init(&coeffs->r_coeffs);
@ -242,7 +247,7 @@ static inline void bw_pan_init(
static inline void bw_pan_set_sample_rate( static inline void bw_pan_set_sample_rate(
bw_pan_coeffs * BW_RESTRICT coeffs, bw_pan_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -270,7 +275,7 @@ static inline void bw_pan_do_update_coeffs(
static inline void bw_pan_reset_coeffs( static inline void bw_pan_reset_coeffs(
bw_pan_coeffs * BW_RESTRICT coeffs) { bw_pan_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_set_sample_rate);
@ -287,7 +292,7 @@ static inline void bw_pan_reset_coeffs(
static inline void bw_pan_update_coeffs_ctrl( static inline void bw_pan_update_coeffs_ctrl(
bw_pan_coeffs * BW_RESTRICT coeffs) { bw_pan_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs);
@ -301,7 +306,7 @@ static inline void bw_pan_update_coeffs_ctrl(
static inline void bw_pan_update_coeffs_audio( static inline void bw_pan_update_coeffs_audio(
bw_pan_coeffs * BW_RESTRICT coeffs) { bw_pan_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs);
@ -317,12 +322,12 @@ static inline void bw_pan_process1(
float x, float x,
float * BW_RESTRICT y_l, float * BW_RESTRICT y_l,
float * BW_RESTRICT y_r) { float * BW_RESTRICT y_r) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
*y_l = bw_gain_process1(&coeffs->l_coeffs, x); *y_l = bw_gain_process1(&coeffs->l_coeffs, x);
@ -340,13 +345,13 @@ static inline void bw_pan_process(
float * y_l, float * y_l,
float * y_r, float * y_r,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
bw_pan_update_coeffs_ctrl(coeffs); bw_pan_update_coeffs_ctrl(coeffs);
@ -368,12 +373,12 @@ static inline void bw_pan_process_multi(
float * const * y_r, float * const * y_r,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_reset_coeffs);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -400,7 +405,7 @@ static inline void bw_pan_process_multi(
static inline void bw_pan_set_pan( static inline void bw_pan_set_pan(
bw_pan_coeffs * BW_RESTRICT coeffs, bw_pan_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pan_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_pan_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -414,7 +419,7 @@ static inline void bw_pan_set_pan(
static inline char bw_pan_coeffs_is_valid( static inline char bw_pan_coeffs_is_valid(
const bw_pan_coeffs * BW_RESTRICT coeffs) { const bw_pan_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_pan_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_pan_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_gain bw_math bw_mm2 bw_one_pole bw_svf }}} * requires {{{ bw_common bw_gain bw_math bw_mm2 bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Second-order peak filter with unitary gain at DC and asymptotically * Second-order peak filter with unitary gain at DC and asymptotically
@ -35,6 +35,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_peak_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_peak_reset_state_multi()</code> and updated C++
@ -157,7 +162,7 @@ static inline void bw_peak_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_peak_update_coeffs_ctrl() * #### bw_peak_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -352,8 +357,8 @@ static inline char bw_peak_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_peak_state`. * than or equal to that of `bw_peak_state`.
@ -421,7 +426,7 @@ struct bw_peak_state {
static inline void bw_peak_init( static inline void bw_peak_init(
bw_peak_coeffs * BW_RESTRICT coeffs) { bw_peak_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_mm2_init(&coeffs->mm2_coeffs); bw_mm2_init(&coeffs->mm2_coeffs);
coeffs->Q = 0.5f; coeffs->Q = 0.5f;
@ -441,7 +446,7 @@ static inline void bw_peak_init(
static inline void bw_peak_set_sample_rate( static inline void bw_peak_set_sample_rate(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -479,7 +484,7 @@ static inline void bw_peak_update_mm2_params(
static inline void bw_peak_reset_coeffs( static inline void bw_peak_reset_coeffs(
bw_peak_coeffs * BW_RESTRICT coeffs) { bw_peak_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->use_bandwidth BW_ASSERT_DEEP(coeffs->use_bandwidth
@ -503,10 +508,10 @@ static inline float bw_peak_reset_state(
const bw_peak_coeffs * BW_RESTRICT coeffs, const bw_peak_coeffs * BW_RESTRICT coeffs,
bw_peak_state * BW_RESTRICT state, bw_peak_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0); const float y = bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state, x_0);
@ -529,18 +534,18 @@ static inline void bw_peak_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_peak_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_peak_reset_state(coeffs, state[i], x_0[i]);
else else
@ -549,12 +554,12 @@ static inline void bw_peak_reset_state_multi(
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_peak_update_coeffs_ctrl( static inline void bw_peak_update_coeffs_ctrl(
bw_peak_coeffs * BW_RESTRICT coeffs) { bw_peak_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->use_bandwidth BW_ASSERT_DEEP(coeffs->use_bandwidth
@ -571,7 +576,7 @@ static inline void bw_peak_update_coeffs_ctrl(
static inline void bw_peak_update_coeffs_audio( static inline void bw_peak_update_coeffs_audio(
bw_peak_coeffs * BW_RESTRICT coeffs) { bw_peak_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->use_bandwidth BW_ASSERT_DEEP(coeffs->use_bandwidth
@ -589,14 +594,14 @@ static inline float bw_peak_process1(
const bw_peak_coeffs * BW_RESTRICT coeffs, const bw_peak_coeffs * BW_RESTRICT coeffs,
bw_peak_state * BW_RESTRICT state, bw_peak_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->use_bandwidth BW_ASSERT_DEEP(coeffs->use_bandwidth
? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f ? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f
&& bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f && bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f
: 1); : 1);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_peak_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_peak_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -616,18 +621,18 @@ static inline void bw_peak_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->use_bandwidth BW_ASSERT_DEEP(coeffs->use_bandwidth
? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f ? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f
&& bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f && bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f
: 1); : 1);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_peak_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_peak_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_peak_update_coeffs_ctrl(coeffs); bw_peak_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -648,7 +653,7 @@ static inline void bw_peak_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_reset_coeffs);
@ -656,14 +661,14 @@ static inline void bw_peak_process_multi(
? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f ? bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) >= 1e-6f
&& bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f && bw_sqrtf(bw_pow2f(coeffs->bandwidth) * coeffs->peak_gain) * bw_rcpf(bw_pow2f(coeffs->bandwidth) - 1.f) <= 1e6f
: 1); : 1);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -684,7 +689,7 @@ static inline void bw_peak_process_multi(
static inline void bw_peak_set_cutoff( static inline void bw_peak_set_cutoff(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -699,7 +704,7 @@ static inline void bw_peak_set_cutoff(
static inline void bw_peak_set_Q( static inline void bw_peak_set_Q(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -720,7 +725,7 @@ static inline void bw_peak_set_Q(
static inline void bw_peak_set_prewarp_at_cutoff( static inline void bw_peak_set_prewarp_at_cutoff(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
@ -733,7 +738,7 @@ static inline void bw_peak_set_prewarp_at_cutoff(
static inline void bw_peak_set_prewarp_freq( static inline void bw_peak_set_prewarp_freq(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -748,7 +753,7 @@ static inline void bw_peak_set_prewarp_freq(
static inline void bw_peak_set_peak_gain_lin( static inline void bw_peak_set_peak_gain_lin(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -769,7 +774,7 @@ static inline void bw_peak_set_peak_gain_lin(
static inline void bw_peak_set_peak_gain_dB( static inline void bw_peak_set_peak_gain_dB(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -784,7 +789,7 @@ static inline void bw_peak_set_peak_gain_dB(
static inline void bw_peak_set_bandwidth( static inline void bw_peak_set_bandwidth(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -805,7 +810,7 @@ static inline void bw_peak_set_bandwidth(
static inline void bw_peak_set_use_bandwidth( static inline void bw_peak_set_use_bandwidth(
bw_peak_coeffs * BW_RESTRICT coeffs, bw_peak_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_peak_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_peak_coeffs_state_init);
@ -823,7 +828,7 @@ static inline void bw_peak_set_use_bandwidth(
static inline char bw_peak_coeffs_is_valid( static inline char bw_peak_coeffs_is_valid(
const bw_peak_coeffs * BW_RESTRICT coeffs) { const bw_peak_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_peak_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_peak_coeffs"))
@ -852,17 +857,17 @@ static inline char bw_peak_coeffs_is_valid(
static inline char bw_peak_state_is_valid( static inline char bw_peak_state_is_valid(
const bw_peak_coeffs * BW_RESTRICT coeffs, const bw_peak_coeffs * BW_RESTRICT coeffs,
const bw_peak_state * BW_RESTRICT state) { const bw_peak_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_peak_state")) if (state->hash != bw_hash_sdbm("bw_peak_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : NULL, &state->mm2_state); return bw_mm2_state_is_valid(coeffs ? &coeffs->mm2_coeffs : BW_NULL, &state->mm2_state);
} }
#undef BW_PEAK_PARAM_Q #undef BW_PEAK_PARAM_Q

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,7 +31,8 @@
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>: * <li>Version <strong>1.0.1</strong>:
* <ul> * <ul>
* <li>Fixed rouding bug when frequency is tiny and negative.</li> * <li>Fixed rounding bug when frequency is tiny and negative.</li>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul> * </ul>
* </li> * </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
@ -169,7 +170,7 @@ static inline void bw_phase_gen_reset_state_multi(
* array. * array.
* *
* The corresponding initial output and phase increment values are put into * The corresponding initial output and phase increment values are put into
* the `y_0` and `y_inc_0` arrays, respectively, if they are not `NULL`. * the `y_0` and `y_inc_0` arrays, respectively, if they are not `BW_NULL`.
* *
* #### bw_phase_gen_update_coeffs_ctrl() * #### bw_phase_gen_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -222,10 +223,10 @@ static inline void bw_phase_gen_process(
* Generates and fills the first `n_samples` of the output buffer `y`, while * Generates and fills the first `n_samples` of the output buffer `y`, while
* using and updating both `coeffs` and `state` (control and audio rate). * using and updating both `coeffs` and `state` (control and audio rate).
* *
* If `x_mod` is not `NULL`, it is used as a source of exponential frequency * If `x_mod` is not `BW_NULL`, it is used as a source of exponential
* modulation (scale `1.f`/octave). * frequency modulation (scale `1.f`/octave).
* *
* If `y_inc` is not `NULL`, it is filled with phase increment values. * If `y_inc` is not `BW_NULL`, it is filled with phase increment values.
* *
* #### bw_phase_gen_process_multi() * #### bw_phase_gen_process_multi()
* ```>>> */ * ```>>> */
@ -242,12 +243,12 @@ static inline void bw_phase_gen_process_multi(
* buffers `y`, while using and updating both the common `coeffs` and each of * buffers `y`, while using and updating both the common `coeffs` and each of
* the `n_channels` `state`s (control and audio rate). * the `n_channels` `state`s (control and audio rate).
* *
* If `x_mod` and the channel-specific element are not `NULL`, this is used * If `x_mod` and the channel-specific element are not `BW_NULL`, this is
* as a source of exponential frequency modulation (scale `1.f`/octave) for * used as a source of exponential frequency modulation (scale `1.f`/octave)
* that channel. * for that channel.
* *
* If `y_inc` and the channel-specific element are not `NULL`, this is filled * If `y_inc` and the channel-specific element are not `BW_NULL`, this is
* with phase increment values for that channel. * filled with phase increment values for that channel.
* *
* #### bw_phase_gen_set_frequency() * #### bw_phase_gen_set_frequency()
* ```>>> */ * ```>>> */
@ -295,8 +296,8 @@ static inline char bw_phase_gen_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_phase_gen_state`. * than or equal to that of `bw_phase_gen_state`.
@ -360,7 +361,7 @@ struct bw_phase_gen_state {
static inline void bw_phase_gen_init( static inline void bw_phase_gen_init(
bw_phase_gen_coeffs * BW_RESTRICT coeffs) { bw_phase_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->portamento_coeffs); bw_one_pole_init(&coeffs->portamento_coeffs);
coeffs->frequency = 1.f; coeffs->frequency = 1.f;
@ -377,7 +378,7 @@ static inline void bw_phase_gen_init(
static inline void bw_phase_gen_set_sample_rate( static inline void bw_phase_gen_set_sample_rate(
bw_phase_gen_coeffs * BW_RESTRICT coeffs, bw_phase_gen_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -403,7 +404,7 @@ static inline void bw_phase_gen_do_update_coeffs_ctrl(
static inline void bw_phase_gen_reset_coeffs( static inline void bw_phase_gen_reset_coeffs(
bw_phase_gen_coeffs * BW_RESTRICT coeffs) { bw_phase_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_set_sample_rate);
@ -425,13 +426,13 @@ static inline void bw_phase_gen_reset_state(
float phase_0, float phase_0,
float * BW_RESTRICT y_0, float * BW_RESTRICT y_0,
float * BW_RESTRICT y_inc_0) { float * BW_RESTRICT y_inc_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(phase_0)); BW_ASSERT(bw_is_finite(phase_0));
BW_ASSERT(y_0 != NULL); BW_ASSERT(y_0 != BW_NULL);
BW_ASSERT(y_inc_0 != NULL); BW_ASSERT(y_inc_0 != BW_NULL);
BW_ASSERT(y_0 != y_inc_0); BW_ASSERT(y_0 != y_inc_0);
state->phase = phase_0; state->phase = phase_0;
@ -456,20 +457,20 @@ static inline void bw_phase_gen_reset_state_multi(
float * y_0, float * y_0,
float * y_inc_0, float * y_inc_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(phase_0 != NULL); BW_ASSERT(phase_0 != BW_NULL);
BW_ASSERT(y_0 != NULL && y_inc_0 != NULL ? y_0 != y_inc_0 : 1); BW_ASSERT(y_0 != BW_NULL && y_inc_0 != BW_NULL ? y_0 != y_inc_0 : 1);
if (y_0 != NULL) { if (y_0 != BW_NULL) {
if (y_inc_0 != NULL) { if (y_inc_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_phase_gen_reset_state(coeffs, state[i], phase_0[i], y_0 + i, y_inc_0 + i); bw_phase_gen_reset_state(coeffs, state[i], phase_0[i], y_0 + i, y_inc_0 + i);
} else { } else {
@ -479,7 +480,7 @@ static inline void bw_phase_gen_reset_state_multi(
} }
} }
} else { } else {
if (y_inc_0 != NULL) { if (y_inc_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) { for (size_t i = 0; i < n_channels; i++) {
float v; float v;
bw_phase_gen_reset_state(coeffs, state[i], phase_0[i], &v, y_inc_0 + i); bw_phase_gen_reset_state(coeffs, state[i], phase_0[i], &v, y_inc_0 + i);
@ -494,13 +495,13 @@ static inline void bw_phase_gen_reset_state_multi(
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
BW_ASSERT_DEEP(y_inc_0 != NULL ? bw_has_only_finite(y_inc_0, n_channels) : 1); BW_ASSERT_DEEP(y_inc_0 != BW_NULL ? bw_has_only_finite(y_inc_0, n_channels) : 1);
} }
static inline void bw_phase_gen_update_coeffs_ctrl( static inline void bw_phase_gen_update_coeffs_ctrl(
bw_phase_gen_coeffs * BW_RESTRICT coeffs) { bw_phase_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
@ -512,7 +513,7 @@ static inline void bw_phase_gen_update_coeffs_ctrl(
static inline void bw_phase_gen_update_coeffs_audio( static inline void bw_phase_gen_update_coeffs_audio(
bw_phase_gen_coeffs * BW_RESTRICT coeffs) { bw_phase_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
@ -535,13 +536,13 @@ static inline void bw_phase_gen_process1(
bw_phase_gen_state * BW_RESTRICT state, bw_phase_gen_state * BW_RESTRICT state,
float * BW_RESTRICT y, float * BW_RESTRICT y,
float * BW_RESTRICT y_inc) { float * BW_RESTRICT y_inc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT(y_inc != NULL); BW_ASSERT(y_inc != BW_NULL);
BW_ASSERT(y != y_inc); BW_ASSERT(y != y_inc);
*y_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state); *y_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state);
@ -561,14 +562,14 @@ static inline void bw_phase_gen_process1_mod(
float x_mod, float x_mod,
float * BW_RESTRICT y, float * BW_RESTRICT y,
float * BW_RESTRICT y_inc) { float * BW_RESTRICT y_inc) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x_mod)); BW_ASSERT(bw_is_finite(x_mod));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT(y_inc != NULL); BW_ASSERT(y_inc != BW_NULL);
BW_ASSERT(y != y_inc); BW_ASSERT(y != y_inc);
*y_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state) * bw_pow2f(x_mod); *y_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state) * bw_pow2f(x_mod);
@ -589,18 +590,18 @@ static inline void bw_phase_gen_process(
float * y, float * y,
float * y_inc, float * y_inc,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(x_mod != NULL ? bw_has_only_finite(x_mod, n_samples) : 1); BW_ASSERT_DEEP(x_mod != BW_NULL ? bw_has_only_finite(x_mod, n_samples) : 1);
BW_ASSERT(y != NULL && y_inc != NULL ? y != y_inc : 1); BW_ASSERT(y != BW_NULL && y_inc != BW_NULL ? y != y_inc : 1);
bw_phase_gen_update_coeffs_ctrl(coeffs); bw_phase_gen_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (x_mod != NULL) { if (x_mod != BW_NULL) {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, y_inc + i); bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, y_inc + i);
@ -612,7 +613,7 @@ static inline void bw_phase_gen_process(
bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, &v_phase_inc); bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, &v_phase_inc);
} }
} else { } else {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
bw_phase_gen_process1(coeffs, state, y + i, y_inc + i); bw_phase_gen_process1(coeffs, state, y + i, y_inc + i);
@ -625,8 +626,8 @@ static inline void bw_phase_gen_process(
} }
} }
} else { } else {
if (x_mod != NULL) { if (x_mod != BW_NULL) {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
float v; float v;
@ -639,7 +640,7 @@ static inline void bw_phase_gen_process(
bw_phase_gen_process1_mod(coeffs, state, x_mod[i], &v, &v_phase_inc); bw_phase_gen_process1_mod(coeffs, state, x_mod[i], &v, &v_phase_inc);
} }
} else { } else {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
float v; float v;
@ -657,8 +658,8 @@ static inline void bw_phase_gen_process(
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phase_gen_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
BW_ASSERT_DEEP(y_inc != NULL ? bw_has_only_finite(y_inc, n_samples) : 1); BW_ASSERT_DEEP(y_inc != BW_NULL ? bw_has_only_finite(y_inc, n_samples) : 1);
} }
static inline void bw_phase_gen_process_multi( static inline void bw_phase_gen_process_multi(
@ -669,32 +670,32 @@ static inline void bw_phase_gen_process_multi(
float * const * y_inc, float * const * y_inc,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] != y[j]); BW_ASSERT(y[i] != y[j]);
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y_inc[i] != y_inc[j]); BW_ASSERT(y_inc[i] != y_inc[j]);
if (y != NULL && y_inc != NULL) if (y != BW_NULL && y_inc != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
BW_ASSERT(y[i] != y_inc[j]); BW_ASSERT(y[i] != y_inc[j]);
#endif #endif
bw_phase_gen_update_coeffs_ctrl(coeffs); bw_phase_gen_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (x_mod != NULL) { if (x_mod != BW_NULL) {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -723,7 +724,7 @@ static inline void bw_phase_gen_process_multi(
} }
} }
} else { } else {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -747,8 +748,8 @@ static inline void bw_phase_gen_process_multi(
} }
} }
} else { } else {
if (x_mod != NULL) { if (x_mod != BW_NULL) {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -773,7 +774,7 @@ static inline void bw_phase_gen_process_multi(
} }
} }
} else { } else {
if (y_inc != NULL) if (y_inc != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_phase_gen_update_coeffs_audio(coeffs); bw_phase_gen_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -801,7 +802,7 @@ static inline void bw_phase_gen_process_multi(
static inline void bw_phase_gen_set_frequency( static inline void bw_phase_gen_set_frequency(
bw_phase_gen_coeffs * BW_RESTRICT coeffs, bw_phase_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -815,7 +816,7 @@ static inline void bw_phase_gen_set_frequency(
static inline void bw_phase_gen_set_portamento_tau( static inline void bw_phase_gen_set_portamento_tau(
bw_phase_gen_coeffs * BW_RESTRICT coeffs, bw_phase_gen_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phase_gen_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phase_gen_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -829,7 +830,7 @@ static inline void bw_phase_gen_set_portamento_tau(
static inline char bw_phase_gen_coeffs_is_valid( static inline char bw_phase_gen_coeffs_is_valid(
const bw_phase_gen_coeffs * BW_RESTRICT coeffs) { const bw_phase_gen_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_phase_gen_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_phase_gen_coeffs"))
@ -867,13 +868,13 @@ static inline char bw_phase_gen_coeffs_is_valid(
static inline char bw_phase_gen_state_is_valid( static inline char bw_phase_gen_state_is_valid(
const bw_phase_gen_coeffs * BW_RESTRICT coeffs, const bw_phase_gen_coeffs * BW_RESTRICT coeffs,
const bw_phase_gen_state * BW_RESTRICT state) { const bw_phase_gen_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_phase_gen_state")) if (state->hash != bw_hash_sdbm("bw_phase_gen_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_ap1 bw_common bw_lp1 bw_math bw_one_pole bw_osc_sin bw_phase_gen * bw_ap1 bw_common bw_lp1 bw_math bw_one_pole bw_osc_sin bw_phase_gen
* }}} * }}}
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input value to * <li>Added initial input value to
@ -145,7 +150,7 @@ static inline void bw_phaser_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_phaser_update_coeffs_ctrl() * #### bw_phaser_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -267,8 +272,8 @@ static inline char bw_phaser_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_phaser_state`. * than or equal to that of `bw_phaser_state`.
@ -330,7 +335,7 @@ struct bw_phaser_state {
static inline void bw_phaser_init( static inline void bw_phaser_init(
bw_phaser_coeffs * BW_RESTRICT coeffs) { bw_phaser_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_phase_gen_init(&coeffs->phase_gen_coeffs); bw_phase_gen_init(&coeffs->phase_gen_coeffs);
bw_ap1_init(&coeffs->ap1_coeffs); bw_ap1_init(&coeffs->ap1_coeffs);
@ -349,7 +354,7 @@ static inline void bw_phaser_init(
static inline void bw_phaser_set_sample_rate( static inline void bw_phaser_set_sample_rate(
bw_phaser_coeffs * BW_RESTRICT coeffs, bw_phaser_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -366,7 +371,7 @@ static inline void bw_phaser_set_sample_rate(
static inline void bw_phaser_reset_coeffs( static inline void bw_phaser_reset_coeffs(
bw_phaser_coeffs * BW_RESTRICT coeffs) { bw_phaser_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_set_sample_rate);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
@ -389,10 +394,10 @@ static inline float bw_phaser_reset_state(
const bw_phaser_coeffs * BW_RESTRICT coeffs, const bw_phaser_coeffs * BW_RESTRICT coeffs,
bw_phaser_state * BW_RESTRICT state, bw_phaser_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float y = bw_ap1_reset_state(&coeffs->ap1_coeffs, &state->ap1_state[0], x_0); float y = bw_ap1_reset_state(&coeffs->ap1_coeffs, &state->ap1_state[0], x_0);
@ -418,18 +423,18 @@ static inline void bw_phaser_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_phaser_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_phaser_reset_state(coeffs, state[i], x_0[i]);
else else
@ -438,12 +443,12 @@ static inline void bw_phaser_reset_state_multi(
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_phaser_update_coeffs_ctrl( static inline void bw_phaser_update_coeffs_ctrl(
bw_phaser_coeffs *BW_RESTRICT coeffs) { bw_phaser_coeffs *BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
@ -456,7 +461,7 @@ static inline void bw_phaser_update_coeffs_ctrl(
static inline void bw_phaser_update_coeffs_audio( static inline void bw_phaser_update_coeffs_audio(
bw_phaser_coeffs * BW_RESTRICT coeffs) { bw_phaser_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
@ -477,11 +482,11 @@ static inline float bw_phaser_process1(
const bw_phaser_coeffs * BW_RESTRICT coeffs, const bw_phaser_coeffs * BW_RESTRICT coeffs,
bw_phaser_state * BW_RESTRICT state, bw_phaser_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phaser_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -504,15 +509,15 @@ static inline void bw_phaser_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_phaser_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_phaser_update_coeffs_ctrl(coeffs); bw_phaser_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -533,18 +538,18 @@ static inline void bw_phaser_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f); BW_ASSERT_DEEP(coeffs->center * bw_pow2f(coeffs->amount) >= 1e-6f && coeffs->center * bw_pow2f(coeffs->amount) <= 1e12f);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -565,7 +570,7 @@ static inline void bw_phaser_process_multi(
static inline void bw_phaser_set_rate( static inline void bw_phaser_set_rate(
bw_phaser_coeffs * BW_RESTRICT coeffs, bw_phaser_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -579,7 +584,7 @@ static inline void bw_phaser_set_rate(
static inline void bw_phaser_set_center( static inline void bw_phaser_set_center(
bw_phaser_coeffs * BW_RESTRICT coeffs, bw_phaser_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -594,7 +599,7 @@ static inline void bw_phaser_set_center(
static inline void bw_phaser_set_amount( static inline void bw_phaser_set_amount(
bw_phaser_coeffs * BW_RESTRICT coeffs, bw_phaser_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_phaser_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_phaser_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -608,7 +613,7 @@ static inline void bw_phaser_set_amount(
static inline char bw_phaser_coeffs_is_valid( static inline char bw_phaser_coeffs_is_valid(
const bw_phaser_coeffs * BW_RESTRICT coeffs) { const bw_phaser_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_phaser_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_phaser_coeffs"))
@ -636,20 +641,20 @@ static inline char bw_phaser_coeffs_is_valid(
static inline char bw_phaser_state_is_valid( static inline char bw_phaser_state_is_valid(
const bw_phaser_coeffs * BW_RESTRICT coeffs, const bw_phaser_coeffs * BW_RESTRICT coeffs,
const bw_phaser_state * BW_RESTRICT state) { const bw_phaser_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_phaser_state")) if (state->hash != bw_hash_sdbm("bw_phaser_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : NULL, &state->ap1_state[0]) return bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : BW_NULL, &state->ap1_state[0])
&& bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : NULL, &state->ap1_state[1]) && bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : BW_NULL, &state->ap1_state[1])
&& bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : NULL, &state->ap1_state[2]) && bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : BW_NULL, &state->ap1_state[2])
&& bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : NULL, &state->ap1_state[3]); && bw_ap1_state_is_valid(coeffs ? &coeffs->ap1_coeffs : BW_NULL, &state->ap1_state[3]);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* Pinking filter. * Pinking filter.
@ -40,6 +40,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_pink_filt_reset_coeffs()</code>, * <li>Added <code>bw_pink_filt_reset_coeffs()</code>,
@ -175,7 +180,7 @@ static inline void bw_pink_filt_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_pink_filt_update_coeffs_ctrl() * #### bw_pink_filt_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -290,8 +295,8 @@ static inline char bw_pink_filt_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_pink_filt_state`. * than or equal to that of `bw_pink_filt_state`.
@ -348,7 +353,7 @@ struct bw_pink_filt_state {
static inline void bw_pink_filt_init( static inline void bw_pink_filt_init(
bw_pink_filt_coeffs * BW_RESTRICT coeffs) { bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->sample_rate_scaling = 0; coeffs->sample_rate_scaling = 0;
@ -364,7 +369,7 @@ static inline void bw_pink_filt_init(
static inline void bw_pink_filt_set_sample_rate( static inline void bw_pink_filt_set_sample_rate(
bw_pink_filt_coeffs * BW_RESTRICT coeffs, bw_pink_filt_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -380,7 +385,7 @@ static inline void bw_pink_filt_set_sample_rate(
static inline void bw_pink_filt_reset_coeffs( static inline void bw_pink_filt_reset_coeffs(
bw_pink_filt_coeffs * BW_RESTRICT coeffs) { bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_set_sample_rate);
@ -398,10 +403,10 @@ static inline float bw_pink_filt_reset_state(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs, const bw_pink_filt_coeffs * BW_RESTRICT coeffs,
bw_pink_filt_state * BW_RESTRICT state, bw_pink_filt_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
(void)coeffs; (void)coeffs;
@ -429,18 +434,18 @@ static inline void bw_pink_filt_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_pink_filt_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_pink_filt_reset_state(coeffs, state[i], x_0[i]);
else else
@ -449,12 +454,12 @@ static inline void bw_pink_filt_reset_state_multi(
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_pink_filt_update_coeffs_ctrl( static inline void bw_pink_filt_update_coeffs_ctrl(
bw_pink_filt_coeffs * BW_RESTRICT coeffs) { bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
@ -463,7 +468,7 @@ static inline void bw_pink_filt_update_coeffs_ctrl(
static inline void bw_pink_filt_update_coeffs_audio( static inline void bw_pink_filt_update_coeffs_audio(
bw_pink_filt_coeffs * BW_RESTRICT coeffs) { bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
@ -474,10 +479,10 @@ static inline float bw_pink_filt_process1(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs, const bw_pink_filt_coeffs * BW_RESTRICT coeffs,
bw_pink_filt_state * BW_RESTRICT state, bw_pink_filt_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -503,10 +508,10 @@ static inline float bw_pink_filt_process1_scaling(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs, const bw_pink_filt_coeffs * BW_RESTRICT coeffs,
bw_pink_filt_state * BW_RESTRICT state, bw_pink_filt_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -526,14 +531,14 @@ static inline void bw_pink_filt_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_pink_filt_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->sample_rate_scaling) if (coeffs->sample_rate_scaling)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -555,17 +560,17 @@ static inline void bw_pink_filt_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -582,7 +587,7 @@ static inline void bw_pink_filt_process_multi(
static inline void bw_pink_filt_set_sample_rate_scaling( static inline void bw_pink_filt_set_sample_rate_scaling(
bw_pink_filt_coeffs * BW_RESTRICT coeffs, bw_pink_filt_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_init);
@ -594,7 +599,7 @@ static inline void bw_pink_filt_set_sample_rate_scaling(
static inline float bw_pink_filt_get_scaling_k( static inline float bw_pink_filt_get_scaling_k(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs) { const bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_pink_filt_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_pink_filt_coeffs_state_set_sample_rate);
@ -603,7 +608,7 @@ static inline float bw_pink_filt_get_scaling_k(
static inline char bw_pink_filt_coeffs_is_valid( static inline char bw_pink_filt_coeffs_is_valid(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs) { const bw_pink_filt_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_pink_filt_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_pink_filt_coeffs"))
@ -623,13 +628,13 @@ static inline char bw_pink_filt_coeffs_is_valid(
static inline char bw_pink_filt_state_is_valid( static inline char bw_pink_filt_state_is_valid(
const bw_pink_filt_coeffs * BW_RESTRICT coeffs, const bw_pink_filt_coeffs * BW_RESTRICT coeffs,
const bw_pink_filt_state * BW_RESTRICT state) { const bw_pink_filt_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_pink_filt_state")) if (state->hash != bw_hash_sdbm("bw_pink_filt_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_env_follow bw_math bw_one_pole }}} * requires {{{ bw_common bw_env_follow bw_math bw_one_pole }}}
* description {{{ * description {{{
* Digital peak programme meter with adjustable integration time constant. * Digital peak programme meter with adjustable integration time constant.
@ -30,6 +30,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Enforced minimum output value <code>-600.f</code>.</li> * <li>Enforced minimum output value <code>-600.f</code>.</li>
@ -144,7 +149,7 @@ static inline void bw_ppm_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_ppm_update_coeffs_ctrl() * #### bw_ppm_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -186,7 +191,7 @@ static inline void bw_ppm_process(
* *
* Output sample values are in dBFS (minimum `-600.f`). * Output sample values are in dBFS (minimum `-600.f`).
* *
* `y` may be `NULL`. * `y` may be `BW_NULL`.
* *
* #### bw_ppm_process_multi() * #### bw_ppm_process_multi()
* ```>>> */ * ```>>> */
@ -205,7 +210,7 @@ static inline void bw_ppm_process_multi(
* *
* Output sample values are in dBFS (minimum `-600.f`). * Output sample values are in dBFS (minimum `-600.f`).
* *
* `y` or any element of `y` may be `NULL`. * `y` or any element of `y` may be `BW_NULL`.
* *
* #### bw_ppm_set_integration_time() * #### bw_ppm_set_integration_time()
* ```>>> */ * ```>>> */
@ -248,8 +253,8 @@ static inline char bw_ppm_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_ppm_state`. * than or equal to that of `bw_ppm_state`.
@ -304,7 +309,7 @@ struct bw_ppm_state {
static inline void bw_ppm_init( static inline void bw_ppm_init(
bw_ppm_coeffs * BW_RESTRICT coeffs) { bw_ppm_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_env_follow_init(&coeffs->env_follow_coeffs); bw_env_follow_init(&coeffs->env_follow_coeffs);
bw_env_follow_set_release_tau(&coeffs->env_follow_coeffs, 0.738300619235528f); bw_env_follow_set_release_tau(&coeffs->env_follow_coeffs, 0.738300619235528f);
@ -321,7 +326,7 @@ static inline void bw_ppm_init(
static inline void bw_ppm_set_sample_rate( static inline void bw_ppm_set_sample_rate(
bw_ppm_coeffs * BW_RESTRICT coeffs, bw_ppm_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -337,7 +342,7 @@ static inline void bw_ppm_set_sample_rate(
static inline void bw_ppm_reset_coeffs( static inline void bw_ppm_reset_coeffs(
bw_ppm_coeffs * BW_RESTRICT coeffs) { bw_ppm_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_set_sample_rate);
@ -355,10 +360,10 @@ static inline float bw_ppm_reset_state(
const bw_ppm_coeffs * BW_RESTRICT coeffs, const bw_ppm_coeffs * BW_RESTRICT coeffs,
bw_ppm_state * BW_RESTRICT state, bw_ppm_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float yl = bw_env_follow_reset_state(&coeffs->env_follow_coeffs, &state->env_follow_state, x_0); const float yl = bw_env_follow_reset_state(&coeffs->env_follow_coeffs, &state->env_follow_state, x_0);
@ -383,18 +388,18 @@ static inline void bw_ppm_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_ppm_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_ppm_reset_state(coeffs, state[i], x_0[i]);
else else
@ -403,12 +408,12 @@ static inline void bw_ppm_reset_state_multi(
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_ppm_update_coeffs_ctrl( static inline void bw_ppm_update_coeffs_ctrl(
bw_ppm_coeffs * BW_RESTRICT coeffs) { bw_ppm_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
@ -420,7 +425,7 @@ static inline void bw_ppm_update_coeffs_ctrl(
static inline void bw_ppm_update_coeffs_audio( static inline void bw_ppm_update_coeffs_audio(
bw_ppm_coeffs * BW_RESTRICT coeffs) { bw_ppm_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
@ -434,10 +439,10 @@ static inline float bw_ppm_process1(
const bw_ppm_coeffs * BW_RESTRICT coeffs, const bw_ppm_coeffs * BW_RESTRICT coeffs,
bw_ppm_state * BW_RESTRICT state, bw_ppm_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -459,16 +464,16 @@ static inline void bw_ppm_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
bw_ppm_update_coeffs_ctrl(coeffs); bw_ppm_update_coeffs_ctrl(coeffs);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_ppm_update_coeffs_audio(coeffs); bw_ppm_update_coeffs_audio(coeffs);
y[i] = bw_ppm_process1(coeffs, state, x[i]); y[i] = bw_ppm_process1(coeffs, state, x[i]);
@ -482,7 +487,7 @@ static inline void bw_ppm_process(
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_ppm_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
} }
static inline void bw_ppm_process_multi( static inline void bw_ppm_process_multi(
@ -492,30 +497,30 @@ static inline void bw_ppm_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] == NULL || y[j] == NULL || y[i] != y[j]); BW_ASSERT(y[i] == BW_NULL || y[j] == BW_NULL || y[i] != y[j]);
#endif #endif
bw_ppm_update_coeffs_ctrl(coeffs); bw_ppm_update_coeffs_ctrl(coeffs);
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_ppm_update_coeffs_audio(coeffs); bw_ppm_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
const float v = bw_ppm_process1(coeffs, state[j], x[j][i]); const float v = bw_ppm_process1(coeffs, state[j], x[j][i]);
if (y[j] != NULL) if (y[j] != BW_NULL)
y[j][i] = v; y[j][i] = v;
} }
} }
@ -533,7 +538,7 @@ static inline void bw_ppm_process_multi(
static inline void bw_ppm_set_integration_tau( static inline void bw_ppm_set_integration_tau(
bw_ppm_coeffs * BW_RESTRICT coeffs, bw_ppm_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ppm_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ppm_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -546,15 +551,15 @@ static inline void bw_ppm_set_integration_tau(
} }
static inline float bw_ppm_get_y_z1(const bw_ppm_state *BW_RESTRICT state) { static inline float bw_ppm_get_y_z1(const bw_ppm_state *BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_ppm_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_ppm_state_is_valid(BW_NULL, state));
return state->y_z1; return state->y_z1;
} }
static inline char bw_ppm_coeffs_is_valid( static inline char bw_ppm_coeffs_is_valid(
const bw_ppm_coeffs * BW_RESTRICT coeffs) { const bw_ppm_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ppm_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ppm_coeffs"))
@ -569,20 +574,20 @@ static inline char bw_ppm_coeffs_is_valid(
static inline char bw_ppm_state_is_valid( static inline char bw_ppm_state_is_valid(
const bw_ppm_coeffs * BW_RESTRICT coeffs, const bw_ppm_coeffs * BW_RESTRICT coeffs,
const bw_ppm_state * BW_RESTRICT state) { const bw_ppm_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_ppm_state")) if (state->hash != bw_hash_sdbm("bw_ppm_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
if (!bw_is_finite(state->y_z1) || state->y_z1 < -600.f) if (!bw_is_finite(state->y_z1) || state->y_z1 < -600.f)
return 0.f; return 0.f;
return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : NULL, &state->env_follow_state); return bw_env_follow_state_is_valid(coeffs ? &coeffs->env_follow_coeffs : BW_NULL, &state->env_follow_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ utility }}} * module_type {{{ utility }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common }}} * requires {{{ bw_common }}}
* description {{{ * description {{{
* Pseudo-random number generators. * Pseudo-random number generators.
@ -42,6 +42,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added one more assertion in <code>bw_randf()</code>.</li> * <li>Added one more assertion in <code>bw_randf()</code>.</li>
@ -119,7 +124,7 @@ extern "C" {
static inline uint32_t bw_randu32( static inline uint32_t bw_randu32(
uint64_t * BW_RESTRICT state) { uint64_t * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
// Permuted Congruential Generator, // Permuted Congruential Generator,
// taken from https://nullprogram.com/blog/2017/09/21/ // taken from https://nullprogram.com/blog/2017/09/21/
*state = *state * 0x9b60933458e17d7d + 0xd737232eeccdf7ed; *state = *state * 0x9b60933458e17d7d + 0xd737232eeccdf7ed;
@ -128,7 +133,7 @@ static inline uint32_t bw_randu32(
static inline float bw_randf( static inline float bw_randf(
uint64_t * BW_RESTRICT state) { uint64_t * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
const float y = (2.f / (float)UINT32_MAX) * (float)bw_randu32(state) - 1.f; const float y = (2.f / (float)UINT32_MAX) * (float)bw_randu32(state) - 1.f;
BW_ASSERT(bw_is_finite(y)); BW_ASSERT(bw_is_finite(y));
return y; return y;

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_buf bw_common bw_delay bw_dry_wet bw_gain bw_lp1 bw_math bw_one_pole * bw_buf bw_common bw_delay bw_dry_wet bw_gain bw_lp1 bw_math bw_one_pole
* bw_osc_sin bw_phase_gen * bw_osc_sin bw_phase_gen
@ -35,6 +35,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial value arguments in * <li>Added initial value arguments in
@ -170,7 +175,7 @@ static inline void bw_reverb_reset_state_multi(
* (left) and `x_r_0` (right) arrays. * (left) and `x_r_0` (right) arrays.
* *
* The corresponding initial output values are written into the `y_l_0` * The corresponding initial output values are written into the `y_l_0`
* (left) and `y_r_0` arrays, if each is not `NULL`. * (left) and `y_r_0` arrays, if each is not `BW_NULL`.
* *
* #### bw_reverb_update_coeffs_ctrl() * #### bw_reverb_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -316,8 +321,8 @@ static inline char bw_reverb_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_reverb_state`. * than or equal to that of `bw_reverb_state`.
@ -455,7 +460,7 @@ struct bw_reverb_state {
static inline void bw_reverb_init( static inline void bw_reverb_init(
bw_reverb_coeffs * BW_RESTRICT coeffs) { bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_delay_init(&coeffs->predelay_coeffs, 0.1f); bw_delay_init(&coeffs->predelay_coeffs, 0.1f);
bw_lp1_init(&coeffs->bandwidth_coeffs); bw_lp1_init(&coeffs->bandwidth_coeffs);
@ -498,7 +503,7 @@ static inline void bw_reverb_init(
static inline void bw_reverb_set_sample_rate( static inline void bw_reverb_set_sample_rate(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -559,7 +564,7 @@ static inline void bw_reverb_set_sample_rate(
static inline size_t bw_reverb_mem_req( static inline size_t bw_reverb_mem_req(
const bw_reverb_coeffs * BW_RESTRICT coeffs) { const bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate);
@ -582,11 +587,11 @@ static inline void bw_reverb_mem_set(
const bw_reverb_coeffs * BW_RESTRICT coeffs, const bw_reverb_coeffs * BW_RESTRICT coeffs,
bw_reverb_state * BW_RESTRICT state, bw_reverb_state * BW_RESTRICT state,
void * BW_RESTRICT mem) { void * BW_RESTRICT mem) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(mem != NULL); BW_ASSERT(mem != BW_NULL);
char *m = (char *)mem; char *m = (char *)mem;
bw_delay_mem_set(&coeffs->predelay_coeffs, &state->predelay_state, m); bw_delay_mem_set(&coeffs->predelay_coeffs, &state->predelay_state, m);
@ -627,7 +632,7 @@ static inline void bw_reverb_mem_set(
static inline void bw_reverb_reset_coeffs( static inline void bw_reverb_reset_coeffs(
bw_reverb_coeffs * BW_RESTRICT coeffs) { bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_set_sample_rate);
@ -671,16 +676,16 @@ static inline void bw_reverb_reset_state(
float x_r_0, float x_r_0,
float * BW_RESTRICT y_l_0, float * BW_RESTRICT y_l_0,
float * BW_RESTRICT y_r_0) { float * BW_RESTRICT y_r_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_mem_set); BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_mem_set);
BW_ASSERT(bw_is_finite(x_l_0)); BW_ASSERT(bw_is_finite(x_l_0));
BW_ASSERT(bw_is_finite(x_r_0)); BW_ASSERT(bw_is_finite(x_r_0));
BW_ASSERT(y_l_0 != NULL); BW_ASSERT(y_l_0 != BW_NULL);
BW_ASSERT(y_r_0 != NULL); BW_ASSERT(y_r_0 != BW_NULL);
BW_ASSERT(y_l_0 != y_r_0); BW_ASSERT(y_l_0 != y_r_0);
const float i = 0.5f * (x_l_0 + x_r_0); const float i = 0.5f * (x_l_0 + x_r_0);
@ -739,21 +744,21 @@ static inline void bw_reverb_reset_state_multi(
float * y_l_0, float * y_l_0,
float * y_r_0, float * y_r_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_l_0 != NULL); BW_ASSERT(x_l_0 != BW_NULL);
BW_ASSERT(x_r_0 != NULL); BW_ASSERT(x_r_0 != BW_NULL);
BW_ASSERT(y_l_0 != NULL && y_r_0 != NULL ? y_l_0 != y_r_0 : 1); BW_ASSERT(y_l_0 != BW_NULL && y_r_0 != BW_NULL ? y_l_0 != y_r_0 : 1);
if (y_l_0 != NULL) { if (y_l_0 != BW_NULL) {
if (y_r_0 != NULL) { if (y_r_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], y_l_0 + i, y_r_0 + i); bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], y_l_0 + i, y_r_0 + i);
} else { } else {
@ -762,7 +767,7 @@ static inline void bw_reverb_reset_state_multi(
bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], y_l_0 + i, &yr); bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], y_l_0 + i, &yr);
} }
} else { } else {
if (y_r_0 != NULL) { if (y_r_0 != BW_NULL) {
float yl; float yl;
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], &yl, y_r_0 + i); bw_reverb_reset_state(coeffs, state[i], x_l_0[i], x_r_0[i], &yl, y_r_0 + i);
@ -775,13 +780,13 @@ static inline void bw_reverb_reset_state_multi(
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_l_0 != NULL ? bw_has_only_finite(y_l_0, n_channels) : 1); BW_ASSERT_DEEP(y_l_0 != BW_NULL ? bw_has_only_finite(y_l_0, n_channels) : 1);
BW_ASSERT_DEEP(y_r_0 != NULL ? bw_has_only_finite(y_r_0, n_channels) : 1); BW_ASSERT_DEEP(y_r_0 != BW_NULL ? bw_has_only_finite(y_r_0, n_channels) : 1);
} }
static inline void bw_reverb_update_coeffs_ctrl( static inline void bw_reverb_update_coeffs_ctrl(
bw_reverb_coeffs * BW_RESTRICT coeffs) { bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
@ -797,7 +802,7 @@ static inline void bw_reverb_update_coeffs_ctrl(
static inline void bw_reverb_update_coeffs_audio( static inline void bw_reverb_update_coeffs_audio(
bw_reverb_coeffs * BW_RESTRICT coeffs) { bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
@ -827,16 +832,16 @@ static inline void bw_reverb_process1(
float x_r, float x_r,
float * y_l, float * y_l,
float * y_r) { float * y_r) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_reset_state);
BW_ASSERT(bw_is_finite(x_l)); BW_ASSERT(bw_is_finite(x_l));
BW_ASSERT(bw_is_finite(x_r)); BW_ASSERT(bw_is_finite(x_r));
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
const float i = 0.5f * (x_l + x_r); const float i = 0.5f * (x_l + x_r);
@ -936,18 +941,18 @@ static inline void bw_reverb_process(
float * y_l, float * y_l,
float * y_r, float * y_r,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_reverb_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_reset_state); BW_ASSERT_DEEP(state->state >= bw_reverb_state_state_reset_state);
BW_ASSERT(x_l != NULL); BW_ASSERT(x_l != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_l, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_l, n_samples));
BW_ASSERT(x_r != NULL); BW_ASSERT(x_r != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_r, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_r, n_samples));
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
bw_reverb_update_coeffs_ctrl(coeffs); bw_reverb_update_coeffs_ctrl(coeffs);
@ -973,19 +978,19 @@ static inline void bw_reverb_process_multi(
float * const * y_r, float * const * y_r,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_l != NULL); BW_ASSERT(x_l != BW_NULL);
BW_ASSERT(x_r != NULL); BW_ASSERT(x_r != BW_NULL);
BW_ASSERT(y_l != NULL); BW_ASSERT(y_l != BW_NULL);
BW_ASSERT(y_r != NULL); BW_ASSERT(y_r != BW_NULL);
BW_ASSERT(y_l != y_r); BW_ASSERT(y_l != y_r);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -1012,7 +1017,7 @@ static inline void bw_reverb_process_multi(
static inline void bw_reverb_set_predelay( static inline void bw_reverb_set_predelay(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -1027,7 +1032,7 @@ static inline void bw_reverb_set_predelay(
static inline void bw_reverb_set_bandwidth( static inline void bw_reverb_set_bandwidth(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -1042,7 +1047,7 @@ static inline void bw_reverb_set_bandwidth(
static inline void bw_reverb_set_damping( static inline void bw_reverb_set_damping(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -1057,7 +1062,7 @@ static inline void bw_reverb_set_damping(
static inline void bw_reverb_set_decay( static inline void bw_reverb_set_decay(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -1072,7 +1077,7 @@ static inline void bw_reverb_set_decay(
static inline void bw_reverb_set_wet( static inline void bw_reverb_set_wet(
bw_reverb_coeffs * BW_RESTRICT coeffs, bw_reverb_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_reverb_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_reverb_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -1086,7 +1091,7 @@ static inline void bw_reverb_set_wet(
static inline char bw_reverb_coeffs_is_valid( static inline char bw_reverb_coeffs_is_valid(
const bw_reverb_coeffs * BW_RESTRICT coeffs) { const bw_reverb_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_reverb_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_reverb_coeffs"))
@ -1145,7 +1150,7 @@ static inline char bw_reverb_coeffs_is_valid(
static inline char bw_reverb_state_is_valid( static inline char bw_reverb_state_is_valid(
const bw_reverb_coeffs * BW_RESTRICT coeffs, const bw_reverb_coeffs * BW_RESTRICT coeffs,
const bw_reverb_state * BW_RESTRICT state) { const bw_reverb_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_reverb_state")) if (state->hash != bw_hash_sdbm("bw_reverb_state"))
@ -1154,29 +1159,29 @@ static inline char bw_reverb_state_is_valid(
return 0; return 0;
if (state->state >= bw_reverb_state_state_reset_state) { if (state->state >= bw_reverb_state_state_reset_state) {
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
if (!bw_lp1_state_is_valid(coeffs ? &coeffs->bandwidth_coeffs : NULL, &state->bandwidth_state) if (!bw_lp1_state_is_valid(coeffs ? &coeffs->bandwidth_coeffs : BW_NULL, &state->bandwidth_state)
|| !bw_lp1_state_is_valid(coeffs ? &coeffs->damping_coeffs : NULL, &state->damping_1_state) || !bw_lp1_state_is_valid(coeffs ? &coeffs->damping_coeffs : BW_NULL, &state->damping_1_state)
|| !bw_lp1_state_is_valid(coeffs ? &coeffs->damping_coeffs : NULL, &state->damping_2_state)) || !bw_lp1_state_is_valid(coeffs ? &coeffs->damping_coeffs : BW_NULL, &state->damping_2_state))
return 0; return 0;
} }
#endif #endif
return bw_delay_state_is_valid(coeffs ? &coeffs->predelay_coeffs : NULL, &state->predelay_state) return bw_delay_state_is_valid(coeffs ? &coeffs->predelay_coeffs : BW_NULL, &state->predelay_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_id1_coeffs : NULL, &state->delay_id1_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_id1_coeffs : BW_NULL, &state->delay_id1_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_id2_coeffs : NULL, &state->delay_id2_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_id2_coeffs : BW_NULL, &state->delay_id2_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_id3_coeffs : NULL, &state->delay_id3_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_id3_coeffs : BW_NULL, &state->delay_id3_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_id4_coeffs : NULL, &state->delay_id4_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_id4_coeffs : BW_NULL, &state->delay_id4_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd1_coeffs : NULL, &state->delay_dd1_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd1_coeffs : BW_NULL, &state->delay_dd1_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd2_coeffs : NULL, &state->delay_dd2_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd2_coeffs : BW_NULL, &state->delay_dd2_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd3_coeffs : NULL, &state->delay_dd3_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd3_coeffs : BW_NULL, &state->delay_dd3_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd4_coeffs : NULL, &state->delay_dd4_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_dd4_coeffs : BW_NULL, &state->delay_dd4_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_d1_coeffs : NULL, &state->delay_d1_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_d1_coeffs : BW_NULL, &state->delay_d1_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_d2_coeffs : NULL, &state->delay_d2_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_d2_coeffs : BW_NULL, &state->delay_d2_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_d3_coeffs : NULL, &state->delay_d3_state) && bw_delay_state_is_valid(coeffs ? &coeffs->delay_d3_coeffs : BW_NULL, &state->delay_d3_state)
&& bw_delay_state_is_valid(coeffs ? &coeffs->delay_d4_coeffs : NULL, &state->delay_d4_state); && bw_delay_state_is_valid(coeffs ? &coeffs->delay_d4_coeffs : BW_NULL, &state->delay_d4_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Ring modulator with variable modulation amount. * Ring modulator with variable modulation amount.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Module renamed as bw_ring_mod.</li> * <li>Module renamed as bw_ring_mod.</li>
@ -226,7 +231,7 @@ struct bw_ring_mod_coeffs {
static inline void bw_ring_mod_init( static inline void bw_ring_mod_init(
bw_ring_mod_coeffs * BW_RESTRICT coeffs) { bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
@ -243,7 +248,7 @@ static inline void bw_ring_mod_init(
static inline void bw_ring_mod_set_sample_rate( static inline void bw_ring_mod_set_sample_rate(
bw_ring_mod_coeffs * BW_RESTRICT coeffs, bw_ring_mod_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -260,7 +265,7 @@ static inline void bw_ring_mod_set_sample_rate(
static inline void bw_ring_mod_reset_coeffs( static inline void bw_ring_mod_reset_coeffs(
bw_ring_mod_coeffs * BW_RESTRICT coeffs) { bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_set_sample_rate);
@ -275,7 +280,7 @@ static inline void bw_ring_mod_reset_coeffs(
static inline void bw_ring_mod_update_coeffs_ctrl( static inline void bw_ring_mod_update_coeffs_ctrl(
bw_ring_mod_coeffs * BW_RESTRICT coeffs) { bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
@ -284,7 +289,7 @@ static inline void bw_ring_mod_update_coeffs_ctrl(
static inline void bw_ring_mod_update_coeffs_audio( static inline void bw_ring_mod_update_coeffs_audio(
bw_ring_mod_coeffs * BW_RESTRICT coeffs) { bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
@ -298,7 +303,7 @@ static inline float bw_ring_mod_process1(
const bw_ring_mod_coeffs * BW_RESTRICT coeffs, const bw_ring_mod_coeffs * BW_RESTRICT coeffs,
float x_mod, float x_mod,
float x_car) { float x_car) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
BW_ASSERT(bw_is_finite(x_mod)); BW_ASSERT(bw_is_finite(x_mod));
@ -320,14 +325,14 @@ static inline void bw_ring_mod_process(
const float * x_car, const float * x_car,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
BW_ASSERT(x_mod != NULL); BW_ASSERT(x_mod != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_mod, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_mod, n_samples));
BW_ASSERT(x_car != NULL); BW_ASSERT(x_car != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x_car, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x_car, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_ring_mod_update_coeffs_audio(coeffs); bw_ring_mod_update_coeffs_audio(coeffs);
@ -346,12 +351,12 @@ static inline void bw_ring_mod_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_reset_coeffs);
BW_ASSERT(x_mod != NULL); BW_ASSERT(x_mod != BW_NULL);
BW_ASSERT(x_car != NULL); BW_ASSERT(x_car != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -371,7 +376,7 @@ static inline void bw_ring_mod_process_multi(
static inline void bw_ring_mod_set_amount( static inline void bw_ring_mod_set_amount(
bw_ring_mod_coeffs * BW_RESTRICT coeffs, bw_ring_mod_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_ring_mod_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_ring_mod_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -385,7 +390,7 @@ static inline void bw_ring_mod_set_amount(
static inline char bw_ring_mod_coeffs_is_valid( static inline char bw_ring_mod_coeffs_is_valid(
const bw_ring_mod_coeffs * BW_RESTRICT coeffs) { const bw_ring_mod_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_ring_mod_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_ring_mod_coeffs"))

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* Antialiased tanh-based saturation with parametric bias and gain * Antialiased tanh-based saturation with parametric bias and gain
@ -45,6 +45,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Changed default value for gain compensation to off.</li> * <li>Changed default value for gain compensation to off.</li>
@ -166,7 +171,7 @@ static inline void bw_satur_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_satur_update_coeffs_ctrl() * #### bw_satur_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -288,8 +293,8 @@ static inline char bw_satur_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_satur_state`. * than or equal to that of `bw_satur_state`.
@ -362,7 +367,7 @@ static inline float bw_satur_tanhf(
static inline void bw_satur_init( static inline void bw_satur_init(
bw_satur_coeffs * BW_RESTRICT coeffs) { bw_satur_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -383,7 +388,7 @@ static inline void bw_satur_init(
static inline void bw_satur_set_sample_rate( static inline void bw_satur_set_sample_rate(
bw_satur_coeffs * BW_RESTRICT coeffs, bw_satur_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -415,7 +420,7 @@ static inline void bw_satur_do_update_coeffs(
static inline void bw_satur_reset_coeffs( static inline void bw_satur_reset_coeffs(
bw_satur_coeffs * BW_RESTRICT coeffs) { bw_satur_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_set_sample_rate);
@ -435,10 +440,10 @@ static inline float bw_satur_reset_state(
const bw_satur_coeffs * BW_RESTRICT coeffs, const bw_satur_coeffs * BW_RESTRICT coeffs,
bw_satur_state * BW_RESTRICT state, bw_satur_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
const float x = bw_one_pole_get_y_z1(&coeffs->smooth_gain_state) * x_0 + bw_one_pole_get_y_z1(&coeffs->smooth_bias_state); const float x = bw_one_pole_get_y_z1(&coeffs->smooth_gain_state) * x_0 + bw_one_pole_get_y_z1(&coeffs->smooth_bias_state);
@ -467,18 +472,18 @@ static inline void bw_satur_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_satur_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_satur_reset_state(coeffs, state[i], x_0[i]);
else else
@ -487,12 +492,12 @@ static inline void bw_satur_reset_state_multi(
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_satur_update_coeffs_ctrl( static inline void bw_satur_update_coeffs_ctrl(
bw_satur_coeffs * BW_RESTRICT coeffs) { bw_satur_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
@ -501,7 +506,7 @@ static inline void bw_satur_update_coeffs_ctrl(
static inline void bw_satur_update_coeffs_audio( static inline void bw_satur_update_coeffs_audio(
bw_satur_coeffs * BW_RESTRICT coeffs) { bw_satur_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
@ -515,10 +520,10 @@ static inline float bw_satur_process1(
const bw_satur_coeffs * BW_RESTRICT coeffs, const bw_satur_coeffs * BW_RESTRICT coeffs,
bw_satur_state * BW_RESTRICT state, bw_satur_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -543,10 +548,10 @@ static inline float bw_satur_process1_comp(
const bw_satur_coeffs * BW_RESTRICT coeffs, const bw_satur_coeffs * BW_RESTRICT coeffs,
bw_satur_state * BW_RESTRICT state, bw_satur_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -566,14 +571,14 @@ static inline void bw_satur_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_satur_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
if (coeffs->gain_compensation) if (coeffs->gain_compensation)
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -599,17 +604,17 @@ static inline void bw_satur_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -630,7 +635,7 @@ static inline void bw_satur_process_multi(
static inline void bw_satur_set_bias( static inline void bw_satur_set_bias(
bw_satur_coeffs * BW_RESTRICT coeffs, bw_satur_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -645,7 +650,7 @@ static inline void bw_satur_set_bias(
static inline void bw_satur_set_gain( static inline void bw_satur_set_gain(
bw_satur_coeffs * BW_RESTRICT coeffs, bw_satur_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -660,7 +665,7 @@ static inline void bw_satur_set_gain(
static inline void bw_satur_set_gain_compensation( static inline void bw_satur_set_gain_compensation(
bw_satur_coeffs * BW_RESTRICT coeffs, bw_satur_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_satur_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_satur_coeffs_state_init);
@ -672,7 +677,7 @@ static inline void bw_satur_set_gain_compensation(
static inline char bw_satur_coeffs_is_valid( static inline char bw_satur_coeffs_is_valid(
const bw_satur_coeffs * BW_RESTRICT coeffs) { const bw_satur_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_satur_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_satur_coeffs"))
@ -709,13 +714,13 @@ static inline char bw_satur_coeffs_is_valid(
static inline char bw_satur_state_is_valid( static inline char bw_satur_state_is_valid(
const bw_satur_coeffs * BW_RESTRICT coeffs, const bw_satur_coeffs * BW_RESTRICT coeffs,
const bw_satur_state * BW_RESTRICT state) { const bw_satur_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_satur_state")) if (state->hash != bw_hash_sdbm("bw_satur_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Slew-rate limiter with separate maximum increasing and decreasing rates. * Slew-rate limiter with separate maximum increasing and decreasing rates.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_slew_lim_reset_state_multi()</code> and updated * <li>Added <code>bw_slew_lim_reset_state_multi()</code> and updated
@ -150,7 +155,7 @@ static inline void bw_slew_lim_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the * The corresponding initial output values are written into the
* `y_0` array, if not `NULL`. * `y_0` array, if not `BW_NULL`.
* *
* #### bw_slew_lim_update_coeffs_ctrl() * #### bw_slew_lim_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -219,7 +224,7 @@ static inline void bw_slew_lim_process(
* first `n_samples` of the output buffer `y`, while using and updating both * first `n_samples` of the output buffer `y`, while using and updating both
* `coeffs` and `state` (control and audio rate). * `coeffs` and `state` (control and audio rate).
* *
* `y` may be `NULL`. * `y` may be `BW_NULL`.
* *
* #### bw_slew_lim_process_multi() * #### bw_slew_lim_process_multi()
* ```>>> */ * ```>>> */
@ -236,7 +241,7 @@ static inline void bw_slew_lim_process_multi(
* using and updating both the common `coeffs` and each of the `n_channels` * using and updating both the common `coeffs` and each of the `n_channels`
* `state`s (control and audio rate). * `state`s (control and audio rate).
* *
* `y` or any element of `y` may be `NULL`. * `y` or any element of `y` may be `BW_NULL`.
* *
* #### bw_slew_lim_set_max_rate() * #### bw_slew_lim_set_max_rate()
* ```>>> */ * ```>>> */
@ -316,8 +321,8 @@ static inline char bw_slew_lim_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_slew_lim_state`. * than or equal to that of `bw_slew_lim_state`.
@ -377,7 +382,7 @@ struct bw_slew_lim_state {
static inline void bw_slew_lim_init( static inline void bw_slew_lim_init(
bw_slew_lim_coeffs * BW_RESTRICT coeffs) { bw_slew_lim_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->max_rate_up = INFINITY; coeffs->max_rate_up = INFINITY;
coeffs->max_rate_down = INFINITY; coeffs->max_rate_down = INFINITY;
@ -394,7 +399,7 @@ static inline void bw_slew_lim_init(
static inline void bw_slew_lim_set_sample_rate( static inline void bw_slew_lim_set_sample_rate(
bw_slew_lim_coeffs * BW_RESTRICT coeffs, bw_slew_lim_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -417,7 +422,7 @@ static inline void bw_slew_lim_do_update_coeffs_ctrl(
static inline void bw_slew_lim_reset_coeffs( static inline void bw_slew_lim_reset_coeffs(
bw_slew_lim_coeffs * BW_RESTRICT coeffs) { bw_slew_lim_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_set_sample_rate);
@ -435,10 +440,10 @@ static inline float bw_slew_lim_reset_state(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
bw_slew_lim_state * BW_RESTRICT state, bw_slew_lim_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
(void)coeffs; (void)coeffs;
@ -463,18 +468,18 @@ static inline void bw_slew_lim_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_slew_lim_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_slew_lim_reset_state(coeffs, state[i], x_0[i]);
else else
@ -483,12 +488,12 @@ static inline void bw_slew_lim_reset_state_multi(
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_slew_lim_update_coeffs_ctrl( static inline void bw_slew_lim_update_coeffs_ctrl(
bw_slew_lim_coeffs * BW_RESTRICT coeffs) { bw_slew_lim_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
@ -500,7 +505,7 @@ static inline void bw_slew_lim_update_coeffs_ctrl(
static inline void bw_slew_lim_update_coeffs_audio( static inline void bw_slew_lim_update_coeffs_audio(
bw_slew_lim_coeffs * BW_RESTRICT coeffs) { bw_slew_lim_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
@ -511,10 +516,10 @@ static inline float bw_slew_lim_process1(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
bw_slew_lim_state * BW_RESTRICT state, bw_slew_lim_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(bw_is_finite(coeffs->max_inc) && bw_is_finite(coeffs->max_dec)); BW_ASSERT(bw_is_finite(coeffs->max_inc) && bw_is_finite(coeffs->max_dec));
@ -534,10 +539,10 @@ static inline float bw_slew_lim_process1_up(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
bw_slew_lim_state * BW_RESTRICT state, bw_slew_lim_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(bw_is_finite(coeffs->max_inc)); BW_ASSERT(bw_is_finite(coeffs->max_inc));
@ -557,10 +562,10 @@ static inline float bw_slew_lim_process1_down(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
bw_slew_lim_state * BW_RESTRICT state, bw_slew_lim_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(bw_is_finite(coeffs->max_dec)); BW_ASSERT(bw_is_finite(coeffs->max_dec));
@ -580,10 +585,10 @@ static inline float bw_slew_lim_process1_none(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
bw_slew_lim_state * BW_RESTRICT state, bw_slew_lim_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -603,16 +608,16 @@ static inline void bw_slew_lim_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
bw_slew_lim_update_coeffs_ctrl(coeffs); bw_slew_lim_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (coeffs->max_rate_up != INFINITY) { if (coeffs->max_rate_up != INFINITY) {
if (coeffs->max_rate_down != INFINITY) if (coeffs->max_rate_down != INFINITY)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
@ -650,7 +655,7 @@ static inline void bw_slew_lim_process(
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y != NULL ? bw_has_only_finite(y, n_samples) : 1); BW_ASSERT_DEEP(y != BW_NULL ? bw_has_only_finite(y, n_samples) : 1);
} }
static inline void bw_slew_lim_process_multi( static inline void bw_slew_lim_process_multi(
@ -660,29 +665,29 @@ static inline void bw_slew_lim_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y != NULL) if (y != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y[i] == NULL || y[j] == NULL || y[i] != y[j]); BW_ASSERT(y[i] == BW_NULL || y[j] == BW_NULL || y[i] != y[j]);
#endif #endif
bw_slew_lim_update_coeffs_ctrl(coeffs); bw_slew_lim_update_coeffs_ctrl(coeffs);
if (y != NULL) { if (y != BW_NULL) {
if (coeffs->max_rate_up != INFINITY) { if (coeffs->max_rate_up != INFINITY) {
if (coeffs->max_rate_down != INFINITY) if (coeffs->max_rate_down != INFINITY)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_slew_lim_process1(coeffs, state[j], x[j][i]); y[j][i] = bw_slew_lim_process1(coeffs, state[j], x[j][i]);
else else
@ -691,14 +696,14 @@ static inline void bw_slew_lim_process_multi(
else else
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
if (y[j] != NULL) if (y[j] != BW_NULL)
y[j][i] = bw_slew_lim_process1_up(coeffs, state[j], x[j][i]); y[j][i] = bw_slew_lim_process1_up(coeffs, state[j], x[j][i]);
else else
bw_slew_lim_process1_up(coeffs, state[j], x[j][i]); bw_slew_lim_process1_up(coeffs, state[j], x[j][i]);
} else { } else {
if (coeffs->max_rate_down != INFINITY) if (coeffs->max_rate_down != INFINITY)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = bw_slew_lim_process1_down(coeffs, state[j], x[j][i]); y[j][i] = bw_slew_lim_process1_down(coeffs, state[j], x[j][i]);
else else
@ -706,18 +711,18 @@ static inline void bw_slew_lim_process_multi(
bw_slew_lim_process1_down(coeffs, state[j], x[j][i]); bw_slew_lim_process1_down(coeffs, state[j], x[j][i]);
else else
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
BW_ASSERT(state[j] != NULL); BW_ASSERT(state[j] != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j])); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j]));
BW_ASSERT(x[j] != NULL); BW_ASSERT(x[j] != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x[j], n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x[j], n_samples));
if (y[j] != NULL) if (y[j] != BW_NULL)
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[j][i] = x[j][i]; y[j][i] = x[j][i];
state[j]->y_z1 = x[j][n_samples - 1]; state[j]->y_z1 = x[j][n_samples - 1];
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j])); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j]));
BW_ASSERT_DEEP(y[j] != NULL ? bw_has_only_finite(y[j], n_samples) : 1); BW_ASSERT_DEEP(y[j] != BW_NULL ? bw_has_only_finite(y[j], n_samples) : 1);
} }
} }
} else { } else {
@ -737,9 +742,9 @@ static inline void bw_slew_lim_process_multi(
bw_slew_lim_process1_down(coeffs, state[j], x[j][i]); bw_slew_lim_process1_down(coeffs, state[j], x[j][i]);
else else
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
BW_ASSERT(state[j] != NULL); BW_ASSERT(state[j] != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j])); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(coeffs, state[j]));
BW_ASSERT(x[j] != NULL); BW_ASSERT(x[j] != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x[j], n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x[j], n_samples));
state[j]->y_z1 = x[j][n_samples - 1]; state[j]->y_z1 = x[j][n_samples - 1];
@ -756,7 +761,7 @@ static inline void bw_slew_lim_process_multi(
static inline void bw_slew_lim_set_max_rate( static inline void bw_slew_lim_set_max_rate(
bw_slew_lim_coeffs * BW_RESTRICT coeffs, bw_slew_lim_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -772,7 +777,7 @@ static inline void bw_slew_lim_set_max_rate(
static inline void bw_slew_lim_set_max_rate_up( static inline void bw_slew_lim_set_max_rate_up(
bw_slew_lim_coeffs * BW_RESTRICT coeffs, bw_slew_lim_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -787,7 +792,7 @@ static inline void bw_slew_lim_set_max_rate_up(
static inline void bw_slew_lim_set_max_rate_down( static inline void bw_slew_lim_set_max_rate_down(
bw_slew_lim_coeffs * BW_RESTRICT coeffs, bw_slew_lim_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_slew_lim_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_slew_lim_coeffs_state_init);
BW_ASSERT(!bw_is_nan(value)); BW_ASSERT(!bw_is_nan(value));
@ -801,15 +806,15 @@ static inline void bw_slew_lim_set_max_rate_down(
static inline float bw_slew_lim_get_y_z1( static inline float bw_slew_lim_get_y_z1(
const bw_slew_lim_state * BW_RESTRICT state) { const bw_slew_lim_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(NULL, state)); BW_ASSERT_DEEP(bw_slew_lim_state_is_valid(BW_NULL, state));
return state->y_z1; return state->y_z1;
} }
static inline char bw_slew_lim_coeffs_is_valid( static inline char bw_slew_lim_coeffs_is_valid(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs) { const bw_slew_lim_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_slew_lim_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_slew_lim_coeffs"))
@ -843,13 +848,13 @@ static inline char bw_slew_lim_coeffs_is_valid(
static inline char bw_slew_lim_state_is_valid( static inline char bw_slew_lim_state_is_valid(
const bw_slew_lim_coeffs * BW_RESTRICT coeffs, const bw_slew_lim_coeffs * BW_RESTRICT coeffs,
const bw_slew_lim_state * BW_RESTRICT state) { const bw_slew_lim_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_slew_lim_state")) if (state->hash != bw_hash_sdbm("bw_slew_lim_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Sample rate reducer. * Sample rate reducer.
@ -31,6 +31,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_sr_reduce_set_sample_rate()</code>, * <li>Added <code>bw_sr_reduce_set_sample_rate()</code>,
@ -152,7 +157,7 @@ static inline void bw_sr_reduce_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_sr_reduce_update_coeffs_ctrl() * #### bw_sr_reduce_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -240,8 +245,8 @@ static inline char bw_sr_reduce_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_sr_reduce_state`. * than or equal to that of `bw_sr_reduce_state`.
@ -295,7 +300,7 @@ struct bw_sr_reduce_state {
static inline void bw_sr_reduce_init( static inline void bw_sr_reduce_init(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs) { bw_sr_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
coeffs->ratio = 1.f; coeffs->ratio = 1.f;
@ -311,7 +316,7 @@ static inline void bw_sr_reduce_init(
static inline void bw_sr_reduce_set_sample_rate( static inline void bw_sr_reduce_set_sample_rate(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs, bw_sr_reduce_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -328,7 +333,7 @@ static inline void bw_sr_reduce_set_sample_rate(
static inline void bw_sr_reduce_reset_coeffs( static inline void bw_sr_reduce_reset_coeffs(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs) { bw_sr_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_set_sample_rate);
@ -346,10 +351,10 @@ static inline float bw_sr_reduce_reset_state(
const bw_sr_reduce_coeffs * BW_RESTRICT coeffs, const bw_sr_reduce_coeffs * BW_RESTRICT coeffs,
bw_sr_reduce_state * BW_RESTRICT state, bw_sr_reduce_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
(void)coeffs; (void)coeffs;
@ -375,18 +380,18 @@ static inline void bw_sr_reduce_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_sr_reduce_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_sr_reduce_reset_state(coeffs, state[i], x_0[i]);
else else
@ -395,12 +400,12 @@ static inline void bw_sr_reduce_reset_state_multi(
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_sr_reduce_update_coeffs_ctrl( static inline void bw_sr_reduce_update_coeffs_ctrl(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs) { bw_sr_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
@ -409,7 +414,7 @@ static inline void bw_sr_reduce_update_coeffs_ctrl(
static inline void bw_sr_reduce_update_coeffs_audio( static inline void bw_sr_reduce_update_coeffs_audio(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs) { bw_sr_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
@ -420,10 +425,10 @@ static inline float bw_sr_reduce_process1(
const bw_sr_reduce_coeffs * BW_RESTRICT coeffs, const bw_sr_reduce_coeffs * BW_RESTRICT coeffs,
bw_sr_reduce_state * BW_RESTRICT state, bw_sr_reduce_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_sr_reduce_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -448,14 +453,14 @@ static inline void bw_sr_reduce_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_sr_reduce_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
for (size_t i = 0; i < n_samples; i++) for (size_t i = 0; i < n_samples; i++)
y[i] = bw_sr_reduce_process1(coeffs, state, x[i]); y[i] = bw_sr_reduce_process1(coeffs, state, x[i]);
@ -473,17 +478,17 @@ static inline void bw_sr_reduce_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -500,7 +505,7 @@ static inline void bw_sr_reduce_process_multi(
static inline void bw_sr_reduce_set_ratio( static inline void bw_sr_reduce_set_ratio(
bw_sr_reduce_coeffs * BW_RESTRICT coeffs, bw_sr_reduce_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_sr_reduce_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_sr_reduce_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -514,7 +519,7 @@ static inline void bw_sr_reduce_set_ratio(
static inline char bw_sr_reduce_coeffs_is_valid( static inline char bw_sr_reduce_coeffs_is_valid(
const bw_sr_reduce_coeffs * BW_RESTRICT coeffs) { const bw_sr_reduce_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_sr_reduce_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_sr_reduce_coeffs"))
@ -529,13 +534,13 @@ static inline char bw_sr_reduce_coeffs_is_valid(
static inline char bw_sr_reduce_state_is_valid( static inline char bw_sr_reduce_state_is_valid(
const bw_sr_reduce_coeffs * BW_RESTRICT coeffs, const bw_sr_reduce_coeffs * BW_RESTRICT coeffs,
const bw_sr_reduce_state * BW_RESTRICT state) { const bw_sr_reduce_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_sr_reduce_state")) if (state->hash != bw_hash_sdbm("bw_sr_reduce_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Aribtrary-ratio IIR sample rate converter. * Aribtrary-ratio IIR sample rate converter.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_src_reset_state_multi()</code> and updated C++ * <li>Added <code>bw_src_reset_state_multi()</code> and updated C++
@ -130,7 +135,7 @@ static inline void bw_src_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_src_process() * #### bw_src_process()
* ```>>> */ * ```>>> */
@ -200,8 +205,8 @@ static inline char bw_src_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_src_state`. * than or equal to that of `bw_src_state`.
@ -257,7 +262,7 @@ struct bw_src_state {
static inline void bw_src_init( static inline void bw_src_init(
bw_src_coeffs * BW_RESTRICT coeffs, bw_src_coeffs * BW_RESTRICT coeffs,
float ratio) { float ratio) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(ratio > 0.f); BW_ASSERT(ratio > 0.f);
coeffs->k = ratio >= 1.f ? 1.f / ratio : -1.f / ratio; coeffs->k = ratio >= 1.f ? 1.f / ratio : -1.f / ratio;
@ -283,9 +288,9 @@ static inline float bw_src_reset_state(
const bw_src_coeffs * BW_RESTRICT coeffs, const bw_src_coeffs * BW_RESTRICT coeffs,
bw_src_state * BW_RESTRICT state, bw_src_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
if (coeffs->k < 0) { if (coeffs->k < 0) {
@ -325,17 +330,17 @@ static inline void bw_src_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_src_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_src_reset_state(coeffs, state[i], x_0[i]);
else else
@ -343,7 +348,7 @@ static inline void bw_src_reset_state_multi(
bw_src_reset_state(coeffs, state[i], x_0[i]); bw_src_reset_state(coeffs, state[i], x_0[i]);
BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_src_process( static inline void bw_src_process(
@ -353,16 +358,16 @@ static inline void bw_src_process(
float * BW_RESTRICT y, float * BW_RESTRICT y,
size_t * BW_RESTRICT n_in_samples, size_t * BW_RESTRICT n_in_samples,
size_t * BW_RESTRICT n_out_samples) { size_t * BW_RESTRICT n_out_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_src_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_src_state_is_valid(coeffs, state));
BW_ASSERT(n_in_samples != NULL); BW_ASSERT(n_in_samples != BW_NULL);
BW_ASSERT(n_out_samples != NULL); BW_ASSERT(n_out_samples != BW_NULL);
BW_ASSERT(n_in_samples != n_out_samples); BW_ASSERT(n_in_samples != n_out_samples);
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, *n_in_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, *n_in_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT(x != y); BW_ASSERT(x != y);
size_t i = 0; size_t i = 0;
@ -444,16 +449,16 @@ static inline void bw_src_process_multi(
size_t n_channels, size_t n_channels,
size_t * BW_RESTRICT n_in_samples, size_t * BW_RESTRICT n_in_samples,
size_t * BW_RESTRICT n_out_samples) { size_t * BW_RESTRICT n_out_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT((void *)x != (void *)y); BW_ASSERT((void *)x != (void *)y);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -463,8 +468,8 @@ static inline void bw_src_process_multi(
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
BW_ASSERT((void *)x[i] != (void *)y[j]); BW_ASSERT((void *)x[i] != (void *)y[j]);
#endif #endif
BW_ASSERT(n_in_samples != NULL); BW_ASSERT(n_in_samples != BW_NULL);
BW_ASSERT(n_out_samples != NULL); BW_ASSERT(n_out_samples != BW_NULL);
BW_ASSERT(n_in_samples != n_out_samples); BW_ASSERT(n_in_samples != n_out_samples);
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -475,7 +480,7 @@ static inline void bw_src_process_multi(
static inline char bw_src_coeffs_is_valid( static inline char bw_src_coeffs_is_valid(
const bw_src_coeffs * BW_RESTRICT coeffs) { const bw_src_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_src_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_src_coeffs"))
@ -493,13 +498,13 @@ static inline char bw_src_coeffs_is_valid(
static inline char bw_src_state_is_valid( static inline char bw_src_state_is_valid(
const bw_src_coeffs * BW_RESTRICT coeffs, const bw_src_coeffs * BW_RESTRICT coeffs,
const bw_src_state * BW_RESTRICT state) { const bw_src_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_src_state")) if (state->hash != bw_hash_sdbm("bw_src_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math }}} * requires {{{ bw_common bw_math }}}
* description {{{ * description {{{
* Integer-ratio IIR sample rate converter. * Integer-ratio IIR sample rate converter.
@ -33,6 +33,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added <code>bw_src_int_reset_state_multi()</code> and updated * <li>Added <code>bw_src_int_reset_state_multi()</code> and updated
@ -139,7 +144,7 @@ static inline void bw_src_int_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_src_int_process() * #### bw_src_int_process()
* ```>>> */ * ```>>> */
@ -184,7 +189,7 @@ static inline void bw_src_int_process_multi(
* A given buffer cannot be used both as an input and output buffer. * A given buffer cannot be used both as an input and output buffer.
* *
* `n_out_samples` is filled with the number of generated output samples for * `n_out_samples` is filled with the number of generated output samples for
* each output buffer, if not `NULL`. * each output buffer, if not `BW_NULL`.
* *
* #### bw_src_int_coeffs_is_valid() * #### bw_src_int_coeffs_is_valid()
* ```>>> */ * ```>>> */
@ -208,8 +213,8 @@ static inline char bw_src_int_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_src_int_state`. * than or equal to that of `bw_src_int_state`.
@ -262,7 +267,7 @@ struct bw_src_int_state {
static inline void bw_src_int_init( static inline void bw_src_int_init(
bw_src_int_coeffs * BW_RESTRICT coeffs, bw_src_int_coeffs * BW_RESTRICT coeffs,
int ratio) { int ratio) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT(ratio < -1 || ratio > 1); BW_ASSERT(ratio < -1 || ratio > 1);
coeffs->ratio = ratio; coeffs->ratio = ratio;
@ -288,9 +293,9 @@ static inline float bw_src_int_reset_state(
const bw_src_int_coeffs * BW_RESTRICT coeffs, const bw_src_int_coeffs * BW_RESTRICT coeffs,
bw_src_int_state * BW_RESTRICT state, bw_src_int_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
if (coeffs->ratio < 0) { if (coeffs->ratio < 0) {
@ -327,17 +332,17 @@ static inline void bw_src_int_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_src_int_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_src_int_reset_state(coeffs, state[i], x_0[i]);
else else
@ -345,7 +350,7 @@ static inline void bw_src_int_reset_state_multi(
bw_src_int_reset_state(coeffs, state[i], x_0[i]); bw_src_int_reset_state(coeffs, state[i], x_0[i]);
BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline size_t bw_src_int_process( static inline size_t bw_src_int_process(
@ -354,13 +359,13 @@ static inline size_t bw_src_int_process(
const float * BW_RESTRICT x, const float * BW_RESTRICT x,
float * BW_RESTRICT y, float * BW_RESTRICT y,
size_t n_in_samples) { size_t n_in_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_src_int_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_src_int_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_in_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_in_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT(x != y); BW_ASSERT(x != y);
size_t n = 0; size_t n = 0;
@ -420,16 +425,16 @@ static inline void bw_src_int_process_multi(
size_t n_channels, size_t n_channels,
size_t n_in_samples, size_t n_in_samples,
size_t * BW_RESTRICT n_out_samples) { size_t * BW_RESTRICT n_out_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_src_int_coeffs_is_valid(coeffs));
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
BW_ASSERT((void *)x != (void *)y); BW_ASSERT((void *)x != (void *)y);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
@ -440,7 +445,7 @@ static inline void bw_src_int_process_multi(
BW_ASSERT((void *)x[i] != (void *)y[j]); BW_ASSERT((void *)x[i] != (void *)y[j]);
#endif #endif
if (n_out_samples != NULL) if (n_out_samples != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
n_out_samples[i] = bw_src_int_process(coeffs, state[i], x[i], y[i], n_in_samples); n_out_samples[i] = bw_src_int_process(coeffs, state[i], x[i], y[i], n_in_samples);
else else
@ -452,7 +457,7 @@ static inline void bw_src_int_process_multi(
static inline char bw_src_int_coeffs_is_valid( static inline char bw_src_int_coeffs_is_valid(
const bw_src_int_coeffs * BW_RESTRICT coeffs) { const bw_src_int_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_src_int_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_src_int_coeffs"))
@ -470,13 +475,13 @@ static inline char bw_src_int_coeffs_is_valid(
static inline char bw_src_int_state_is_valid( static inline char bw_src_int_state_is_valid(
const bw_src_int_coeffs * BW_RESTRICT coeffs, const bw_src_int_coeffs * BW_RESTRICT coeffs,
const bw_src_int_state * BW_RESTRICT state) { const bw_src_int_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_src_int_state")) if (state->hash != bw_hash_sdbm("bw_src_int_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole }}} * requires {{{ bw_common bw_math bw_one_pole }}}
* description {{{ * description {{{
* State variable filter (2nd order, 12 dB/oct) model with separated lowpass, * State variable filter (2nd order, 12 dB/oct) model with separated lowpass,
@ -28,6 +28,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Changed model to get positive polarity at the bandpass * <li>Changed model to get positive polarity at the bandpass
@ -174,7 +179,7 @@ static inline void bw_svf_reset_state_multi(
* *
* The corresponding initial lowpass, bandpass, and highpass output values * The corresponding initial lowpass, bandpass, and highpass output values
* are put into the `y_lp_0`, `y_bp_0`, and `y_hp_0` arrays, respectively, if * are put into the `y_lp_0`, `y_bp_0`, and `y_hp_0` arrays, respectively, if
* they are not `NULL`. * they are not `BW_NULL`.
* *
* #### bw_svf_update_coeffs_ctrl() * #### bw_svf_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -217,8 +222,8 @@ static inline void bw_svf_process(
/*! <<<``` /*! <<<```
* Processes the first `n_samples` of the input buffer `x` and fills the * Processes the first `n_samples` of the input buffer `x` and fills the
* first `n_samples` of the output buffers `y_lp` (lowpass), `y_bp` * first `n_samples` of the output buffers `y_lp` (lowpass), `y_bp`
* (bandpass), and `y_hp` (highpass), if they are not `NULL`, while using and * (bandpass), and `y_hp` (highpass), if they are not `BW_NULL`, while using
* updating both `coeffs` and `state` (control and audio rate). * and updating both `coeffs` and `state` (control and audio rate).
* *
* #### bw_svf_process_multi() * #### bw_svf_process_multi()
* ```>>> */ * ```>>> */
@ -238,7 +243,7 @@ static inline void bw_svf_process_multi(
* updating both the common `coeffs` and each of the `n_channels` `state`s * updating both the common `coeffs` and each of the `n_channels` `state`s
* (control and audio rate). * (control and audio rate).
* *
* `y_lp`, `y_bp`, and `y_hp`, or any of their elements may be `NULL`. * `y_lp`, `y_bp`, and `y_hp`, or any of their elements may be `BW_NULL`.
* *
* #### bw_svf_set_cutoff() * #### bw_svf_set_cutoff()
* ```>>> */ * ```>>> */
@ -312,8 +317,8 @@ static inline char bw_svf_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_svf_state`. * than or equal to that of `bw_svf_state`.
@ -390,7 +395,7 @@ struct bw_svf_state {
static inline void bw_svf_init( static inline void bw_svf_init(
bw_svf_coeffs * BW_RESTRICT coeffs) { bw_svf_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_one_pole_init(&coeffs->smooth_coeffs); bw_one_pole_init(&coeffs->smooth_coeffs);
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f); bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.005f);
@ -412,7 +417,7 @@ static inline void bw_svf_init(
static inline void bw_svf_set_sample_rate( static inline void bw_svf_set_sample_rate(
bw_svf_coeffs * BW_RESTRICT coeffs, bw_svf_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -462,7 +467,7 @@ static inline void bw_svf_do_update_coeffs(
static inline void bw_svf_reset_coeffs( static inline void bw_svf_reset_coeffs(
bw_svf_coeffs * BW_RESTRICT coeffs) { bw_svf_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_set_sample_rate);
@ -486,14 +491,14 @@ static inline void bw_svf_reset_state(
float * BW_RESTRICT y_lp_0, float * BW_RESTRICT y_lp_0,
float * BW_RESTRICT y_bp_0, float * BW_RESTRICT y_bp_0,
float * BW_RESTRICT y_hp_0) { float * BW_RESTRICT y_hp_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
BW_ASSERT(y_lp_0 != NULL); BW_ASSERT(y_lp_0 != BW_NULL);
BW_ASSERT(y_bp_0 != NULL); BW_ASSERT(y_bp_0 != BW_NULL);
BW_ASSERT(y_hp_0 != NULL); BW_ASSERT(y_hp_0 != BW_NULL);
BW_ASSERT(y_lp_0 != y_bp_0); BW_ASSERT(y_lp_0 != y_bp_0);
BW_ASSERT(y_lp_0 != y_hp_0); BW_ASSERT(y_lp_0 != y_hp_0);
BW_ASSERT(y_bp_0 != y_hp_0); BW_ASSERT(y_bp_0 != y_hp_0);
@ -526,20 +531,20 @@ static inline void bw_svf_reset_state_multi(
float * y_bp_0, float * y_bp_0,
float * y_hp_0, float * y_hp_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_lp_0 != NULL) { if (y_lp_0 != BW_NULL) {
if (y_bp_0 != NULL) { if (y_bp_0 != BW_NULL) {
if (y_hp_0 != NULL) { if (y_hp_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
bw_svf_reset_state(coeffs, state[i], x_0[i], y_lp_0 + i, y_bp_0 + i, y_hp_0 + i); bw_svf_reset_state(coeffs, state[i], x_0[i], y_lp_0 + i, y_bp_0 + i, y_hp_0 + i);
} else { } else {
@ -549,7 +554,7 @@ static inline void bw_svf_reset_state_multi(
} }
} }
} else { } else {
if (y_hp_0 != NULL) { if (y_hp_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) { for (size_t i = 0; i < n_channels; i++) {
float v_bp; float v_bp;
bw_svf_reset_state(coeffs, state[i], x_0[i], y_lp_0 + i, &v_bp, y_hp_0 + i); bw_svf_reset_state(coeffs, state[i], x_0[i], y_lp_0 + i, &v_bp, y_hp_0 + i);
@ -562,8 +567,8 @@ static inline void bw_svf_reset_state_multi(
} }
} }
} else { } else {
if (y_bp_0 != NULL) { if (y_bp_0 != BW_NULL) {
if (y_hp_0 != NULL) { if (y_hp_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) { for (size_t i = 0; i < n_channels; i++) {
float v_lp; float v_lp;
bw_svf_reset_state(coeffs, state[i], x_0[i], &v_lp, y_bp_0 + i, y_hp_0 + i); bw_svf_reset_state(coeffs, state[i], x_0[i], &v_lp, y_bp_0 + i, y_hp_0 + i);
@ -575,7 +580,7 @@ static inline void bw_svf_reset_state_multi(
} }
} }
} else { } else {
if (y_hp_0 != NULL) { if (y_hp_0 != BW_NULL) {
for (size_t i = 0; i < n_channels; i++) { for (size_t i = 0; i < n_channels; i++) {
float v_lp, v_bp; float v_lp, v_bp;
bw_svf_reset_state(coeffs, state[i], x_0[i], &v_lp, &v_bp, y_hp_0 + i); bw_svf_reset_state(coeffs, state[i], x_0[i], &v_lp, &v_bp, y_hp_0 + i);
@ -591,14 +596,14 @@ static inline void bw_svf_reset_state_multi(
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_lp_0 != NULL ? bw_has_only_finite(y_lp_0, n_channels) : 1); BW_ASSERT_DEEP(y_lp_0 != BW_NULL ? bw_has_only_finite(y_lp_0, n_channels) : 1);
BW_ASSERT_DEEP(y_bp_0 != NULL ? bw_has_only_finite(y_bp_0, n_channels) : 1); BW_ASSERT_DEEP(y_bp_0 != BW_NULL ? bw_has_only_finite(y_bp_0, n_channels) : 1);
BW_ASSERT_DEEP(y_hp_0 != NULL ? bw_has_only_finite(y_hp_0, n_channels) : 1); BW_ASSERT_DEEP(y_hp_0 != BW_NULL ? bw_has_only_finite(y_hp_0, n_channels) : 1);
} }
static inline void bw_svf_update_coeffs_ctrl( static inline void bw_svf_update_coeffs_ctrl(
bw_svf_coeffs * BW_RESTRICT coeffs) { bw_svf_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
@ -607,7 +612,7 @@ static inline void bw_svf_update_coeffs_ctrl(
static inline void bw_svf_update_coeffs_audio( static inline void bw_svf_update_coeffs_audio(
bw_svf_coeffs * BW_RESTRICT coeffs) { bw_svf_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
@ -624,15 +629,15 @@ static inline void bw_svf_process1(
float * BW_RESTRICT y_lp, float * BW_RESTRICT y_lp,
float * BW_RESTRICT y_bp, float * BW_RESTRICT y_bp,
float * BW_RESTRICT y_hp) { float * BW_RESTRICT y_hp) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
BW_ASSERT(y_lp != NULL); BW_ASSERT(y_lp != BW_NULL);
BW_ASSERT(y_bp != NULL); BW_ASSERT(y_bp != BW_NULL);
BW_ASSERT(y_hp != NULL); BW_ASSERT(y_hp != BW_NULL);
BW_ASSERT(y_lp != y_bp); BW_ASSERT(y_lp != y_bp);
BW_ASSERT(y_lp != y_hp); BW_ASSERT(y_lp != y_hp);
BW_ASSERT(y_bp != y_hp); BW_ASSERT(y_bp != y_hp);
@ -664,20 +669,20 @@ static inline void bw_svf_process(
float * y_bp, float * y_bp,
float * y_hp, float * y_hp,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y_lp == NULL || y_bp == NULL || y_lp != y_bp); BW_ASSERT(y_lp == BW_NULL || y_bp == BW_NULL || y_lp != y_bp);
BW_ASSERT(y_lp == NULL || y_hp == NULL || y_lp != y_hp); BW_ASSERT(y_lp == BW_NULL || y_hp == BW_NULL || y_lp != y_hp);
BW_ASSERT(y_bp == NULL || y_hp == NULL || y_bp != y_hp); BW_ASSERT(y_bp == BW_NULL || y_hp == BW_NULL || y_bp != y_hp);
if (y_lp != NULL) { if (y_lp != BW_NULL) {
if (y_bp != NULL) { if (y_bp != BW_NULL) {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
bw_svf_process1(coeffs, state, x[i], y_lp + i, y_bp + i, y_hp + i); bw_svf_process1(coeffs, state, x[i], y_lp + i, y_bp + i, y_hp + i);
@ -690,7 +695,7 @@ static inline void bw_svf_process(
} }
} }
} else { } else {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
float v_bp; float v_bp;
@ -705,8 +710,8 @@ static inline void bw_svf_process(
} }
} }
} else { } else {
if (y_bp != NULL) { if (y_bp != BW_NULL) {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
float v_lp; float v_lp;
@ -720,7 +725,7 @@ static inline void bw_svf_process(
} }
} }
} else { } else {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
float v_lp, v_bp; float v_lp, v_bp;
@ -739,9 +744,9 @@ static inline void bw_svf_process(
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_svf_state_is_valid(coeffs, state));
BW_ASSERT_DEEP(y_lp != NULL ? bw_has_only_finite(y_lp, n_samples) : 1); BW_ASSERT_DEEP(y_lp != BW_NULL ? bw_has_only_finite(y_lp, n_samples) : 1);
BW_ASSERT_DEEP(y_bp != NULL ? bw_has_only_finite(y_bp, n_samples) : 1); BW_ASSERT_DEEP(y_bp != BW_NULL ? bw_has_only_finite(y_bp, n_samples) : 1);
BW_ASSERT_DEEP(y_hp != NULL ? bw_has_only_finite(y_hp, n_samples) : 1); BW_ASSERT_DEEP(y_hp != BW_NULL ? bw_has_only_finite(y_hp, n_samples) : 1);
} }
static inline void bw_svf_process_multi( static inline void bw_svf_process_multi(
@ -753,49 +758,49 @@ static inline void bw_svf_process_multi(
float * const * y_hp, float * const * y_hp,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y_lp == NULL || y_bp == NULL || y_lp != y_bp); BW_ASSERT(y_lp == BW_NULL || y_bp == BW_NULL || y_lp != y_bp);
BW_ASSERT(y_lp == NULL || y_hp == NULL || y_lp != y_hp); BW_ASSERT(y_lp == BW_NULL || y_hp == BW_NULL || y_lp != y_hp);
BW_ASSERT(y_bp == NULL || y_hp == NULL || y_bp != y_hp); BW_ASSERT(y_bp == BW_NULL || y_hp == BW_NULL || y_bp != y_hp);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
if (y_lp != NULL) if (y_lp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y_lp[i] == NULL || y_lp[j] == NULL || y_lp[i] != y_lp[j]); BW_ASSERT(y_lp[i] == BW_NULL || y_lp[j] == BW_NULL || y_lp[i] != y_lp[j]);
if (y_bp != NULL) if (y_bp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y_bp[i] == NULL || y_bp[j] == NULL || y_bp[i] != y_bp[j]); BW_ASSERT(y_bp[i] == BW_NULL || y_bp[j] == BW_NULL || y_bp[i] != y_bp[j]);
if (y_hp != NULL) if (y_hp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(y_hp[i] == NULL || y_hp[j] == NULL || y_hp[i] != y_hp[j]); BW_ASSERT(y_hp[i] == BW_NULL || y_hp[j] == BW_NULL || y_hp[i] != y_hp[j]);
if (y_lp != NULL && y_bp != NULL) if (y_lp != BW_NULL && y_bp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
BW_ASSERT(y_lp[i] == NULL || y_bp[j] == NULL || y_lp[i] != y_bp[j]); BW_ASSERT(y_lp[i] == BW_NULL || y_bp[j] == BW_NULL || y_lp[i] != y_bp[j]);
if (y_lp != NULL && y_hp != NULL) if (y_lp != BW_NULL && y_hp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
BW_ASSERT(y_lp[i] == NULL || y_hp[j] == NULL || y_lp[i] != y_hp[j]); BW_ASSERT(y_lp[i] == BW_NULL || y_hp[j] == BW_NULL || y_lp[i] != y_hp[j]);
if (y_bp != NULL && y_hp != NULL) if (y_bp != BW_NULL && y_hp != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = 0; j < n_channels; j++) for (size_t j = 0; j < n_channels; j++)
BW_ASSERT(y_bp[i] == NULL || y_hp[j] == NULL || y_bp[i] != y_hp[j]); BW_ASSERT(y_bp[i] == BW_NULL || y_hp[j] == BW_NULL || y_bp[i] != y_hp[j]);
#endif #endif
if (y_lp != NULL) { if (y_lp != BW_NULL) {
if (y_bp != NULL) { if (y_bp != BW_NULL) {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -823,7 +828,7 @@ static inline void bw_svf_process_multi(
} }
} }
} else { } else {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -848,8 +853,8 @@ static inline void bw_svf_process_multi(
} }
} }
} else { } else {
if (y_bp != NULL) { if (y_bp != BW_NULL) {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -873,7 +878,7 @@ static inline void bw_svf_process_multi(
} }
} }
} else { } else {
if (y_hp != NULL) { if (y_hp != BW_NULL) {
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
bw_svf_update_coeffs_audio(coeffs); bw_svf_update_coeffs_audio(coeffs);
for (size_t j = 0; j < n_channels; j++) { for (size_t j = 0; j < n_channels; j++) {
@ -902,7 +907,7 @@ static inline void bw_svf_process_multi(
static inline void bw_svf_set_cutoff( static inline void bw_svf_set_cutoff(
bw_svf_coeffs * BW_RESTRICT coeffs, bw_svf_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -917,7 +922,7 @@ static inline void bw_svf_set_cutoff(
static inline void bw_svf_set_Q( static inline void bw_svf_set_Q(
bw_svf_coeffs * BW_RESTRICT coeffs, bw_svf_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -932,7 +937,7 @@ static inline void bw_svf_set_Q(
static inline void bw_svf_set_prewarp_at_cutoff( static inline void bw_svf_set_prewarp_at_cutoff(
bw_svf_coeffs * BW_RESTRICT coeffs, bw_svf_coeffs * BW_RESTRICT coeffs,
char value) { char value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init);
@ -945,7 +950,7 @@ static inline void bw_svf_set_prewarp_at_cutoff(
static inline void bw_svf_set_prewarp_freq( static inline void bw_svf_set_prewarp_freq(
bw_svf_coeffs * BW_RESTRICT coeffs, bw_svf_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_svf_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_svf_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -959,7 +964,7 @@ static inline void bw_svf_set_prewarp_freq(
static inline char bw_svf_coeffs_is_valid( static inline char bw_svf_coeffs_is_valid(
const bw_svf_coeffs * BW_RESTRICT coeffs) { const bw_svf_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_svf_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_svf_coeffs"))
@ -1017,13 +1022,13 @@ static inline char bw_svf_coeffs_is_valid(
static inline char bw_svf_state_is_valid( static inline char bw_svf_state_is_valid(
const bw_svf_coeffs * BW_RESTRICT coeffs, const bw_svf_coeffs * BW_RESTRICT coeffs,
const bw_svf_state * BW_RESTRICT state) { const bw_svf_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_svf_state")) if (state->hash != bw_hash_sdbm("bw_svf_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ * requires {{{
* bw_common bw_math bw_one_pole bw_osc_sin bw_phase_gen bw_ring_mod * bw_common bw_math bw_one_pole bw_osc_sin bw_phase_gen bw_ring_mod
* }}} * }}}
@ -29,6 +29,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input value to * <li>Added initial input value to
@ -142,7 +147,7 @@ static inline void bw_trem_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_trem_update_coeffs_ctrl() * #### bw_trem_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -244,8 +249,8 @@ static inline char bw_trem_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_trem_state`. * than or equal to that of `bw_trem_state`.
@ -301,7 +306,7 @@ struct bw_trem_state {
static inline void bw_trem_init( static inline void bw_trem_init(
bw_trem_coeffs * BW_RESTRICT coeffs) { bw_trem_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_phase_gen_init(&coeffs->phase_gen_coeffs); bw_phase_gen_init(&coeffs->phase_gen_coeffs);
bw_ring_mod_init(&coeffs->ring_mod_coeffs); bw_ring_mod_init(&coeffs->ring_mod_coeffs);
@ -318,7 +323,7 @@ static inline void bw_trem_init(
static inline void bw_trem_set_sample_rate( static inline void bw_trem_set_sample_rate(
bw_trem_coeffs * BW_RESTRICT coeffs, bw_trem_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -335,7 +340,7 @@ static inline void bw_trem_set_sample_rate(
static inline void bw_trem_reset_coeffs( static inline void bw_trem_reset_coeffs(
bw_trem_coeffs * BW_RESTRICT coeffs) { bw_trem_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_set_sample_rate);
@ -354,10 +359,10 @@ static inline float bw_trem_reset_state(
const bw_trem_coeffs * BW_RESTRICT coeffs, const bw_trem_coeffs * BW_RESTRICT coeffs,
bw_trem_state * BW_RESTRICT state, bw_trem_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float p, pi; float p, pi;
@ -383,18 +388,18 @@ static inline void bw_trem_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_trem_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_trem_reset_state(coeffs, state[i], x_0[i]);
else else
@ -403,12 +408,12 @@ static inline void bw_trem_reset_state_multi(
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_trem_update_coeffs_ctrl( static inline void bw_trem_update_coeffs_ctrl(
bw_trem_coeffs * BW_RESTRICT coeffs) { bw_trem_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
@ -421,7 +426,7 @@ static inline void bw_trem_update_coeffs_ctrl(
static inline void bw_trem_update_coeffs_audio( static inline void bw_trem_update_coeffs_audio(
bw_trem_coeffs * BW_RESTRICT coeffs) { bw_trem_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
@ -436,10 +441,10 @@ static inline float bw_trem_process1(
const bw_trem_coeffs * BW_RESTRICT coeffs, const bw_trem_coeffs * BW_RESTRICT coeffs,
bw_trem_state * BW_RESTRICT state, bw_trem_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_trem_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_trem_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -462,14 +467,14 @@ static inline void bw_trem_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_trem_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_trem_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_trem_update_coeffs_ctrl(coeffs); bw_trem_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -490,17 +495,17 @@ static inline void bw_trem_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -521,7 +526,7 @@ static inline void bw_trem_process_multi(
static inline void bw_trem_set_rate( static inline void bw_trem_set_rate(
bw_trem_coeffs * BW_RESTRICT coeffs, bw_trem_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -535,7 +540,7 @@ static inline void bw_trem_set_rate(
static inline void bw_trem_set_amount( static inline void bw_trem_set_amount(
bw_trem_coeffs * BW_RESTRICT coeffs, bw_trem_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_trem_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_trem_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -549,7 +554,7 @@ static inline void bw_trem_set_amount(
static inline char bw_trem_coeffs_is_valid( static inline char bw_trem_coeffs_is_valid(
const bw_trem_coeffs * BW_RESTRICT coeffs) { const bw_trem_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_trem_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_trem_coeffs"))
@ -564,17 +569,17 @@ static inline char bw_trem_coeffs_is_valid(
static inline char bw_trem_state_is_valid( static inline char bw_trem_state_is_valid(
const bw_trem_coeffs * BW_RESTRICT coeffs, const bw_trem_coeffs * BW_RESTRICT coeffs,
const bw_trem_state * BW_RESTRICT state) { const bw_trem_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_trem_state")) if (state->hash != bw_hash_sdbm("bw_trem_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_phase_gen_state_is_valid(coeffs ? &coeffs->phase_gen_coeffs : NULL, &state->phase_gen_state); return bw_phase_gen_state_is_valid(coeffs ? &coeffs->phase_gen_coeffs : BW_NULL, &state->phase_gen_state);
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2023 Orastron Srl unipersonale * Copyright (C) 2023, 2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,13 +20,18 @@
/*! /*!
* module_type {{{ utility }}} * module_type {{{ utility }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_note_queue }}} * requires {{{ bw_common bw_note_queue }}}
* description {{{ * description {{{
* Basic voice allocator with low/high note priority. * Basic voice allocator with low/high note priority.
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Specified that velocity can be negative in * <li>Specified that velocity can be negative in
@ -149,15 +154,15 @@ void bw_voice_alloc(
bw_note_queue * BW_RESTRICT queue, bw_note_queue * BW_RESTRICT queue,
void * BW_RESTRICT const * BW_RESTRICT voices, void * BW_RESTRICT const * BW_RESTRICT voices,
size_t n_voices) { size_t n_voices) {
BW_ASSERT(opts != NULL); BW_ASSERT(opts != BW_NULL);
BW_ASSERT(opts->priority == bw_voice_alloc_priority_low || opts->priority == bw_voice_alloc_priority_high); BW_ASSERT(opts->priority == bw_voice_alloc_priority_low || opts->priority == bw_voice_alloc_priority_high);
BW_ASSERT(n_voices == 0 || opts->note_on != NULL); BW_ASSERT(n_voices == 0 || opts->note_on != BW_NULL);
BW_ASSERT(n_voices == 0 || opts->note_off != NULL); BW_ASSERT(n_voices == 0 || opts->note_off != BW_NULL);
BW_ASSERT(n_voices == 0 || opts->get_note != NULL); BW_ASSERT(n_voices == 0 || opts->get_note != BW_NULL);
BW_ASSERT(n_voices == 0 || opts->is_free != NULL); BW_ASSERT(n_voices == 0 || opts->is_free != BW_NULL);
BW_ASSERT(queue != NULL); BW_ASSERT(queue != BW_NULL);
BW_ASSERT_DEEP(bw_note_queue_is_valid(queue)); BW_ASSERT_DEEP(bw_note_queue_is_valid(queue));
BW_ASSERT(n_voices == 0 || voices != NULL); BW_ASSERT(n_voices == 0 || voices != BW_NULL);
for (unsigned char i = 0; i < queue->n_events; i++) { for (unsigned char i = 0; i < queue->n_events; i++) {
bw_note_queue_event *ev = queue->events + i; bw_note_queue_event *ev = queue->events + i;

View File

@ -1,7 +1,7 @@
/* /*
* Brickworks * Brickworks
* *
* Copyright (C) 2022, 2023 Orastron Srl unipersonale * Copyright (C) 2022-2024 Orastron Srl unipersonale
* *
* Brickworks is free software: you can redistribute it and/or modify * Brickworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
/*! /*!
* module_type {{{ dsp }}} * module_type {{{ dsp }}}
* version {{{ 1.0.0 }}} * version {{{ 1.0.1 }}}
* requires {{{ bw_common bw_math bw_one_pole bw_svf }}} * requires {{{ bw_common bw_math bw_one_pole bw_svf }}}
* description {{{ * description {{{
* Wah effect. * Wah effect.
@ -29,6 +29,11 @@
* }}} * }}}
* changelog {{{ * changelog {{{
* <ul> * <ul>
* <li>Version <strong>1.0.1</strong>:
* <ul>
* <li>Now using <code>BW_NULL</code>.</li>
* </ul>
* </li>
* <li>Version <strong>1.0.0</strong>: * <li>Version <strong>1.0.0</strong>:
* <ul> * <ul>
* <li>Added initial input value to * <li>Added initial input value to
@ -156,7 +161,7 @@ static inline void bw_wah_reset_state_multi(
* array. * array.
* *
* The corresponding initial output values are written into the `y_0` array, * The corresponding initial output values are written into the `y_0` array,
* if not `NULL`. * if not `BW_NULL`.
* *
* #### bw_wah_update_coeffs_ctrl() * #### bw_wah_update_coeffs_ctrl()
* ```>>> */ * ```>>> */
@ -244,8 +249,8 @@ static inline char bw_wah_state_is_valid(
* seems to be the case and `0` if it is certainly not. False positives are * seems to be the case and `0` if it is certainly not. False positives are
* possible, false negatives are not. * possible, false negatives are not.
* *
* If `coeffs` is not `NULL` extra cross-checks might be performed (`state` * If `coeffs` is not `BW_NULL` extra cross-checks might be performed
* is supposed to be associated to `coeffs`). * (`state` is supposed to be associated to `coeffs`).
* *
* `state` must at least point to a readable memory block of size greater * `state` must at least point to a readable memory block of size greater
* than or equal to that of `bw_wah_state`. * than or equal to that of `bw_wah_state`.
@ -298,7 +303,7 @@ struct bw_wah_state {
static inline void bw_wah_init( static inline void bw_wah_init(
bw_wah_coeffs * BW_RESTRICT coeffs) { bw_wah_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
bw_svf_init(&coeffs->svf_coeffs); bw_svf_init(&coeffs->svf_coeffs);
bw_svf_set_cutoff(&coeffs->svf_coeffs, 600.f); bw_svf_set_cutoff(&coeffs->svf_coeffs, 600.f);
@ -316,7 +321,7 @@ static inline void bw_wah_init(
static inline void bw_wah_set_sample_rate( static inline void bw_wah_set_sample_rate(
bw_wah_coeffs * BW_RESTRICT coeffs, bw_wah_coeffs * BW_RESTRICT coeffs,
float sample_rate) { float sample_rate) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_init);
BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f); BW_ASSERT(bw_is_finite(sample_rate) && sample_rate > 0.f);
@ -332,7 +337,7 @@ static inline void bw_wah_set_sample_rate(
static inline void bw_wah_reset_coeffs( static inline void bw_wah_reset_coeffs(
bw_wah_coeffs * BW_RESTRICT coeffs) { bw_wah_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_set_sample_rate); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_set_sample_rate);
@ -350,10 +355,10 @@ static inline float bw_wah_reset_state(
const bw_wah_coeffs * BW_RESTRICT coeffs, const bw_wah_coeffs * BW_RESTRICT coeffs,
bw_wah_state * BW_RESTRICT state, bw_wah_state * BW_RESTRICT state,
float x_0) { float x_0) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT(bw_is_finite(x_0)); BW_ASSERT(bw_is_finite(x_0));
float lp, bp, hp; float lp, bp, hp;
@ -377,18 +382,18 @@ static inline void bw_wah_reset_state_multi(
const float * x_0, const float * x_0,
float * y_0, float * y_0,
size_t n_channels) { size_t n_channels) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x_0 != NULL); BW_ASSERT(x_0 != BW_NULL);
if (y_0 != NULL) if (y_0 != BW_NULL)
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
y_0[i] = bw_wah_reset_state(coeffs, state[i], x_0[i]); y_0[i] = bw_wah_reset_state(coeffs, state[i], x_0[i]);
else else
@ -397,12 +402,12 @@ static inline void bw_wah_reset_state_multi(
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT_DEEP(y_0 != NULL ? bw_has_only_finite(y_0, n_channels) : 1); BW_ASSERT_DEEP(y_0 != BW_NULL ? bw_has_only_finite(y_0, n_channels) : 1);
} }
static inline void bw_wah_update_coeffs_ctrl( static inline void bw_wah_update_coeffs_ctrl(
bw_wah_coeffs * BW_RESTRICT coeffs) { bw_wah_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
@ -414,7 +419,7 @@ static inline void bw_wah_update_coeffs_ctrl(
static inline void bw_wah_update_coeffs_audio( static inline void bw_wah_update_coeffs_audio(
bw_wah_coeffs * BW_RESTRICT coeffs) { bw_wah_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
@ -428,10 +433,10 @@ static inline float bw_wah_process1(
const bw_wah_coeffs * BW_RESTRICT coeffs, const bw_wah_coeffs * BW_RESTRICT coeffs,
bw_wah_state * BW_RESTRICT state, bw_wah_state * BW_RESTRICT state,
float x) { float x) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_wah_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_wah_state_is_valid(coeffs, state));
BW_ASSERT(bw_is_finite(x)); BW_ASSERT(bw_is_finite(x));
@ -452,14 +457,14 @@ static inline void bw_wah_process(
const float * x, const float * x,
float * y, float * y,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
BW_ASSERT_DEEP(bw_wah_state_is_valid(coeffs, state)); BW_ASSERT_DEEP(bw_wah_state_is_valid(coeffs, state));
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples)); BW_ASSERT_DEEP(bw_has_only_finite(x, n_samples));
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
bw_wah_update_coeffs_ctrl(coeffs); bw_wah_update_coeffs_ctrl(coeffs);
for (size_t i = 0; i < n_samples; i++) { for (size_t i = 0; i < n_samples; i++) {
@ -480,17 +485,17 @@ static inline void bw_wah_process_multi(
float * const * y, float * const * y,
size_t n_channels, size_t n_channels,
size_t n_samples) { size_t n_samples) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_reset_coeffs);
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
BW_ASSERT(state[i] != state[j]); BW_ASSERT(state[i] != state[j]);
#endif #endif
BW_ASSERT(x != NULL); BW_ASSERT(x != BW_NULL);
BW_ASSERT(y != NULL); BW_ASSERT(y != BW_NULL);
#ifndef BW_NO_DEBUG #ifndef BW_NO_DEBUG
for (size_t i = 0; i < n_channels; i++) for (size_t i = 0; i < n_channels; i++)
for (size_t j = i + 1; j < n_channels; j++) for (size_t j = i + 1; j < n_channels; j++)
@ -511,7 +516,7 @@ static inline void bw_wah_process_multi(
static inline void bw_wah_set_wah( static inline void bw_wah_set_wah(
bw_wah_coeffs * BW_RESTRICT coeffs, bw_wah_coeffs * BW_RESTRICT coeffs,
float value) { float value) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs)); BW_ASSERT_DEEP(bw_wah_coeffs_is_valid(coeffs));
BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_init); BW_ASSERT_DEEP(coeffs->state >= bw_wah_coeffs_state_init);
BW_ASSERT(bw_is_finite(value)); BW_ASSERT(bw_is_finite(value));
@ -525,7 +530,7 @@ static inline void bw_wah_set_wah(
static inline char bw_wah_coeffs_is_valid( static inline char bw_wah_coeffs_is_valid(
const bw_wah_coeffs * BW_RESTRICT coeffs) { const bw_wah_coeffs * BW_RESTRICT coeffs) {
BW_ASSERT(coeffs != NULL); BW_ASSERT(coeffs != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (coeffs->hash != bw_hash_sdbm("bw_wah_coeffs")) if (coeffs->hash != bw_hash_sdbm("bw_wah_coeffs"))
@ -540,17 +545,17 @@ static inline char bw_wah_coeffs_is_valid(
static inline char bw_wah_state_is_valid( static inline char bw_wah_state_is_valid(
const bw_wah_coeffs * BW_RESTRICT coeffs, const bw_wah_coeffs * BW_RESTRICT coeffs,
const bw_wah_state * BW_RESTRICT state) { const bw_wah_state * BW_RESTRICT state) {
BW_ASSERT(state != NULL); BW_ASSERT(state != BW_NULL);
#ifdef BW_DEBUG_DEEP #ifdef BW_DEBUG_DEEP
if (state->hash != bw_hash_sdbm("bw_wah_state")) if (state->hash != bw_hash_sdbm("bw_wah_state"))
return 0; return 0;
if (coeffs != NULL && coeffs->reset_id != state->coeffs_reset_id) if (coeffs != BW_NULL && coeffs->reset_id != state->coeffs_reset_id)
return 0; return 0;
#endif #endif
return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : NULL, &state->svf_state); return bw_svf_state_is_valid(coeffs ? &coeffs->svf_coeffs : BW_NULL, &state->svf_state);
} }
#ifdef __cplusplus #ifdef __cplusplus