updated svf to new API (still doc and wah/synth examples broken)
This commit is contained in:
parent
98990c7437
commit
3b8a4d7186
@ -1,10 +1,13 @@
|
|||||||
0.2.0
|
0.2.0
|
||||||
-----
|
-----
|
||||||
* Refactored API of DSP modules to avoid dynamic memory allocation.
|
* Refactored API of DSP modules.
|
||||||
|
* Removed bw_inline_one_pole (functionality implemented by bw_one_pole).
|
||||||
* Added bw_wah and bw_example_fx_wah.
|
* Added bw_wah and bw_example_fx_wah.
|
||||||
|
* Added BW_RESTRICT and removed BW_MALLOC, BW_REALLOC, and BW_FREE from
|
||||||
|
bw_common.
|
||||||
* Renamed bw_example_fx to bw_example_fx_svf.
|
* Renamed bw_example_fx to bw_example_fx_svf.
|
||||||
* Removed output "Level" parameter from bw_example_fx_svf.
|
* Removed output "Level" parameter from bw_example_fx_svf.
|
||||||
* Now using correct "Fx|Filter" VST3 subcategory for bw_example_fx_svf.
|
* Using correct "Fx|Filter" VST3 subcategory for bw_example_fx_svf.
|
||||||
* Using official logo as VST3 plugin icon.
|
* Using official logo as VST3 plugin icon.
|
||||||
|
|
||||||
0.1.0
|
0.1.0
|
||||||
|
1
TODO
1
TODO
@ -9,6 +9,7 @@ code:
|
|||||||
* web examples construction/destruction
|
* web examples construction/destruction
|
||||||
* web effect multichannel in?
|
* web effect multichannel in?
|
||||||
* check const restrict etc.
|
* check const restrict etc.
|
||||||
|
* define BW_RESTRICT to __restrict or similar when the compiler supports it
|
||||||
|
|
||||||
build system:
|
build system:
|
||||||
* make makefiles handle paths with spaces etc
|
* make makefiles handle paths with spaces etc
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "bw_example_fx_svf.h"
|
#include "bw_example_fx_svf.h"
|
||||||
|
|
||||||
#include <bw_common.h>
|
|
||||||
#include <bw_svf.h>
|
#include <bw_svf.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
p_cutoff,
|
p_cutoff,
|
||||||
@ -30,42 +30,44 @@ enum {
|
|||||||
|
|
||||||
struct _bw_example_fx_svf {
|
struct _bw_example_fx_svf {
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_svf svf;
|
bw_svf_coeffs svf_coeffs;
|
||||||
|
bw_svf_state svf_state;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
float params[p_n];
|
float params[p_n];
|
||||||
};
|
};
|
||||||
|
|
||||||
bw_example_fx_svf bw_example_fx_svf_new() {
|
bw_example_fx_svf bw_example_fx_svf_new() {
|
||||||
bw_example_fx_svf instance = (bw_example_fx_svf)BW_MALLOC(sizeof(struct _bw_example_fx_svf));
|
bw_example_fx_svf instance = (bw_example_fx_svf)malloc(sizeof(struct _bw_example_fx_svf));
|
||||||
if (instance != NULL)
|
if (instance != NULL)
|
||||||
bw_svf_init(&instance->svf);
|
bw_svf_init(&instance->svf_coeffs);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_svf_free(bw_example_fx_svf instance) {
|
void bw_example_fx_svf_free(bw_example_fx_svf instance) {
|
||||||
BW_FREE(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_svf_set_sample_rate(bw_example_fx_svf instance, float sample_rate) {
|
void bw_example_fx_svf_set_sample_rate(bw_example_fx_svf instance, float sample_rate) {
|
||||||
bw_svf_set_sample_rate(&instance->svf, sample_rate);
|
bw_svf_set_sample_rate(&instance->svf_coeffs, sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_svf_reset(bw_example_fx_svf instance) {
|
void bw_example_fx_svf_reset(bw_example_fx_svf instance) {
|
||||||
bw_svf_reset(&instance->svf);
|
bw_svf_reset_coeffs(&instance->svf_coeffs);
|
||||||
|
bw_svf_reset_state(&instance->svf_coeffs, &instance->svf_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_svf_process(bw_example_fx_svf instance, const float** x, float** y, int n_samples) {
|
void bw_example_fx_svf_process(bw_example_fx_svf instance, const float** x, float** y, int n_samples) {
|
||||||
bw_svf_process(&instance->svf, x[0], y[0], NULL, NULL, n_samples);
|
bw_svf_process(&instance->svf_coeffs, &instance->svf_state, x[0], y[0], NULL, NULL, n_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_svf_set_parameter(bw_example_fx_svf instance, int index, float value) {
|
void bw_example_fx_svf_set_parameter(bw_example_fx_svf instance, int index, float value) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case p_cutoff:
|
case p_cutoff:
|
||||||
bw_svf_set_cutoff(&instance->svf, (20e3f - 20.f) * value * value * value + 20.f);
|
bw_svf_set_cutoff(&instance->svf_coeffs, (20e3f - 20.f) * value * value * value + 20.f);
|
||||||
break;
|
break;
|
||||||
case p_Q:
|
case p_Q:
|
||||||
bw_svf_set_Q(&instance->svf, 0.5f + 9.5f * value);
|
bw_svf_set_Q(&instance->svf_coeffs, 0.5f + 9.5f * value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ INSTALL_PREFIX=/usr/local
|
|||||||
|
|
||||||
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
${ROOT_DIR}/../../../src/bw_svf.c \
|
|
||||||
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
||||||
\
|
\
|
||||||
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
||||||
|
@ -17,7 +17,6 @@ LDFLAGS= \
|
|||||||
|
|
||||||
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
${ROOT_DIR}/../../../src/bw_svf.c \
|
|
||||||
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
||||||
\
|
\
|
||||||
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
||||||
|
@ -25,7 +25,6 @@ ARCH=x86_64
|
|||||||
|
|
||||||
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
${ROOT_DIR}/../../../src/bw_svf.c \
|
|
||||||
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
||||||
\
|
\
|
||||||
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
${ROOT_DIR}/../../common/vst3/entry.cpp \
|
||||||
|
@ -25,7 +25,6 @@ LDFLAGS= \
|
|||||||
|
|
||||||
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
${ROOT_DIR}/../../../src/bw_svf.c \
|
|
||||||
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
${ROOT_DIR}/../src/bw_example_fx_svf.c \
|
||||||
${ROOT_DIR}/../../common/web/walloc.c \
|
${ROOT_DIR}/../../common/web/walloc.c \
|
||||||
${ROOT_DIR}/../../common/web/wrapper.c
|
${ROOT_DIR}/../../common/web/wrapper.c
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
* <li>Version <strong>0.2.0</strong>:
|
* <li>Version <strong>0.2.0</strong>:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Removed BW_MALLOC, BW_REALLOC, and BW_FREE.</li>
|
* <li>Removed BW_MALLOC, BW_REALLOC, and BW_FREE.</li>
|
||||||
|
* <li>Added BW_RESTRICT.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* </li>
|
* </li>
|
||||||
* <li>Version <strong>0.1.0</strong>:
|
* <li>Version <strong>0.1.0</strong>:
|
||||||
@ -82,6 +83,14 @@
|
|||||||
# include <math.h>
|
# include <math.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BW_RESTRICT
|
||||||
|
# if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
|
||||||
|
# define BW_RESTRICT restrict
|
||||||
|
# else
|
||||||
|
# define BW_RESTRICT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! ... }}} */
|
/*! ... }}} */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <bw_common.h>
|
||||||
|
|
||||||
/*! api {{{
|
/*! api {{{
|
||||||
* #### bw_one_pole_coeffs
|
* #### bw_one_pole_coeffs
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
@ -75,39 +77,39 @@ typedef enum {
|
|||||||
*
|
*
|
||||||
* #### bw_one_pole_init()
|
* #### bw_one_pole_init()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_init(bw_one_pole_coeffs *restrict coeffs);
|
static inline void bw_one_pole_init(bw_one_pole_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Initializes `coeffs`.
|
* Initializes `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_one_pole_set_sample_rate()
|
* #### bw_one_pole_set_sample_rate()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *restrict coeffs, float sample_rate);
|
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the `sample_rate` (Hz) value for the given `coeffs`.
|
* Sets the `sample_rate` (Hz) value for the given `coeffs`.
|
||||||
*
|
*
|
||||||
* #### bw_one_pole_reset_state()
|
* #### 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);
|
static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Resets the given `state` to the initial state using the given `coeffs`.
|
* 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);
|
static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs);
|
||||||
|
|
||||||
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *restrict coeffs);
|
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs);
|
||||||
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *restrict coeffs);
|
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *BW_RESTRICT coeffs);
|
||||||
|
|
||||||
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(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_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_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_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_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_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(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_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_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_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);
|
static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x);
|
||||||
|
|
||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_process()
|
* #### bw_one_pole_process()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
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);
|
static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, int n_samples);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* 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
|
||||||
@ -117,7 +119,7 @@ static inline void bw_one_pole_process(bw_one_pole_coeffs *restrict coeffs, bw_o
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_init_val()
|
* #### bw_one_pole_set_init_val()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the initial/quiescent `value` for the given `instance`.
|
* Sets the initial/quiescent `value` for the given `instance`.
|
||||||
*
|
*
|
||||||
@ -131,7 +133,7 @@ static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *restrict coeffs,
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff()
|
* #### bw_one_pole_set_cutoff()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -147,7 +149,7 @@ static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *restrict coeffs, f
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff_up()
|
* #### bw_one_pole_set_cutoff_up()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -161,7 +163,7 @@ static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *restrict coeffs
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_cutoff_down()
|
* #### bw_one_pole_set_cutoff_down()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -175,7 +177,7 @@ static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *restrict coef
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau()
|
* #### bw_one_pole_set_tau()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -191,7 +193,7 @@ static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *restrict coeffs, floa
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau_up()
|
* #### bw_one_pole_set_tau_up()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -205,7 +207,7 @@ static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *restrict coeffs, f
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_tau_down()
|
* #### bw_one_pole_set_tau_down()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -219,7 +221,7 @@ static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *restrict coeffs,
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_sticky_thresh()
|
* #### bw_one_pole_set_sticky_thresh()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *restrict coeffs, float value);
|
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *BW_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`.
|
||||||
@ -235,7 +237,7 @@ static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *restrict co
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_one_pole_set_sticky_mode()
|
* #### bw_one_pole_set_sticky_mode()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *restrict coeffs, bw_one_pole_sticky_mode value);
|
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_sticky_mode value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the current distance metric for sticky behavior.
|
* Sets the current distance metric for sticky behavior.
|
||||||
* }}} */
|
* }}} */
|
||||||
@ -272,27 +274,27 @@ struct _bw_one_pole_state {
|
|||||||
|
|
||||||
#include <bw_math.h>
|
#include <bw_math.h>
|
||||||
|
|
||||||
static inline void bw_one_pole_init(bw_one_pole_coeffs *restrict coeffs) {
|
static inline void bw_one_pole_init(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
|
||||||
coeffs->init_val = 0.f;
|
coeffs->init_val = 0.f;
|
||||||
coeffs->cutoff_up = INFINITY;
|
coeffs->cutoff_up = INFINITY;
|
||||||
coeffs->cutoff_down = INFINITY;
|
coeffs->cutoff_down = INFINITY;
|
||||||
coeffs->sticky_thresh = 0.f;
|
coeffs->sticky_thresh = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *restrict coeffs, float sample_rate) {
|
static inline void bw_one_pole_set_sample_rate(bw_one_pole_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
coeffs->Ttm2pi = -6.283185307179586f / sample_rate;
|
coeffs->Ttm2pi = -6.283185307179586f / sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *restrict coeffs) {
|
static inline void bw_one_pole_reset_coeffs(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
|
||||||
coeffs->param_changed = ~0;
|
coeffs->param_changed = ~0;
|
||||||
bw_one_pole_update_coeffs_ctrl(coeffs);
|
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) {
|
static inline void bw_one_pole_reset_state(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state) {
|
||||||
state->y_z1 = coeffs->init_val;
|
state->y_z1 = coeffs->init_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *restrict coeffs) {
|
static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
|
||||||
if (coeffs->param_changed) {
|
if (coeffs->param_changed) {
|
||||||
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_CUTOFF_UP)
|
if (coeffs->param_changed & _BW_ONE_POLE_PARAM_CUTOFF_UP)
|
||||||
coeffs->mA1u = bw_expf_3(coeffs->Ttm2pi * coeffs->cutoff_up);
|
coeffs->mA1u = bw_expf_3(coeffs->Ttm2pi * coeffs->cutoff_up);
|
||||||
@ -304,16 +306,16 @@ static inline void bw_one_pole_update_coeffs_ctrl(bw_one_pole_coeffs *restrict c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *restrict coeffs) {
|
static inline void bw_one_pole_update_coeffs_audio(bw_one_pole_coeffs *BW_RESTRICT coeffs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
const float y = x + coeffs->mA1u * (state->y_z1 - x);
|
const float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
state->y_z1 = y;
|
state->y_z1 = y;
|
||||||
return 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) {
|
static inline float bw_one_pole_process1_sticky_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
const float d = y - x;
|
const float d = y - x;
|
||||||
if (d * d <= coeffs->st2)
|
if (d * d <= coeffs->st2)
|
||||||
@ -322,7 +324,7 @@ static inline float bw_one_pole_process1_sticky_abs(const bw_one_pole_coeffs *re
|
|||||||
return 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) {
|
static inline float bw_one_pole_process1_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
float y = x + coeffs->mA1u * (state->y_z1 - x);
|
||||||
const float d = y - x;
|
const float d = y - x;
|
||||||
if (d * d <= coeffs->st2 * x * x)
|
if (d * d <= coeffs->st2 * x * x)
|
||||||
@ -331,13 +333,13 @@ static inline float bw_one_pole_process1_sticky_rel(const bw_one_pole_coeffs *re
|
|||||||
return 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) {
|
static inline float bw_one_pole_process1_asym(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
const float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
const float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
state->y_z1 = y;
|
state->y_z1 = y;
|
||||||
return 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) {
|
static inline float bw_one_pole_process1_asym_sticky_abs(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
const float d = y - x;
|
const float d = y - x;
|
||||||
if (d * d <= coeffs->st2)
|
if (d * d <= coeffs->st2)
|
||||||
@ -346,7 +348,7 @@ static inline float bw_one_pole_process1_asym_sticky_abs(const bw_one_pole_coeff
|
|||||||
return 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) {
|
static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, float x) {
|
||||||
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
float y = x + (x >= state->y_z1 ? coeffs->mA1u : coeffs->mA1d) * (state->y_z1 - x);
|
||||||
const float d = y - x;
|
const float d = y - x;
|
||||||
if (d * d <= coeffs->st2 * x * x)
|
if (d * d <= coeffs->st2 * x * x)
|
||||||
@ -355,7 +357,7 @@ static inline float bw_one_pole_process1_asym_sticky_rel(const bw_one_pole_coeff
|
|||||||
return 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) {
|
static inline void bw_one_pole_process(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
||||||
bw_one_pole_update_coeffs_ctrl(coeffs);
|
bw_one_pole_update_coeffs_ctrl(coeffs);
|
||||||
|
|
||||||
if (coeffs->mA1u != coeffs->mA1d) {
|
if (coeffs->mA1u != coeffs->mA1d) {
|
||||||
@ -388,52 +390,52 @@ static inline void bw_one_pole_process(bw_one_pole_coeffs *restrict coeffs, bw_o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *restrict coeffs, float value) {
|
static inline void bw_one_pole_set_init_val(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
coeffs->init_val = value;
|
coeffs->init_val = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *restrict coeffs, float value) {
|
static inline void bw_one_pole_set_cutoff(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_one_pole_set_cutoff_up(coeffs, value);
|
bw_one_pole_set_cutoff_up(coeffs, value);
|
||||||
bw_one_pole_set_cutoff_down(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) {
|
static inline void bw_one_pole_set_cutoff_up(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
if (coeffs->cutoff_up != value) {
|
if (coeffs->cutoff_up != value) {
|
||||||
coeffs->cutoff_up = value;
|
coeffs->cutoff_up = value;
|
||||||
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_UP;
|
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) {
|
static inline void bw_one_pole_set_cutoff_down(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
if (coeffs->cutoff_down != value) {
|
if (coeffs->cutoff_down != value) {
|
||||||
coeffs->cutoff_down = value;
|
coeffs->cutoff_down = value;
|
||||||
coeffs->param_changed |= _BW_ONE_POLE_PARAM_CUTOFF_DOWN;
|
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) {
|
static inline void bw_one_pole_set_tau(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_one_pole_set_tau_up(coeffs, value);
|
bw_one_pole_set_tau_up(coeffs, value);
|
||||||
bw_one_pole_set_tau_down(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) {
|
static inline void bw_one_pole_set_tau_up(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_one_pole_set_cutoff_up(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(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
|
// 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) {
|
static inline void bw_one_pole_set_tau_down(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
bw_one_pole_set_cutoff_down(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
bw_one_pole_set_cutoff_down(coeffs, value < 1e-9f ? INFINITY : 0.1591549430918953f * bw_rcpf_2(value));
|
||||||
// as before
|
// as before
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *restrict coeffs, float value) {
|
static inline void bw_one_pole_set_sticky_thresh(bw_one_pole_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
if (coeffs->sticky_thresh != value) {
|
if (coeffs->sticky_thresh != value) {
|
||||||
coeffs->sticky_thresh = value;
|
coeffs->sticky_thresh = value;
|
||||||
coeffs->param_changed |= _BW_ONE_POLE_PARAM_STICKY_THRESH;
|
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) {
|
static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT coeffs, bw_one_pole_sticky_mode value) {
|
||||||
coeffs->sticky_mode = value;
|
coeffs->sticky_mode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
280
include/bw_svf.h
280
include/bw_svf.h
@ -48,42 +48,57 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! api {{{
|
#include <bw_common.h>
|
||||||
* #### bw_svf
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_svf bw_svf;
|
|
||||||
/*! <<<```
|
|
||||||
* Instance object.
|
|
||||||
* >>> */
|
|
||||||
|
|
||||||
/*! ...
|
/*! api {{{
|
||||||
|
* #### bw_svf_coeffs
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_svf_coeffs bw_svf_coeffs;
|
||||||
|
/*! <<<```
|
||||||
|
* Coefficients.
|
||||||
|
*
|
||||||
|
* ### bw_svf_state
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_svf_state bw_svf_state;
|
||||||
|
/*! <<<```
|
||||||
|
* State.
|
||||||
|
*
|
||||||
* #### bw_svf_init()
|
* #### bw_svf_init()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_svf_init(bw_svf *instance);
|
static inline void bw_svf_init(bw_svf_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Initializes the `instance` object.
|
* Initializes `coeffs`.
|
||||||
* >>> */
|
*
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_svf_set_sample_rate()
|
* #### bw_svf_set_sample_rate()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_svf_set_sample_rate(bw_svf *instance, float sample_rate);
|
static inline void bw_svf_set_sample_rate(bw_svf_coeffs *BW_RESTRICT coeffs, float sample_rate);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the `sample_rate` (Hz) value for the given `instance`.
|
* Sets the `sample_rate` (Hz) value for the given `coeffs`.
|
||||||
|
*
|
||||||
|
* #### bw_svf_reset_state()
|
||||||
|
* ```>>> */
|
||||||
|
static inline void bw_svf_reset_state(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state);
|
||||||
|
/*! <<<```
|
||||||
|
* Resets the given `state` to the initial state using the given `coeffs`.
|
||||||
* >>> */
|
* >>> */
|
||||||
|
|
||||||
/*! ...
|
static inline void bw_svf_reset_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs);
|
||||||
* #### bw_svf_reset()
|
|
||||||
* ```>>> */
|
static inline void bw_svf_update_coeffs_ctrl(bw_svf_coeffs *BW_RESTRICT coeffs);
|
||||||
void bw_svf_reset(bw_svf *instance);
|
static inline void bw_svf_update_coeffs_audio(bw_svf_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
|
||||||
* Resets the given `instance` to its initial state.
|
static inline float bw_svf_process1_lp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x);
|
||||||
* >>> */
|
static inline float bw_svf_process1_bp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x);
|
||||||
|
static inline float bw_svf_process1_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x);
|
||||||
|
static inline void bw_svf_process1_lp_bp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp);
|
||||||
|
static inline void bw_svf_process1_lp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_hp);
|
||||||
|
static inline void bw_svf_process1_bp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_bp, float *y_hp);
|
||||||
|
static inline void bw_svf_process1_lp_bp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp, float *y_hp);
|
||||||
|
|
||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_svf_process()
|
* #### bw_svf_process()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_svf_process(bw_svf *instance, const float *x, float* y_lp, float *y_bp, float *y_hp, int n_samples);
|
static inline void bw_svf_process(bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, const float *x, float *y_lp, float *y_bp, float *y_hp, 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
|
||||||
@ -94,7 +109,7 @@ void bw_svf_process(bw_svf *instance, const float *x, float* y_lp, float *y_bp,
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_svf_set_cutoff()
|
* #### bw_svf_set_cutoff()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_svf_set_cutoff(bw_svf *instance, float value);
|
static inline void bw_svf_set_cutoff(bw_svf_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the cutoff frequency to the given `value` (Hz) for the given
|
* Sets the cutoff frequency to the given `value` (Hz) for the given
|
||||||
* `instance`.
|
* `instance`.
|
||||||
@ -105,7 +120,7 @@ void bw_svf_set_cutoff(bw_svf *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_svf_set_Q()
|
* #### bw_svf_set_Q()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_svf_set_Q(bw_svf *instance, float value);
|
static inline void bw_svf_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the quality factor to the given `value` (Hz) for the given
|
* Sets the quality factor to the given `value` (Hz) for the given
|
||||||
* `instance`.
|
* `instance`.
|
||||||
@ -113,12 +128,14 @@ void bw_svf_set_Q(bw_svf *instance, float value);
|
|||||||
* Default value: `0.5f`.
|
* Default value: `0.5f`.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
|
/*** Implementation ***/
|
||||||
|
|
||||||
|
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||||
|
* change at any time in future versions. Please, do not use it directly. */
|
||||||
|
|
||||||
#include <bw_one_pole.h>
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
/* WARNING: the internal definition of this struct is not part of the public
|
struct _bw_svf_coeffs {
|
||||||
* API. Its content may change at any time in future versions. Please, do not
|
|
||||||
* access its members directly. */
|
|
||||||
struct _bw_svf {
|
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_one_pole_coeffs smooth_cutoff_coeffs;
|
bw_one_pole_coeffs smooth_cutoff_coeffs;
|
||||||
bw_one_pole_state smooth_cutoff_state;
|
bw_one_pole_state smooth_cutoff_state;
|
||||||
@ -126,28 +143,201 @@ struct _bw_svf {
|
|||||||
bw_one_pole_state smooth_Q_state;
|
bw_one_pole_state smooth_Q_state;
|
||||||
|
|
||||||
// Coefficients
|
// Coefficients
|
||||||
float t_k;
|
float t_k;
|
||||||
|
|
||||||
float t;
|
float t;
|
||||||
float k;
|
float k;
|
||||||
float hp_hp_z1;
|
float hp_hp_z1;
|
||||||
float hp_bp_z1;
|
float hp_bp_z1;
|
||||||
float hp_x;
|
float hp_x;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
float cutoff;
|
float cutoff;
|
||||||
float Q;
|
float Q;
|
||||||
|
|
||||||
float cutoff_cur;
|
float cutoff_cur;
|
||||||
float Q_cur;
|
float Q_cur;
|
||||||
|
|
||||||
// State
|
|
||||||
char first_run;
|
|
||||||
float hp_z1;
|
|
||||||
float lp_z1;
|
|
||||||
float bp_z1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _bw_svf_state {
|
||||||
|
// State
|
||||||
|
float hp_z1;
|
||||||
|
float lp_z1;
|
||||||
|
float bp_z1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void bw_svf_init(bw_svf_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_init(&coeffs->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_set_tau(&coeffs->smooth_cutoff_coeffs, 0.05f);
|
||||||
|
bw_one_pole_set_sticky_thresh(&coeffs->smooth_cutoff_coeffs, 1e-3f);
|
||||||
|
bw_one_pole_init(&coeffs->smooth_Q_coeffs);
|
||||||
|
bw_one_pole_set_tau(&coeffs->smooth_Q_coeffs, 0.05f);
|
||||||
|
bw_one_pole_set_sticky_thresh(&coeffs->smooth_Q_coeffs, 1e-3f);
|
||||||
|
coeffs->cutoff = 1e3f;
|
||||||
|
coeffs->Q = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_set_sample_rate(bw_svf_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
|
bw_one_pole_set_sample_rate(&coeffs->smooth_cutoff_coeffs, sample_rate);
|
||||||
|
bw_one_pole_set_sample_rate(&coeffs->smooth_Q_coeffs, sample_rate);
|
||||||
|
coeffs->t_k = 3.141592653589793f / sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _bw_svf_do_update_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs, char force) {
|
||||||
|
const char cutoff_changed = force || coeffs->cutoff != coeffs->cutoff_cur;
|
||||||
|
const char Q_changed = force || coeffs->Q != coeffs->Q_cur;
|
||||||
|
if (cutoff_changed || Q_changed) {
|
||||||
|
if (cutoff_changed) {
|
||||||
|
coeffs->cutoff_cur = bw_one_pole_process1_sticky_rel(&coeffs->smooth_cutoff_coeffs, &coeffs->smooth_cutoff_state, coeffs->cutoff);
|
||||||
|
coeffs->t = bw_tanf_3(coeffs->t_k * coeffs->cutoff_cur);
|
||||||
|
}
|
||||||
|
if (Q_changed) {
|
||||||
|
coeffs->Q_cur = bw_one_pole_process1_sticky_abs(&coeffs->smooth_Q_coeffs, &coeffs->smooth_Q_state, coeffs->Q);
|
||||||
|
coeffs->k = bw_rcpf_2(coeffs->Q_cur);
|
||||||
|
}
|
||||||
|
const float kpt = coeffs->k + coeffs->t;
|
||||||
|
coeffs->hp_hp_z1 = coeffs->t * kpt;
|
||||||
|
coeffs->hp_bp_z1 = coeffs->t + kpt;
|
||||||
|
coeffs->hp_x = bw_rcpf_2(1.f + coeffs->hp_hp_z1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_reset_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_set_init_val(&coeffs->smooth_cutoff_coeffs, coeffs->cutoff);
|
||||||
|
bw_one_pole_reset_coeffs(&coeffs->smooth_cutoff_coeffs);
|
||||||
|
bw_one_pole_reset_state(&coeffs->smooth_cutoff_coeffs, &coeffs->smooth_cutoff_state);
|
||||||
|
bw_one_pole_set_init_val(&coeffs->smooth_Q_coeffs, coeffs->Q);
|
||||||
|
bw_one_pole_reset_coeffs(&coeffs->smooth_Q_coeffs);
|
||||||
|
bw_one_pole_reset_state(&coeffs->smooth_Q_coeffs, &coeffs->smooth_Q_state);
|
||||||
|
_bw_svf_do_update_coeffs(coeffs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_reset_state(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state) {
|
||||||
|
state->hp_z1 = 0.f;
|
||||||
|
state->lp_z1 = 0.f;
|
||||||
|
state->bp_z1 = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_update_coeffs_ctrl(bw_svf_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_update_coeffs_audio(bw_svf_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
_bw_svf_do_update_coeffs(coeffs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_svf_process1_lp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
return lp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_svf_process1_bp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float bw_svf_process1_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_process1_lp_bp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
*y_lp = lp;
|
||||||
|
*y_bp = bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_process1_lp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_hp) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
*y_lp = lp;
|
||||||
|
*y_hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_process1_bp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_bp, float *y_hp) {
|
||||||
|
float lp, bp, hp;
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x, &lp, &bp, &hp);
|
||||||
|
*y_bp = bp;
|
||||||
|
*y_hp = hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_process1_lp_bp_hp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp, float *y_hp) {
|
||||||
|
*y_hp = coeffs->hp_x * (x - state->lp_z1 + coeffs->hp_bp_z1 * state->bp_z1 - coeffs->hp_hp_z1 * state->hp_z1);
|
||||||
|
*y_bp = state->bp_z1 - coeffs->t * (*y_hp + state->hp_z1);
|
||||||
|
*y_lp = state->lp_z1 - coeffs->t * (*y_bp + state->bp_z1);
|
||||||
|
|
||||||
|
state->hp_z1 = *y_hp;
|
||||||
|
state->lp_z1 = *y_lp;
|
||||||
|
state->bp_z1 = *y_bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_process(bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, const float *x, float *y_lp, float *y_bp, float *y_hp, int n_samples) {
|
||||||
|
if (y_lp != NULL) {
|
||||||
|
if (y_bp != NULL) {
|
||||||
|
if (y_hp != NULL) {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
bw_svf_process1_lp_bp_hp(coeffs, state, x[i], y_lp + i, y_bp + i, y_hp + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
bw_svf_process1_lp_bp(coeffs, state, x[i], y_lp + i, y_bp + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (y_hp != NULL) {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
bw_svf_process1_lp_hp(coeffs, state, x[i], y_lp + i, y_hp + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
y_lp[i] = bw_svf_process1_lp(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (y_bp != NULL) {
|
||||||
|
if (y_hp != NULL) {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
bw_svf_process1_bp_hp(coeffs, state, x[i], y_bp + i, y_hp + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
y_bp[i] = bw_svf_process1_bp(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (y_hp != NULL) {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
y_hp[i] = bw_svf_process1_hp(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
|
const float v = bw_svf_process1_lp(coeffs, state, x[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_set_cutoff(bw_svf_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
|
coeffs->cutoff = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_svf_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
|
coeffs->Q = value;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
111
src/bw_svf.c
111
src/bw_svf.c
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* Brickworks
|
|
||||||
*
|
|
||||||
* Copyright (C) 2022 Orastron Srl unipersonale
|
|
||||||
*
|
|
||||||
* Brickworks is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, version 3 of the License.
|
|
||||||
*
|
|
||||||
* Brickworks is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
*
|
|
||||||
* File author: Stefano D'Angelo
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <bw_svf.h>
|
|
||||||
|
|
||||||
#include <bw_math.h>
|
|
||||||
|
|
||||||
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->Q = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_svf_reset(bw_svf *instance) {
|
|
||||||
instance->first_run = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PARAM_CUTOFF 1
|
|
||||||
#define PARAM_Q (1<<1)
|
|
||||||
|
|
||||||
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 Q_changed = instance->Q != instance->Q_cur || instance->first_run;
|
|
||||||
if (cutoff_changed || Q_changed) {
|
|
||||||
if (cutoff_changed) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (Q_changed) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
const float kpt = instance->k + instance->t;
|
|
||||||
instance->hp_hp_z1 = instance->t * kpt;
|
|
||||||
instance->hp_bp_z1 = instance->t + kpt;
|
|
||||||
instance->hp_x = bw_rcpf_2(1.f + instance->hp_hp_z1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
bw_one_pole_set_init_val(&instance->smooth_cutoff_coeffs, instance->cutoff);
|
|
||||||
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);
|
|
||||||
instance->hp_z1 = 0.f;
|
|
||||||
instance->lp_z1 = 0.f;
|
|
||||||
instance->bp_z1 = 0.f;
|
|
||||||
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++) {
|
|
||||||
update_coefficients(instance);
|
|
||||||
|
|
||||||
const float hp = instance->hp_x * (x[i] - instance->lp_z1 + instance->hp_bp_z1 * instance->bp_z1 - instance->hp_hp_z1 * instance->hp_z1);
|
|
||||||
const float bp = instance->bp_z1 - instance->t * (hp + instance->hp_z1);
|
|
||||||
const float lp = instance->lp_z1 - instance->t * (bp + instance->bp_z1);
|
|
||||||
instance->hp_z1 = hp;
|
|
||||||
instance->lp_z1 = lp;
|
|
||||||
instance->bp_z1 = bp;
|
|
||||||
if (y_lp)
|
|
||||||
y_lp[i] = lp;
|
|
||||||
if (y_bp)
|
|
||||||
y_bp[i] = bp;
|
|
||||||
if (y_hp)
|
|
||||||
y_hp[i] = hp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_svf_set_cutoff(bw_svf *instance, float value) {
|
|
||||||
instance->cutoff = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_svf_set_Q(bw_svf *instance, float value) {
|
|
||||||
instance->Q = value;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user