moving towards lower level inline API for all modules
This commit is contained in:
parent
eb16e3d1a0
commit
98990c7437
1
TODO
1
TODO
@ -8,6 +8,7 @@ code:
|
|||||||
* API for buffer fill, scale, offset, zero, copy...?
|
* API for buffer fill, scale, offset, zero, copy...?
|
||||||
* web examples construction/destruction
|
* web examples construction/destruction
|
||||||
* web effect multichannel in?
|
* web effect multichannel in?
|
||||||
|
* check const restrict etc.
|
||||||
|
|
||||||
build system:
|
build system:
|
||||||
* make makefiles handle paths with spaces etc
|
* make makefiles handle paths with spaces etc
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
* }}}
|
* }}}
|
||||||
* changelog {{{
|
* changelog {{{
|
||||||
* <ul>
|
* <ul>
|
||||||
|
* <li>Version <strong>0.2.0</strong>:
|
||||||
|
* <ul>
|
||||||
|
* <li>Removed BW_MALLOC, BW_REALLOC, and BW_FREE.</li>
|
||||||
|
* </ul>
|
||||||
|
* </li>
|
||||||
* <li>Version <strong>0.1.0</strong>:
|
* <li>Version <strong>0.1.0</strong>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>First release.</li>
|
* <li>First release.</li>
|
||||||
@ -77,24 +82,6 @@
|
|||||||
# include <math.h>
|
# include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### BW_MALLOC, BW_REALLOC, BW_FREE
|
|
||||||
* If any of these is not defined, then `stdlib.h` is `#include`d and the
|
|
||||||
* missing ones are defined as `malloc`, `realloc`, or `free`, respectively.
|
|
||||||
* >>> */
|
|
||||||
#if !defined(BW_MALLOC) || !defined(BW_REALLOC) || !defined(BW_FREE)
|
|
||||||
# include <stdlib.h>
|
|
||||||
# ifndef BW_MALLOC
|
|
||||||
# define BW_MALLOC malloc
|
|
||||||
# endif
|
|
||||||
# ifndef BW_REALLOC
|
|
||||||
# define BW_REALLOC realloc
|
|
||||||
# endif
|
|
||||||
# ifndef BW_FREE
|
|
||||||
# define BW_FREE free
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! ... }}} */
|
/*! ... }}} */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,7 +120,8 @@ bw_one_pole *bw_env_follow_get_one_pole(bw_env_follow *instance);
|
|||||||
* access its members directly. */
|
* access its members directly. */
|
||||||
struct _bw_env_follow {
|
struct _bw_env_follow {
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_one_pole one_pole;
|
bw_one_pole_coeffs one_pole_coeffs;
|
||||||
|
bw_one_pole_state one_pole_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.2.0 }}}
|
* version {{{ 0.2.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_inline_one_pole bw_math }}}
|
* requires {{{ bw_config bw_common bw_one_pole bw_math }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Linear ADSR envelope generator.
|
* Linear ADSR envelope generator.
|
||||||
*
|
*
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* Brickworks
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 Orastron Srl unipersonale
|
|
||||||
*
|
|
||||||
* Brickworks is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3 of the License.
|
|
||||||
*
|
|
||||||
* Brickworks is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
*
|
|
||||||
* File author: Stefano D'Angelo
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* module_type {{{ utility }}}
|
|
||||||
* version {{{ 0.1.0 }}}
|
|
||||||
* requires {{{ bw_config bw_common bw_math }}}
|
|
||||||
* description {{{
|
|
||||||
* Inline one-pole (6 dB/oct) lowpass filter with unitary DC gain and sticky
|
|
||||||
* target-reach threshold.
|
|
||||||
*
|
|
||||||
* This is similar to [bw_one_pole](bw_one_pole) but can be used to process
|
|
||||||
* on a sample-by-sample basis without buffers.
|
|
||||||
* }}}
|
|
||||||
* changelog {{{
|
|
||||||
* <ul>
|
|
||||||
* <li>Version <strong>0.1.0</strong>:
|
|
||||||
* <ul>
|
|
||||||
* <li>First release.</li>
|
|
||||||
* </ul>
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
* }}}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BW_INLINE_ONE_POLE_H
|
|
||||||
#define _BW_INLINE_ONE_POLE_H
|
|
||||||
|
|
||||||
#include <bw_math.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*! api {{{
|
|
||||||
* #### bw_inline_one_pole_get_mA1()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_inline_one_pole_get_mA1(float sample_rate, float tau);
|
|
||||||
/*! <<<```
|
|
||||||
* Computes the `mA1` coefficient requested by other functions in this
|
|
||||||
* module, corresponding to the given `sample_rate` (Hz) and time constant
|
|
||||||
* `tau` (s) values.
|
|
||||||
* >>> */
|
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_inline_one_pole()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_inline_one_pole(float x, float y_z1, float mA1);
|
|
||||||
/*! <<<```
|
|
||||||
* Processes one input sample `x`, using the previous output value `y_z1` and
|
|
||||||
* the `mA1` coefficient, and returns the corresponding output sample.
|
|
||||||
*
|
|
||||||
* This function does not feature sticky target-reach threshold.
|
|
||||||
* >>> */
|
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_inline_one_pole_sticky_abs()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_inline_one_pole_sticky_abs(float x, float y_z1, float mA1, float thresh_sq);
|
|
||||||
/*! <<<```
|
|
||||||
* Like `bw_inline_one_pole()` but when the absolute difference between the
|
|
||||||
* output and the input (|*value to be returned* - `x`|) would be smaller
|
|
||||||
* than the square root of `thresh_sq`, it just returns `x`.
|
|
||||||
* >>> */
|
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_inline_one_pole_sticky_rel()
|
|
||||||
* ```>>> */
|
|
||||||
static inline float bw_inline_one_pole_sticky_rel(float x, float y_z1, float mA1, float thresh_sq);
|
|
||||||
/*! <<<```
|
|
||||||
* Like `bw_inline_one_pole()` but when the relative difference of the output
|
|
||||||
* with respect to the input (|*value to be returned* - `x`| / |`x`|) would
|
|
||||||
* be smaller than the square root of `thresh_sq`, it just returns `x`.
|
|
||||||
* }}} */
|
|
||||||
|
|
||||||
/* Implementation */
|
|
||||||
|
|
||||||
static inline float bw_inline_one_pole_get_mA1(float sample_rate, float tau) {
|
|
||||||
return bw_expf_3(-bw_rcpf_2(sample_rate * tau));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float bw_inline_one_pole(float x, float y_z1, float mA1) {
|
|
||||||
return x + mA1 * (y_z1 - x);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float bw_inline_one_pole_sticky_abs(float x, float y_z1, float mA1, float thresh_sq) {
|
|
||||||
float y = bw_inline_one_pole(x, y_z1, mA1);
|
|
||||||
const float d = x - y;
|
|
||||||
return d * d < thresh_sq ? x : y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float bw_inline_one_pole_sticky_rel(float x, float y_z1, float mA1, float thresh_sq) {
|
|
||||||
float y = bw_inline_one_pole(x, y_z1, mA1);
|
|
||||||
const float d = x - y;
|
|
||||||
return d * d < thresh_sq * (x * x) ? x : y;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -363,7 +363,10 @@ static inline float bw_sqrtf_2(float x);
|
|||||||
* Relative error < 0.0007%.
|
* Relative error < 0.0007%.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
/* Implementation */
|
/*** Implementation ***/
|
||||||
|
|
||||||
|
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||||
|
* change at any time in future versions. Please, do not use it directly. */
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
float f;
|
float f;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>Version <strong>0.2.0</strong>:
|
* <li>Version <strong>0.2.0</strong>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Refactored API to avoid dynamic memory allocation.</li>
|
* <li>Refactored API.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </li>
|
* </li>
|
||||||
* <li>Version <strong>0.1.0</strong>:
|
* <li>Version <strong>0.1.0</strong>:
|
||||||
@ -49,14 +49,18 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! api {{{
|
/*! api {{{
|
||||||
* #### bw_one_pole
|
* #### bw_one_pole_coeffs
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
typedef struct _bw_one_pole bw_one_pole;
|
typedef struct _bw_one_pole_coeffs bw_one_pole_coeffs;
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Instance object.
|
* Coefficients.
|
||||||
|
*
|
||||||
|
* ### bw_one_pole_state
|
||||||
* >>> */
|
* >>> */
|
||||||
|
typedef struct _bw_one_pole_state bw_one_pole_state;
|
||||||
/*! ...
|
/*! <<<```
|
||||||
|
* State.
|
||||||
|
*
|
||||||
* #### bw_one_pole_sticky_mode
|
* #### bw_one_pole_sticky_mode
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -68,36 +72,42 @@ typedef enum {
|
|||||||
* * `bw_one_pole_sticky_mode_abs`: absolute difference (|`out` - `in`|);
|
* * `bw_one_pole_sticky_mode_abs`: absolute difference (|`out` - `in`|);
|
||||||
* * `bw_one_pole_sticky_mode_rel`: relative difference with respect to
|
* * `bw_one_pole_sticky_mode_rel`: relative difference with respect to
|
||||||
* input (|`out` - `in`| / |`in`|);
|
* input (|`out` - `in`| / |`in`|);
|
||||||
* >>> */
|
*
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_one_pole_init()
|
* #### bw_one_pole_init()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_init(bw_one_pole *instance);
|
static inline void bw_one_pole_init(bw_one_pole_coeffs *restrict coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Initializes the `instance` object.
|
* Initializes `coeffs`.
|
||||||
* >>> */
|
*
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_one_pole_set_sample_rate()
|
* #### bw_one_pole_set_sample_rate()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_sample_rate(bw_one_pole *instance, float sample_rate);
|
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *restrict coeffs, float sample_rate);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the `sample_rate` (Hz) value for the given `instance`.
|
* Sets the `sample_rate` (Hz) value for the given `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_one_pole_reset_state()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state);
|
||||||
|
/*! <<<```
|
||||||
|
* Resets the given `state` to the initial state using the given `coeffs`.
|
||||||
* >>> */
|
* >>> */
|
||||||
|
|
||||||
/*! ...
|
static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *restrict coeffs);
|
||||||
* #### bw_one_pole_reset()
|
|
||||||
* ```>>> */
|
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *restrict coeffs);
|
||||||
void bw_one_pole_reset(bw_one_pole *instance);
|
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *restrict coeffs);
|
||||||
/*! <<<```
|
|
||||||
* Resets the given `instance` to its initial state.
|
static inline float bw_one_pole_process1(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
* >>> */
|
static inline float bw_one_pole_process1_sticky_abs(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
|
static inline float bw_one_pole_process1_sticky_rel(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
|
static inline float bw_one_pole_process1_asym(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
|
static inline float bw_one_pole_process1_asym_sticky_abs(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
|
static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x);
|
||||||
|
|
||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_process()
|
* #### bw_one_pole_process()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_process(bw_one_pole *instance, const float* x, float* y, int n_samples);
|
static inline void bw_one_pole_process(bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, const float *x, float *y, int n_samples);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Lets the given `instance` process `n_samples` samples from the input
|
* Lets the given `instance` process `n_samples` samples from the input
|
||||||
* buffer `x` and fills the corresponding `n_samples` samples in the output
|
* buffer `x` and fills the corresponding `n_samples` samples in the output
|
||||||
@ -107,7 +117,7 @@ void bw_one_pole_process(bw_one_pole *instance, const float* x, float* y, int n_
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_init_val()
|
* #### bw_one_pole_set_init_val()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_init_val(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the initial/quiescent `value` for the given `instance`.
|
* Sets the initial/quiescent `value` for the given `instance`.
|
||||||
*
|
*
|
||||||
@ -121,7 +131,7 @@ void bw_one_pole_set_init_val(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff()
|
* #### bw_one_pole_set_cutoff()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_cutoff(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets both the upgoing (attack) and downgoing (decay) cutoff frequency to
|
* Sets both the upgoing (attack) and downgoing (decay) cutoff frequency to
|
||||||
* the given `value` (Hz) for the given `instance`.
|
* the given `value` (Hz) for the given `instance`.
|
||||||
@ -137,7 +147,7 @@ void bw_one_pole_set_cutoff(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff_up()
|
* #### bw_one_pole_set_cutoff_up()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_cutoff_up(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the upgoing (attack) cutoff frequency to the given `value` (Hz) for
|
* Sets the upgoing (attack) cutoff frequency to the given `value` (Hz) for
|
||||||
* the given `instance`.
|
* the given `instance`.
|
||||||
@ -151,7 +161,7 @@ void bw_one_pole_set_cutoff_up(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff_down()
|
* #### bw_one_pole_set_cutoff_down()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_cutoff_down(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the downgoing (attack) cutoff frequency to the given `value` (Hz)
|
* Sets the downgoing (attack) cutoff frequency to the given `value` (Hz)
|
||||||
* for the given `instance`.
|
* for the given `instance`.
|
||||||
@ -165,7 +175,7 @@ void bw_one_pole_set_cutoff_down(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau()
|
* #### bw_one_pole_set_tau()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_tau(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets both the upgoing (attack) and downgoing (decay) time constant to the
|
* Sets both the upgoing (attack) and downgoing (decay) time constant to the
|
||||||
* given `value` (s) for the given `instance`.
|
* given `value` (s) for the given `instance`.
|
||||||
@ -181,7 +191,7 @@ void bw_one_pole_set_tau(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau_up()
|
* #### bw_one_pole_set_tau_up()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_tau_up(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the upgoing (attack) time constant to the given `value` (s) for the
|
* Sets the upgoing (attack) time constant to the given `value` (s) for the
|
||||||
* given `instance`.
|
* given `instance`.
|
||||||
@ -195,7 +205,7 @@ void bw_one_pole_set_tau_up(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau_down()
|
* #### bw_one_pole_set_tau_down()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_tau_down(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the downgoing (decay) time constant to the given `value` (s) for the
|
* Sets the downgoing (decay) time constant to the given `value` (s) for the
|
||||||
* given `instance`.
|
* given `instance`.
|
||||||
@ -209,7 +219,7 @@ void bw_one_pole_set_tau_down(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_sticky_thresh()
|
* #### bw_one_pole_set_sticky_thresh()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_sticky_thresh(bw_one_pole *instance, float value);
|
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *restrict coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the target-reach threshold specified by `value` for the given
|
* Sets the target-reach threshold specified by `value` for the given
|
||||||
* `instance`.
|
* `instance`.
|
||||||
@ -225,15 +235,17 @@ void bw_one_pole_set_sticky_thresh(bw_one_pole *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_sticky_mode()
|
* #### bw_one_pole_set_sticky_mode()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_one_pole_set_sticky_mode(bw_one_pole *instance, bw_one_pole_sticky_mode value);
|
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *restrict coeffs, bw_one_pole_sticky_mode value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the current distance metric for sticky behavior.
|
* Sets the current distance metric for sticky behavior.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
/* WARNING: the internal definition of this struct is not part of the public
|
/*** Implementation ***/
|
||||||
* API. Its content may change at any time in future versions. Please, do not
|
|
||||||
* access its members directly. */
|
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||||
struct _bw_one_pole {
|
* change at any time in future versions. Please, do not use it directly. */
|
||||||
|
|
||||||
|
struct _bw_one_pole_coeffs {
|
||||||
// Coefficients
|
// Coefficients
|
||||||
float Ttm2pi;
|
float Ttm2pi;
|
||||||
|
|
||||||
@ -248,13 +260,183 @@ struct _bw_one_pole {
|
|||||||
float sticky_thresh;
|
float sticky_thresh;
|
||||||
bw_one_pole_sticky_mode sticky_mode;
|
bw_one_pole_sticky_mode sticky_mode;
|
||||||
int param_changed;
|
int param_changed;
|
||||||
|
|
||||||
// State
|
|
||||||
char first_run;
|
|
||||||
float x_z1;
|
|
||||||
float y_z1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _bw_one_pole_state {
|
||||||
|
float y_z1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define _BW_ONE_POLE_PARAM_CUTOFF_UP 1
|
||||||
|
#define _BW_ONE_POLE_PARAM_CUTOFF_DOWN (1<<1)
|
||||||
|
#define _BW_ONE_POLE_PARAM_STICKY_THRESH (1<<2)
|
||||||
|
|
||||||
|
#include <bw_math.h>
|
||||||
|
|
||||||
|
static inline void bw_one_pole_init(bw_one_pole_coeffs *restrict coeffs) {
|
||||||
|
coeffs->init_val = 0.f;
|
||||||
|
coeffs->cutoff_up = INFINITY;
|
||||||
|
coeffs->cutoff_down = INFINITY;
|
||||||
|
coeffs->sticky_thresh = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *restrict coeffs, float sample_rate) {
|
||||||
|
coeffs->Ttm2pi = -6.283185307179586f / sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *restrict coeffs) {
|
||||||
|
coeffs->param_changed = ~0;
|
||||||
|
bw_one_pole_update_coeffs_ctrl(coeffs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state) {
|
||||||
|
state->y_z1 = coeffs->init_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *restrict coeffs) {
|
||||||
|
if (coeffs->param_changed) {
|
||||||
|
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_CUTOFF_UP)
|
||||||
|
coeffs->mA1u = bw_expf_3(coeffs->Ttm2pi * coeffs->cutoff_up);
|
||||||
|
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_CUTOFF_DOWN)
|
||||||
|
coeffs->mA1d = bw_expf_3(coeffs->Ttm2pi * coeffs->cutoff_down);
|
||||||
|
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_STICKY_THRESH)
|
||||||
|
coeffs->st2 = coeffs->sticky_thresh * coeffs->sticky_thresh;
|
||||||
|
coeffs->param_changed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *restrict coeffs) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
const float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1_sticky_abs(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
|
const float d = y - x;
|
||||||
|
if (d * d <= coeffs->st2)
|
||||||
|
y = x;
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1_sticky_rel(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
|
const float d = y - x;
|
||||||
|
if (d * d <= coeffs->st2 * x * x)
|
||||||
|
y = x;
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1_asym(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
const float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1_asym_sticky_abs(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
|
const float d = y - x;
|
||||||
|
if (d * d <= coeffs->st2)
|
||||||
|
y = x;
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, float x) {
|
||||||
|
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
|
const float d = y - x;
|
||||||
|
if (d * d <= coeffs->st2 * x * x)
|
||||||
|
y = x;
|
||||||
|
state->y_z1 = y;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_process(bw_one_pole_coeffs *restrict coeffs, bw_one_pole_state *restrict state, const float *x, float *y, int n_samples) {
|
||||||
|
bw_one_pole_update_coeffs_ctrl(coeffs);
|
||||||
|
|
||||||
|
if (coeffs->mA1u != coeffs->mA1d) {
|
||||||
|
if (coeffs->st2 != 0.f) {
|
||||||
|
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1_asym_sticky_abs(coeffs, state, x[i]);
|
||||||
|
else
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1_asym_sticky_rel(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1_asym(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (coeffs->st2 != 0.f) {
|
||||||
|
if (coeffs->sticky_mode == bw_one_pole_sticky_mode_abs)
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1_sticky_abs(coeffs, state, x[i]);
|
||||||
|
else
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1_sticky_rel(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < n_samples; i++)
|
||||||
|
y[i] = bw_one_pole_process1(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
coeffs->init_val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
bw_one_pole_set_cutoff_up(coeffs, value);
|
||||||
|
bw_one_pole_set_cutoff_down(coeffs, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
if (coeffs->cutoff_up != value) {
|
||||||
|
coeffs->cutoff_up = value;
|
||||||
|
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_UP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
if (coeffs->cutoff_down != value) {
|
||||||
|
coeffs->cutoff_down = value;
|
||||||
|
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
bw_one_pole_set_tau_up(coeffs, value);
|
||||||
|
bw_one_pole_set_tau_down(coeffs, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
bw_one_pole_set_cutoff_up(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
||||||
|
// tau < 1 ns is instantaneous for any practical purpose
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
bw_one_pole_set_cutoff_down(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
||||||
|
// as before
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *restrict coeffs, float value) {
|
||||||
|
if (coeffs->sticky_thresh != value) {
|
||||||
|
coeffs->sticky_thresh = value;
|
||||||
|
coeffs->param_changed |= _BW_ONE_POLE_PARAM_STICKY_THRESH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *restrict coeffs, bw_one_pole_sticky_mode value) {
|
||||||
|
coeffs->sticky_mode = value;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.2.0 }}}
|
* version {{{ 0.2.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_inline_one_pole bw_math }}}
|
* requires {{{ bw_config bw_common bw_one_pole bw_math }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Pulse oscillator waveshaper with variable pulse width (actually, duty
|
* Pulse oscillator waveshaper with variable pulse width (actually, duty
|
||||||
* cycle) and PolyBLEP antialiasing.
|
* cycle) and PolyBLEP antialiasing.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.2.0 }}}
|
* version {{{ 0.2.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_inline_one_pole bw_math }}}
|
* requires {{{ bw_config bw_common bw_one_pole bw_math }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Triangle oscillator waveshaper with variable slope (increasing time over
|
* Triangle oscillator waveshaper with variable slope (increasing time over
|
||||||
* period) and PolyBLEP antialiasing.
|
* period) and PolyBLEP antialiasing.
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.2.0 }}}
|
* version {{{ 0.2.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_inline_one_pole bw_math }}}
|
* requires {{{ bw_config bw_common bw_one_pole bw_math }}}
|
||||||
* 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,
|
||||||
* bandpass, and highpass outputs.
|
* bandpass, and highpass outputs.
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>Version <strong>0.2.0</strong>:
|
* <li>Version <strong>0.2.0</strong>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Refactored API to avoid dynamic memory allocation.</li>
|
* <li>Refactored API.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </li>
|
* </li>
|
||||||
* <li>Version <strong>0.1.0</strong>:
|
* <li>Version <strong>0.1.0</strong>:
|
||||||
@ -113,13 +113,20 @@ void bw_svf_set_Q(bw_svf *instance, float value);
|
|||||||
* Default value: `0.5f`.
|
* Default value: `0.5f`.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
/* WARNING: the internal definition of this struct is not part of the public
|
/* WARNING: the internal definition of this struct is not part of the public
|
||||||
* API. Its content may change at any time in future versions. Please, do not
|
* API. Its content may change at any time in future versions. Please, do not
|
||||||
* access its members directly. */
|
* access its members directly. */
|
||||||
struct _bw_svf {
|
struct _bw_svf {
|
||||||
|
// Sub-components
|
||||||
|
bw_one_pole_coeffs smooth_cutoff_coeffs;
|
||||||
|
bw_one_pole_state smooth_cutoff_state;
|
||||||
|
bw_one_pole_coeffs smooth_Q_coeffs;
|
||||||
|
bw_one_pole_state smooth_Q_state;
|
||||||
|
|
||||||
// Coefficients
|
// Coefficients
|
||||||
float t_k;
|
float t_k;
|
||||||
float smooth_mA1;
|
|
||||||
|
|
||||||
float t;
|
float t;
|
||||||
float k;
|
float k;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* module_type {{{ dsp }}}
|
* module_type {{{ dsp }}}
|
||||||
* version {{{ 0.2.0 }}}
|
* version {{{ 0.2.0 }}}
|
||||||
* requires {{{ bw_config bw_common bw_inline_one_pole bw_math bw_wah }}}
|
* requires {{{ bw_config bw_common bw_one_pole bw_math bw_wah }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Wah effect.
|
* Wah effect.
|
||||||
*
|
*
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* Brickworks
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021, 2022 Orastron Srl unipersonale
|
|
||||||
*
|
|
||||||
* Brickworks is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3 of the License.
|
|
||||||
*
|
|
||||||
* Brickworks is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
*
|
|
||||||
* File author: Stefano D'Angelo
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <bw_one_pole.h>
|
|
||||||
|
|
||||||
#include <bw_math.h>
|
|
||||||
|
|
||||||
void bw_one_pole_init(bw_one_pole *instance) {
|
|
||||||
instance->init_val = 0.f;
|
|
||||||
instance->cutoff_up = INFINITY;
|
|
||||||
instance->cutoff_down = INFINITY;
|
|
||||||
instance->sticky_thresh = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_sample_rate(bw_one_pole *instance, float sample_rate) {
|
|
||||||
instance->Ttm2pi = -6.283185307179586f / sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_reset(bw_one_pole *instance) {
|
|
||||||
instance->first_run = 1;
|
|
||||||
instance->param_changed = ~0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PARAM_CUTOFF_UP 1
|
|
||||||
#define PARAM_CUTOFF_DOWN (1<<1)
|
|
||||||
#define PARAM_STICKY_THRESH (1<<2)
|
|
||||||
|
|
||||||
void bw_one_pole_process(bw_one_pole *instance, const float* x, float* y, int n_samples) {
|
|
||||||
if (instance->param_changed) {
|
|
||||||
if (instance->param_changed & PARAM_CUTOFF_UP)
|
|
||||||
instance->mA1u = bw_expf_3(instance->Ttm2pi * instance->cutoff_up);
|
|
||||||
if (instance->param_changed & PARAM_CUTOFF_DOWN)
|
|
||||||
instance->mA1d = bw_expf_3(instance->Ttm2pi * instance->cutoff_down);
|
|
||||||
if (instance->param_changed & PARAM_STICKY_THRESH)
|
|
||||||
instance->st2 = instance->sticky_thresh * instance->sticky_thresh;
|
|
||||||
instance->param_changed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->first_run) {
|
|
||||||
instance->x_z1 = instance->init_val;
|
|
||||||
instance->y_z1 = instance->init_val;
|
|
||||||
instance->first_run = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->mA1u != instance->mA1d) {
|
|
||||||
if (instance->st2 != 0.f) {
|
|
||||||
if (instance->sticky_mode == bw_one_pole_sticky_mode_abs)
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
float out = in + (in >= instance->y_z1 ? instance->mA1u : instance->mA1d) * (instance->y_z1 - in);
|
|
||||||
const float d = out - in;
|
|
||||||
if (d * d <= instance->st2)
|
|
||||||
out = in;
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
float out = in + (in >= instance->y_z1 ? instance->mA1u : instance->mA1d) * (instance->y_z1 - in);
|
|
||||||
const float d = out - in;
|
|
||||||
if (d * d <= instance->st2 * in * in)
|
|
||||||
out = in;
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
const float out = in + (in >= instance->y_z1 ? instance->mA1u : instance->mA1d) * (instance->y_z1 - in);
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (instance->st2 != 0.f) {
|
|
||||||
if (instance->sticky_mode == bw_one_pole_sticky_mode_abs)
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
float out = in + instance->mA1u * (instance->y_z1 - in);
|
|
||||||
const float d = out - in;
|
|
||||||
if (d * d <= instance->st2)
|
|
||||||
out = in;
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
float out = in + instance->mA1u * (instance->y_z1 - in);
|
|
||||||
const float d = out - in;
|
|
||||||
if (d * d <= instance->st2 * in * in)
|
|
||||||
out = in;
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float in = x[i];
|
|
||||||
const float out = in + instance->mA1u * (instance->y_z1 - in);
|
|
||||||
instance->x_z1 = in;
|
|
||||||
instance->y_z1 = out;
|
|
||||||
y[i] = out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_init_val(bw_one_pole *instance, float value) {
|
|
||||||
instance->init_val = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_cutoff(bw_one_pole *instance, float value) {
|
|
||||||
bw_one_pole_set_cutoff_up(instance, value);
|
|
||||||
bw_one_pole_set_cutoff_down(instance, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_cutoff_up(bw_one_pole *instance, float value) {
|
|
||||||
if (instance->cutoff_up != value) {
|
|
||||||
instance->cutoff_up = value;
|
|
||||||
instance->param_changed |= PARAM_CUTOFF_UP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_cutoff_down(bw_one_pole *instance, float value) {
|
|
||||||
if (instance->cutoff_down != value) {
|
|
||||||
instance->cutoff_down = value;
|
|
||||||
instance->param_changed |= PARAM_CUTOFF_DOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_tau(bw_one_pole *instance, float value) {
|
|
||||||
bw_one_pole_set_tau_up(instance, value);
|
|
||||||
bw_one_pole_set_tau_down(instance, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_tau_up(bw_one_pole *instance, float value) {
|
|
||||||
bw_one_pole_set_cutoff_up(instance, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
|
||||||
// tau < 1 ns is instantaneous for any practical purpose
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_tau_down(bw_one_pole *instance, float value) {
|
|
||||||
bw_one_pole_set_cutoff_down(instance, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
|
||||||
// as before
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_sticky_thresh(bw_one_pole *instance, float value) {
|
|
||||||
if (instance->sticky_thresh != value) {
|
|
||||||
instance->sticky_thresh = value;
|
|
||||||
instance->param_changed |= PARAM_STICKY_THRESH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_one_pole_set_sticky_mode(bw_one_pole *instance, bw_one_pole_sticky_mode value) {
|
|
||||||
instance->sticky_mode = value;
|
|
||||||
}
|
|
27
src/bw_svf.c
27
src/bw_svf.c
@ -20,16 +20,22 @@
|
|||||||
#include <bw_svf.h>
|
#include <bw_svf.h>
|
||||||
|
|
||||||
#include <bw_math.h>
|
#include <bw_math.h>
|
||||||
#include <bw_inline_one_pole.h>
|
|
||||||
|
|
||||||
void bw_svf_init(bw_svf *instance) {
|
void bw_svf_init(bw_svf *instance) {
|
||||||
|
bw_one_pole_init(&instance->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_set_tau(&instance->smooth_cutoff_coeffs, 0.05f);
|
||||||
|
bw_one_pole_set_sticky_thresh(&instance->smooth_cutoff_coeffs, 1e-3f);
|
||||||
|
bw_one_pole_init(&instance->smooth_Q_coeffs);
|
||||||
|
bw_one_pole_set_tau(&instance->smooth_Q_coeffs, 0.05f);
|
||||||
|
bw_one_pole_set_sticky_thresh(&instance->smooth_Q_coeffs, 1e-3f);
|
||||||
instance->cutoff = 1e3f;
|
instance->cutoff = 1e3f;
|
||||||
instance->Q = 0.5f;
|
instance->Q = 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_svf_set_sample_rate(bw_svf *instance, float sample_rate) {
|
void bw_svf_set_sample_rate(bw_svf *instance, float sample_rate) {
|
||||||
|
bw_one_pole_set_sample_rate(&instance->smooth_cutoff_coeffs, sample_rate);
|
||||||
|
bw_one_pole_set_sample_rate(&instance->smooth_Q_coeffs, sample_rate);
|
||||||
instance->t_k = 3.141592653589793f / sample_rate;
|
instance->t_k = 3.141592653589793f / sample_rate;
|
||||||
instance->smooth_mA1 = bw_inline_one_pole_get_mA1(sample_rate, 0.05f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_svf_reset(bw_svf *instance) {
|
void bw_svf_reset(bw_svf *instance) {
|
||||||
@ -40,15 +46,17 @@ void bw_svf_reset(bw_svf *instance) {
|
|||||||
#define PARAM_Q (1<<1)
|
#define PARAM_Q (1<<1)
|
||||||
|
|
||||||
static inline void update_coefficients(bw_svf *instance) {
|
static inline void update_coefficients(bw_svf *instance) {
|
||||||
|
bw_one_pole_update_coeffs_audio(&instance->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_update_coeffs_audio(&instance->smooth_Q_coeffs);
|
||||||
const char cutoff_changed = instance->cutoff != instance->cutoff_cur || instance->first_run;
|
const char cutoff_changed = instance->cutoff != instance->cutoff_cur || instance->first_run;
|
||||||
const char Q_changed = instance->Q != instance->Q_cur || instance->first_run;
|
const char Q_changed = instance->Q != instance->Q_cur || instance->first_run;
|
||||||
if (cutoff_changed || Q_changed) {
|
if (cutoff_changed || Q_changed) {
|
||||||
if (cutoff_changed) {
|
if (cutoff_changed) {
|
||||||
instance->cutoff_cur = bw_inline_one_pole_sticky_rel(instance->cutoff, instance->cutoff_cur, instance->smooth_mA1, 1e-6f);
|
instance->cutoff_cur = bw_one_pole_process1_sticky_rel(&instance->smooth_cutoff_coeffs, &instance->smooth_cutoff_state, instance->cutoff);
|
||||||
instance->t = bw_tanf_3(instance->t_k * instance->cutoff_cur);
|
instance->t = bw_tanf_3(instance->t_k * instance->cutoff_cur);
|
||||||
}
|
}
|
||||||
if (Q_changed) {
|
if (Q_changed) {
|
||||||
instance->Q_cur = bw_inline_one_pole_sticky_abs(instance->Q, instance->Q_cur, instance->smooth_mA1, 1e-6f);
|
instance->Q_cur = bw_one_pole_process1_sticky_abs(&instance->smooth_Q_coeffs, &instance->smooth_Q_state, instance->Q);
|
||||||
instance->k = bw_rcpf_2(instance->Q_cur);
|
instance->k = bw_rcpf_2(instance->Q_cur);
|
||||||
}
|
}
|
||||||
const float kpt = instance->k + instance->t;
|
const float kpt = instance->k + instance->t;
|
||||||
@ -60,14 +68,21 @@ static inline void update_coefficients(bw_svf *instance) {
|
|||||||
|
|
||||||
void bw_svf_process(bw_svf *instance, const float *x, float *y_lp, float *y_bp, float *y_hp, int n_samples) {
|
void bw_svf_process(bw_svf *instance, const float *x, float *y_lp, float *y_bp, float *y_hp, int n_samples) {
|
||||||
if (instance->first_run) {
|
if (instance->first_run) {
|
||||||
instance->cutoff_cur = instance->cutoff;
|
bw_one_pole_set_init_val(&instance->smooth_cutoff_coeffs, instance->cutoff);
|
||||||
instance->Q_cur = instance->Q;
|
bw_one_pole_reset_coeffs(&instance->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_reset_state(&instance->smooth_cutoff_coeffs, &instance->smooth_cutoff_state);
|
||||||
|
bw_one_pole_set_init_val(&instance->smooth_Q_coeffs, instance->Q);
|
||||||
|
bw_one_pole_reset_coeffs(&instance->smooth_Q_coeffs);
|
||||||
|
bw_one_pole_reset_state(&instance->smooth_Q_coeffs, &instance->smooth_Q_state);
|
||||||
update_coefficients(instance);
|
update_coefficients(instance);
|
||||||
instance->hp_z1 = 0.f;
|
instance->hp_z1 = 0.f;
|
||||||
instance->lp_z1 = 0.f;
|
instance->lp_z1 = 0.f;
|
||||||
instance->bp_z1 = 0.f;
|
instance->bp_z1 = 0.f;
|
||||||
instance->first_run = 0;
|
instance->first_run = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bw_one_pole_update_coeffs_ctrl(&instance->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_update_coeffs_ctrl(&instance->smooth_Q_coeffs);
|
||||||
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
update_coefficients(instance);
|
update_coefficients(instance);
|
||||||
|
Loading…
Reference in New Issue
Block a user