using new API for phase gen + fixed param setting bug + fixes/improvements
This commit is contained in:
parent
6202235c48
commit
74dff37dd3
@ -66,6 +66,7 @@ void bw_example_fx_svf_process(bw_example_fx_svf instance, const float** x, floa
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
instance->params[index] = value;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case p_cutoff:
|
case p_cutoff:
|
||||||
bw_svf_set_cutoff(&instance->svf_coeffs, (20e3f - 20.f) * value * value * value + 20.f);
|
bw_svf_set_cutoff(&instance->svf_coeffs, (20e3f - 20.f) * value * value * value + 20.f);
|
||||||
|
@ -66,6 +66,7 @@ void bw_example_fx_wah_process(bw_example_fx_wah instance, const float** x, floa
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_fx_wah_set_parameter(bw_example_fx_wah instance, int index, float value) {
|
void bw_example_fx_wah_set_parameter(bw_example_fx_wah instance, int index, float value) {
|
||||||
|
instance->params[index] = value;
|
||||||
bw_wah_set_wah(&instance->wah_coeffs, value);
|
bw_wah_set_wah(&instance->wah_coeffs, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,20 @@
|
|||||||
|
|
||||||
#include <bw_math.h>
|
#include <bw_math.h>
|
||||||
#include <bw_phase_gen.h>
|
#include <bw_phase_gen.h>
|
||||||
|
#ifdef __WASM__
|
||||||
|
# include "walloc.h"
|
||||||
|
#else
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
#include <bw_osc_pulse.h>
|
#include <bw_osc_pulse.h>
|
||||||
#include <bw_osc_filt.h>
|
#include <bw_osc_filt.h>
|
||||||
#include <bw_svf.h>
|
#include <bw_svf.h>
|
||||||
#include <bw_env_gen.h>
|
#include <bw_env_gen.h>
|
||||||
#include <bw_vol.h>
|
#include <bw_vol.h>
|
||||||
#include <bw_env_follow.h>
|
#include <bw_env_follow.h>
|
||||||
|
*/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
p_volume,
|
p_volume,
|
||||||
@ -46,13 +54,16 @@ enum {
|
|||||||
|
|
||||||
struct _bw_example_synth {
|
struct _bw_example_synth {
|
||||||
// Sub-components
|
// Sub-components
|
||||||
bw_phase_gen phase_gen;
|
bw_phase_gen_coeffs phase_gen_coeffs;
|
||||||
|
bw_phase_gen_state phase_gen_state;
|
||||||
|
/*
|
||||||
bw_osc_pulse osc_pulse;
|
bw_osc_pulse osc_pulse;
|
||||||
bw_osc_filt osc_filt;
|
bw_osc_filt osc_filt;
|
||||||
bw_svf svf;
|
bw_svf svf;
|
||||||
bw_env_gen env_gen;
|
bw_env_gen env_gen;
|
||||||
bw_vol vol;
|
bw_vol vol;
|
||||||
bw_env_follow env_follow;
|
bw_env_follow env_follow;
|
||||||
|
*/
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
float params[p_n];
|
float params[p_n];
|
||||||
@ -66,11 +77,12 @@ struct _bw_example_synth {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bw_example_synth bw_example_synth_new() {
|
bw_example_synth bw_example_synth_new() {
|
||||||
bw_example_synth instance = (bw_example_synth)BW_MALLOC(sizeof(struct _bw_example_synth));
|
bw_example_synth instance = (bw_example_synth)malloc(sizeof(struct _bw_example_synth));
|
||||||
if (instance == NULL)
|
if (instance == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bw_phase_gen_init(&instance->phase_gen);
|
bw_phase_gen_init(&instance->phase_gen_coeffs);
|
||||||
|
/*
|
||||||
bw_osc_pulse_init(&instance->osc_pulse);
|
bw_osc_pulse_init(&instance->osc_pulse);
|
||||||
bw_osc_filt_init(&instance->osc_filt);
|
bw_osc_filt_init(&instance->osc_filt);
|
||||||
bw_svf_init(&instance->svf);
|
bw_svf_init(&instance->svf);
|
||||||
@ -80,43 +92,52 @@ bw_example_synth bw_example_synth_new() {
|
|||||||
|
|
||||||
bw_osc_pulse_set_antialiasing(&instance->osc_pulse, 1);
|
bw_osc_pulse_set_antialiasing(&instance->osc_pulse, 1);
|
||||||
bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(&instance->env_follow), 1.f);
|
bw_one_pole_set_cutoff_down(bw_env_follow_get_one_pole(&instance->env_follow), 1.f);
|
||||||
|
*/
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_synth_free(bw_example_synth instance) {
|
void bw_example_synth_free(bw_example_synth instance) {
|
||||||
BW_FREE(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_synth_set_sample_rate(bw_example_synth instance, float sample_rate) {
|
void bw_example_synth_set_sample_rate(bw_example_synth instance, float sample_rate) {
|
||||||
bw_phase_gen_set_sample_rate(&instance->phase_gen, sample_rate);
|
bw_phase_gen_set_sample_rate(&instance->phase_gen_coeffs, sample_rate);
|
||||||
|
/*
|
||||||
bw_osc_pulse_set_sample_rate(&instance->osc_pulse, sample_rate);
|
bw_osc_pulse_set_sample_rate(&instance->osc_pulse, sample_rate);
|
||||||
bw_svf_set_sample_rate(&instance->svf, sample_rate);
|
bw_svf_set_sample_rate(&instance->svf, sample_rate);
|
||||||
bw_env_gen_set_sample_rate(&instance->env_gen, sample_rate);
|
bw_env_gen_set_sample_rate(&instance->env_gen, sample_rate);
|
||||||
bw_vol_set_sample_rate(&instance->vol, sample_rate);
|
bw_vol_set_sample_rate(&instance->vol, sample_rate);
|
||||||
bw_env_follow_set_sample_rate(&instance->env_follow, sample_rate);
|
bw_env_follow_set_sample_rate(&instance->env_follow, sample_rate);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_synth_reset(bw_example_synth instance) {
|
void bw_example_synth_reset(bw_example_synth instance) {
|
||||||
bw_phase_gen_reset(&instance->phase_gen);
|
bw_phase_gen_reset_coeffs(&instance->phase_gen_coeffs);
|
||||||
|
bw_phase_gen_reset_state(&instance->phase_gen_coeffs, &instance->phase_gen_state);
|
||||||
|
/*
|
||||||
bw_osc_pulse_reset(&instance->osc_pulse);
|
bw_osc_pulse_reset(&instance->osc_pulse);
|
||||||
bw_osc_filt_reset(&instance->osc_filt);
|
bw_osc_filt_reset(&instance->osc_filt);
|
||||||
bw_svf_reset(&instance->svf);
|
bw_svf_reset(&instance->svf);
|
||||||
bw_env_gen_reset(&instance->env_gen);
|
bw_env_gen_reset(&instance->env_gen);
|
||||||
bw_vol_reset(&instance->vol);
|
bw_vol_reset(&instance->vol);
|
||||||
bw_env_follow_reset(&instance->env_follow);
|
bw_env_follow_reset(&instance->env_follow);
|
||||||
|
*/
|
||||||
instance->note = -1;
|
instance->note = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_synth_process(bw_example_synth instance, const float** x, float** y, int n_samples) {
|
void bw_example_synth_process(bw_example_synth instance, const float** x, float** y, int n_samples) {
|
||||||
// TODO: I was too lazy to keep track of master tune and note and only update when needed, could be improved
|
// TODO: I was too lazy to keep track of master tune and note and only update when needed, could be improved
|
||||||
if (instance->note != -1) {
|
if (instance->note != -1) {
|
||||||
bw_phase_gen_set_frequency(&instance->phase_gen,
|
bw_phase_gen_set_frequency(&instance->phase_gen_coeffs,
|
||||||
440.f * bw_pow2f_3(8.333333333333333e-2f * ((instance->note - 69) + 2.f * instance->params[p_master_tune] - 1.f)));
|
440.f * bw_pow2f_3(8.333333333333333e-2f * ((instance->note - 69) + 2.f * instance->params[p_master_tune] - 1.f)));
|
||||||
bw_env_gen_set_gate(&instance->env_gen, 1);
|
//bw_env_gen_set_gate(&instance->env_gen, 1);
|
||||||
} else
|
} else
|
||||||
bw_env_gen_set_gate(&instance->env_gen, 0);
|
;
|
||||||
|
//bw_env_gen_set_gate(&instance->env_gen, 0);
|
||||||
|
|
||||||
|
bw_phase_gen_process(&instance->phase_gen_coeffs, &instance->phase_gen_state, NULL, y[0], instance->buf, n_samples);
|
||||||
|
/*
|
||||||
for (int i = 0; i < n_samples; i += BUFFER_SIZE) {
|
for (int i = 0; i < n_samples; i += BUFFER_SIZE) {
|
||||||
float *out = y[0] + i;
|
float *out = y[0] + i;
|
||||||
const uint32_t n = bw_minu32(n_samples - i, BUFFER_SIZE);
|
const uint32_t n = bw_minu32(n_samples - i, BUFFER_SIZE);
|
||||||
@ -131,19 +152,22 @@ void bw_example_synth_process(bw_example_synth instance, const float** x, float*
|
|||||||
bw_env_follow_process(&instance->env_follow, out, instance->buf, n);
|
bw_env_follow_process(&instance->env_follow, out, instance->buf, n);
|
||||||
instance->level = instance->buf[i + n - 1];
|
instance->level = instance->buf[i + n - 1];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
instance->level = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_example_synth_set_parameter(bw_example_synth instance, int index, float value) {
|
void bw_example_synth_set_parameter(bw_example_synth instance, int index, float value) {
|
||||||
|
instance->params[index] = value;
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
/*
|
||||||
case p_volume:
|
case p_volume:
|
||||||
bw_vol_set_volume(&instance->vol, value);
|
bw_vol_set_volume(&instance->vol, value);
|
||||||
break;
|
break;
|
||||||
case p_master_tune:
|
*/
|
||||||
instance->params[p_master_tune] = value;
|
|
||||||
break;
|
|
||||||
case p_portamento:
|
case p_portamento:
|
||||||
bw_phase_gen_set_portamento_tau(&instance->phase_gen, value);
|
bw_phase_gen_set_portamento_tau(&instance->phase_gen_coeffs, value);
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
case p_pulse_width:
|
case p_pulse_width:
|
||||||
bw_osc_pulse_set_pulse_width(&instance->osc_pulse, value);
|
bw_osc_pulse_set_pulse_width(&instance->osc_pulse, value);
|
||||||
break;
|
break;
|
||||||
@ -165,6 +189,7 @@ void bw_example_synth_set_parameter(bw_example_synth instance, int index, float
|
|||||||
case p_release:
|
case p_release:
|
||||||
bw_env_gen_set_release(&instance->env_gen, value);
|
bw_env_gen_set_release(&instance->env_gen, value);
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
CC=clang
|
CC=clang
|
||||||
CFLAGS= \
|
CFLAGS= \
|
||||||
|
-D__WASM__ \
|
||||||
-I${ROOT_DIR}/../src \
|
-I${ROOT_DIR}/../src \
|
||||||
-I${ROOT_DIR}/../../common/web \
|
-I${ROOT_DIR}/../../common/web \
|
||||||
-I${ROOT_DIR}/../../../include \
|
-I${ROOT_DIR}/../../../include \
|
||||||
@ -27,14 +28,6 @@ LDFLAGS= \
|
|||||||
|
|
||||||
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
SOURCES= \
|
SOURCES= \
|
||||||
${ROOT_DIR}/../../../src/bw_phase_gen.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_osc_pulse.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_osc_filt.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_svf.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_env_gen.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_vol.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_env_follow.c \
|
|
||||||
${ROOT_DIR}/../../../src/bw_one_pole.c \
|
|
||||||
${ROOT_DIR}/../src/bw_example_synth.c \
|
${ROOT_DIR}/../src/bw_example_synth.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
|
||||||
|
@ -242,6 +242,8 @@ static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT c
|
|||||||
* Sets the current distance metric for sticky behavior.
|
* Sets the current distance metric for sticky behavior.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
|
static inline float bw_one_pole_get_y_z1(const bw_one_pole_state *BW_RESTRICT state);
|
||||||
|
|
||||||
/*** Implementation ***/
|
/*** Implementation ***/
|
||||||
|
|
||||||
/* WARNING: This part of the file is not part of the public API. Its content may
|
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||||
@ -439,6 +441,10 @@ static inline void bw_one_pole_set_sticky_mode(bw_one_pole_coeffs *BW_RESTRICT c
|
|||||||
coeffs->sticky_mode = value;
|
coeffs->sticky_mode = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float bw_one_pole_get_y_z1(const bw_one_pole_state *BW_RESTRICT state) {
|
||||||
|
return state->y_z1;
|
||||||
|
}
|
||||||
|
|
||||||
#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_math }}}
|
* requires {{{ bw_config bw_common bw_math bw_one_pole }}}
|
||||||
* description {{{
|
* description {{{
|
||||||
* Phase generator with portamento and exponential frequency modulation.
|
* Phase generator with portamento and exponential frequency modulation.
|
||||||
*
|
*
|
||||||
@ -30,7 +30,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,42 +49,52 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! api {{{
|
#include <bw_common.h>
|
||||||
* #### bw_phase_gen
|
|
||||||
* ```>>> */
|
|
||||||
typedef struct _bw_phase_gen bw_phase_gen;
|
|
||||||
/*! <<<```
|
|
||||||
* Instance object.
|
|
||||||
* >>> */
|
|
||||||
|
|
||||||
/*! ...
|
/*! api {{{
|
||||||
|
* #### bw_phase_gen_coeffs
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_phase_gen_coeffs bw_phase_gen_coeffs;
|
||||||
|
/*! <<<```
|
||||||
|
* Coefficients.
|
||||||
|
*
|
||||||
|
* ### bw_phase_gen_state
|
||||||
|
* ```>>> */
|
||||||
|
typedef struct _bw_phase_gen_state bw_phase_gen_state;
|
||||||
|
/*! <<<```
|
||||||
|
* State.
|
||||||
|
*
|
||||||
* #### bw_phase_gen_init()
|
* #### bw_phase_gen_init()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_init(bw_phase_gen *instance);
|
static inline void bw_phase_gen_init(bw_phase_gen_coeffs *BW_RESTRICT coeffs);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Initializes the `instance` object.
|
* Initializes `coeffs`.
|
||||||
* >>> */
|
*
|
||||||
|
|
||||||
/*! ...
|
|
||||||
* #### bw_phase_gen_set_sample_rate()
|
* #### bw_phase_gen_set_sample_rate()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_set_sample_rate(bw_phase_gen *instance, float sample_rate);
|
static inline void bw_phase_gen_set_sample_rate(bw_phase_gen_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_phase_gen_reset()
|
* #### bw_phase_gen_reset()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_reset(bw_phase_gen *instance);
|
static inline void bw_phase_gen_reset_state(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Resets the given `instance` to its initial state.
|
* Resets the given `state` to the initial state using the given `coeffs`.
|
||||||
* >>> */
|
* >>> */
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_reset_coeffs(bw_phase_gen_coeffs *BW_RESTRICT coeffs);
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_update_coeffs_ctrl(bw_phase_gen_coeffs *BW_RESTRICT coeffs);
|
||||||
|
static inline void bw_phase_gen_update_coeffs_audio(bw_phase_gen_coeffs *BW_RESTRICT coeffs);
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_process1(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, float *y, float *y_phase_inc);
|
||||||
|
static inline void bw_phase_gen_process1_mod(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, float x_mod, float *y, float *y_phase_inc);
|
||||||
|
|
||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_phase_gen_process()
|
* #### bw_phase_gen_process()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_process(bw_phase_gen *instance, const float *x_mod, float* y, float *y_phase_inc, int n_samples);
|
static inline void bw_phase_gen_process(bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, const float *x_mod, float* y, float *y_phase_inc, int n_samples);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Lets the given `instance` generate `n_samples` samples and puts them in
|
* Lets the given `instance` generate `n_samples` samples and puts them in
|
||||||
* the output buffer `y`.
|
* the output buffer `y`.
|
||||||
@ -98,7 +108,7 @@ void bw_phase_gen_process(bw_phase_gen *instance, const float *x_mod, float* y,
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_phase_gen_set_frequency()
|
* #### bw_phase_gen_set_frequency()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_set_frequency(bw_phase_gen *instance, float value);
|
static inline void bw_phase_gen_set_frequency(bw_phase_gen_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the base frequency to `value` (Hz) for the given `instance`.
|
* Sets the base frequency to `value` (Hz) for the given `instance`.
|
||||||
*
|
*
|
||||||
@ -108,34 +118,131 @@ void bw_phase_gen_set_frequency(bw_phase_gen *instance, float value);
|
|||||||
/*! ...
|
/*! ...
|
||||||
* #### bw_phase_gen_set_portamento_tau()
|
* #### bw_phase_gen_set_portamento_tau()
|
||||||
* ```>>> */
|
* ```>>> */
|
||||||
void bw_phase_gen_set_portamento_tau(bw_phase_gen *instance, float value);
|
static inline void bw_phase_gen_set_portamento_tau(bw_phase_gen_coeffs *BW_RESTRICT coeffs, float value);
|
||||||
/*! <<<```
|
/*! <<<```
|
||||||
* Sets the portamento time constant `value` (s) for the given `instance`.
|
* Sets the portamento time constant `value` (s) for the given `instance`.
|
||||||
*
|
*
|
||||||
* Default value: `0.f`.
|
* Default value: `0.f`.
|
||||||
* }}} */
|
* }}} */
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
struct _bw_phase_gen {
|
|
||||||
// Coefficients
|
|
||||||
float T;
|
|
||||||
|
|
||||||
float portamento_target;
|
/* WARNING: This part of the file is not part of the public API. Its content may
|
||||||
float portamento_mA1;
|
* change at any time in future versions. Please, do not use it directly. */
|
||||||
|
|
||||||
|
#include <bw_math.h>
|
||||||
|
#include <bw_one_pole.h>
|
||||||
|
|
||||||
|
struct _bw_phase_gen_coeffs {
|
||||||
|
// Sub-components
|
||||||
|
bw_one_pole_coeffs portamento_coeffs;
|
||||||
|
bw_one_pole_state portamento_state;
|
||||||
|
|
||||||
|
// Coefficients
|
||||||
|
float T;
|
||||||
|
|
||||||
|
float portamento_target;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
float frequency;
|
float frequency;
|
||||||
float portamento_tau;
|
float frequency_prev;
|
||||||
int param_changed;
|
|
||||||
|
|
||||||
// State
|
|
||||||
char first_run;
|
|
||||||
float phase;
|
|
||||||
float portamento_z1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _bw_phase_gen_state {
|
||||||
|
// State
|
||||||
|
float phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_init(bw_phase_gen_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_init(&coeffs->portamento_coeffs);
|
||||||
|
coeffs->frequency = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_set_sample_rate(bw_phase_gen_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||||
|
bw_one_pole_set_sample_rate(&coeffs->portamento_coeffs, sample_rate);
|
||||||
|
coeffs->T = 1.f / sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _bw_phase_gen_do_update_coeffs_ctrl(bw_phase_gen_coeffs *BW_RESTRICT coeffs, char force) {
|
||||||
|
bw_one_pole_update_coeffs_ctrl(&coeffs->portamento_coeffs);
|
||||||
|
if (force || coeffs->frequency != coeffs->frequency_prev) {
|
||||||
|
coeffs->portamento_target = coeffs->T * coeffs->frequency;
|
||||||
|
coeffs->frequency_prev = coeffs->frequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_reset_coeffs(bw_phase_gen_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
_bw_phase_gen_do_update_coeffs_ctrl(coeffs, 1);
|
||||||
|
bw_one_pole_set_init_val(&coeffs->portamento_coeffs, coeffs->portamento_target);
|
||||||
|
bw_one_pole_reset_coeffs(&coeffs->portamento_coeffs);
|
||||||
|
bw_one_pole_reset_state(&coeffs->portamento_coeffs, &coeffs->portamento_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_reset_state(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state) {
|
||||||
|
state->phase = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_update_coeffs_ctrl(bw_phase_gen_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
_bw_phase_gen_do_update_coeffs_ctrl(coeffs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_update_coeffs_audio(bw_phase_gen_coeffs *BW_RESTRICT coeffs) {
|
||||||
|
bw_one_pole_process1(&coeffs->portamento_coeffs, &coeffs->portamento_state, coeffs->portamento_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float _bw_phase_gen_update_phase(bw_phase_gen_state *BW_RESTRICT state, float phase_inc) {
|
||||||
|
state->phase += phase_inc;
|
||||||
|
state->phase -= bw_floorf(state->phase);
|
||||||
|
return state->phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_process1(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, float *y, float *y_phase_inc) {
|
||||||
|
*y_phase_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state);
|
||||||
|
*y = _bw_phase_gen_update_phase(state, *y_phase_inc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_process1_mod(const bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, float x_mod, float *y, float *y_phase_inc) {
|
||||||
|
*y_phase_inc = bw_one_pole_get_y_z1(&coeffs->portamento_state) * bw_pow2f_3(x_mod);
|
||||||
|
*y = _bw_phase_gen_update_phase(state, *y_phase_inc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_process(bw_phase_gen_coeffs *BW_RESTRICT coeffs, bw_phase_gen_state *BW_RESTRICT state, const float *x_mod, float* y, float *y_phase_inc, int n_samples) {
|
||||||
|
bw_phase_gen_update_coeffs_ctrl(coeffs);
|
||||||
|
if (x_mod != NULL) {
|
||||||
|
if (y_phase_inc != NULL)
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_phase_gen_update_coeffs_audio(coeffs);
|
||||||
|
bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, y_phase_inc + i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_phase_gen_update_coeffs_audio(coeffs);
|
||||||
|
float v_phase_inc;
|
||||||
|
bw_phase_gen_process1_mod(coeffs, state, x_mod[i], y + i, &v_phase_inc);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (y_phase_inc != NULL)
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_phase_gen_update_coeffs_audio(coeffs);
|
||||||
|
bw_phase_gen_process1(coeffs, state, y + i, y_phase_inc + i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (int i = 0; i < n_samples; i++) {
|
||||||
|
bw_phase_gen_update_coeffs_audio(coeffs);
|
||||||
|
float v_phase_inc;
|
||||||
|
bw_phase_gen_process1(coeffs, state, y + i, &v_phase_inc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_set_frequency(bw_phase_gen_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
|
coeffs->frequency = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bw_phase_gen_set_portamento_tau(bw_phase_gen_coeffs *BW_RESTRICT coeffs, float value) {
|
||||||
|
bw_one_pole_set_tau(&coeffs->portamento_coeffs, value);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,13 +87,7 @@ static inline void bw_svf_reset_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs);
|
|||||||
static inline void bw_svf_update_coeffs_ctrl(bw_svf_coeffs *BW_RESTRICT coeffs);
|
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);
|
static inline void bw_svf_update_coeffs_audio(bw_svf_coeffs *BW_RESTRICT coeffs);
|
||||||
|
|
||||||
static inline float bw_svf_process1_lp(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x);
|
static inline void bw_svf_process1(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp, float *y_hp);
|
||||||
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()
|
||||||
@ -154,9 +148,6 @@ struct _bw_svf_coeffs {
|
|||||||
// Parameters
|
// Parameters
|
||||||
float cutoff;
|
float cutoff;
|
||||||
float Q;
|
float Q;
|
||||||
|
|
||||||
float cutoff_cur;
|
|
||||||
float Q_cur;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _bw_svf_state {
|
struct _bw_svf_state {
|
||||||
@ -184,16 +175,18 @@ static inline void bw_svf_set_sample_rate(bw_svf_coeffs *BW_RESTRICT coeffs, flo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void _bw_svf_do_update_coeffs(bw_svf_coeffs *BW_RESTRICT coeffs, char force) {
|
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;
|
float cutoff_cur = bw_one_pole_get_y_z1(&coeffs->smooth_cutoff_state);
|
||||||
const char Q_changed = force || coeffs->Q != coeffs->Q_cur;
|
float Q_cur = bw_one_pole_get_y_z1(&coeffs->smooth_Q_state);
|
||||||
|
const char cutoff_changed = force || coeffs->cutoff != cutoff_cur;
|
||||||
|
const char Q_changed = force || coeffs->Q != Q_cur;
|
||||||
if (cutoff_changed || Q_changed) {
|
if (cutoff_changed || Q_changed) {
|
||||||
if (cutoff_changed) {
|
if (cutoff_changed) {
|
||||||
coeffs->cutoff_cur = bw_one_pole_process1_sticky_rel(&coeffs->smooth_cutoff_coeffs, &coeffs->smooth_cutoff_state, coeffs->cutoff);
|
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);
|
coeffs->t = bw_tanf_3(coeffs->t_k * cutoff_cur);
|
||||||
}
|
}
|
||||||
if (Q_changed) {
|
if (Q_changed) {
|
||||||
coeffs->Q_cur = bw_one_pole_process1_sticky_abs(&coeffs->smooth_Q_coeffs, &coeffs->smooth_Q_state, coeffs->Q);
|
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);
|
coeffs->k = bw_rcpf_2(Q_cur);
|
||||||
}
|
}
|
||||||
const float kpt = coeffs->k + coeffs->t;
|
const float kpt = coeffs->k + coeffs->t;
|
||||||
coeffs->hp_hp_z1 = coeffs->t * kpt;
|
coeffs->hp_hp_z1 = coeffs->t * kpt;
|
||||||
@ -225,46 +218,7 @@ static inline void bw_svf_update_coeffs_audio(bw_svf_coeffs *BW_RESTRICT coeffs)
|
|||||||
_bw_svf_do_update_coeffs(coeffs, 0);
|
_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) {
|
static inline void bw_svf_process1(const bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_state *BW_RESTRICT state, float x, float *y_lp, float *y_bp, float *y_hp) {
|
||||||
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_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_bp = state->bp_z1 - coeffs->t * (*y_hp + state->hp_z1);
|
||||||
*y_lp = state->lp_z1 - coeffs->t * (*y_bp + state->bp_z1);
|
*y_lp = state->lp_z1 - coeffs->t * (*y_bp + state->bp_z1);
|
||||||
@ -280,24 +234,27 @@ static inline void bw_svf_process(bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_stat
|
|||||||
if (y_hp != NULL) {
|
if (y_hp != NULL) {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
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);
|
bw_svf_process1(coeffs, state, x[i], y_lp + i, y_bp + i, y_hp + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
bw_svf_process1_lp_bp(coeffs, state, x[i], y_lp + i, y_bp + i);
|
float v_lp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], &v_lp, y_bp + i, y_hp + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (y_hp != NULL) {
|
if (y_hp != NULL) {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
bw_svf_process1_lp_hp(coeffs, state, x[i], y_lp + i, y_hp + i);
|
float v_bp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], y_lp + i, &v_bp, y_hp + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
y_lp[i] = bw_svf_process1_lp(coeffs, state, x[i]);
|
float v_bp, v_hp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], y_lp + i, &v_bp, &v_hp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,24 +263,28 @@ static inline void bw_svf_process(bw_svf_coeffs *BW_RESTRICT coeffs, bw_svf_stat
|
|||||||
if (y_hp != NULL) {
|
if (y_hp != NULL) {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
bw_svf_process1_bp_hp(coeffs, state, x[i], y_bp + i, y_hp + i);
|
float v_lp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], &v_lp, y_bp + i, y_hp + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
y_bp[i] = bw_svf_process1_bp(coeffs, state, x[i]);
|
float v_lp, v_hp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], &v_lp, y_bp + i, &v_hp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (y_hp != NULL) {
|
if (y_hp != NULL) {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
y_hp[i] = bw_svf_process1_hp(coeffs, state, x[i]);
|
float v_lp, v_bp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], &v_lp, &v_bp, y_hp + i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < n_samples; i++) {
|
for (int i = 0; i < n_samples; i++) {
|
||||||
bw_svf_update_coeffs_audio(coeffs);
|
bw_svf_update_coeffs_audio(coeffs);
|
||||||
const float v = bw_svf_process1_lp(coeffs, state, x[i]);
|
float v_lp, v_bp, v_hp;
|
||||||
|
bw_svf_process1(coeffs, state, x[i], &v_lp, &v_bp, &v_hp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,9 @@ static inline void bw_wah_update_coeffs_audio(bw_wah_coeffs *BW_RESTRICT coeffs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline float bw_wah_process1(const bw_wah_coeffs *BW_RESTRICT coeffs, bw_wah_state *BW_RESTRICT state, float x) {
|
static inline float bw_wah_process1(const bw_wah_coeffs *BW_RESTRICT coeffs, bw_wah_state *BW_RESTRICT state, float x) {
|
||||||
return bw_svf_process1_bp(&coeffs->svf_coeffs, &state->svf_state, x);
|
float v_lp, v_hp, v_bp;
|
||||||
|
bw_svf_process1(&coeffs->svf_coeffs, &state->svf_state, x, &v_lp, &v_bp, &v_hp);
|
||||||
|
return v_lp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bw_wah_process(bw_wah_coeffs *BW_RESTRICT coeffs, bw_wah_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
static inline void bw_wah_process(bw_wah_coeffs *BW_RESTRICT coeffs, bw_wah_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
|
||||||
|
@ -1,95 +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_phase_gen.h>
|
|
||||||
|
|
||||||
#include <bw_math.h>
|
|
||||||
|
|
||||||
void bw_phase_gen_init(bw_phase_gen *instance) {
|
|
||||||
instance->frequency = 1.f;
|
|
||||||
instance->portamento_tau = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_phase_gen_set_sample_rate(bw_phase_gen *instance, float sample_rate) {
|
|
||||||
instance->T = 1.f / sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_phase_gen_reset(bw_phase_gen *instance) {
|
|
||||||
instance->first_run = 1;
|
|
||||||
instance->param_changed = ~0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PARAM_FREQUENCY 1
|
|
||||||
#define PARAM_PORTAMENTO_TAU (1<<1)
|
|
||||||
|
|
||||||
void bw_phase_gen_process(bw_phase_gen *instance, const float *x_mod, float* y, float *y_phase_inc, int n_samples) {
|
|
||||||
if (instance->param_changed) {
|
|
||||||
if (instance->param_changed & PARAM_FREQUENCY)
|
|
||||||
instance->portamento_target = instance->T * instance->frequency;
|
|
||||||
if (instance->param_changed & PARAM_PORTAMENTO_TAU)
|
|
||||||
instance->portamento_mA1 = bw_expf_3(-instance->T * bw_rcpf_2(instance->portamento_tau));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->first_run) {
|
|
||||||
instance->phase = 0.f;
|
|
||||||
instance->portamento_z1 = instance->portamento_target;
|
|
||||||
instance->first_run = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y_phase_inc == NULL)
|
|
||||||
y_phase_inc = y;
|
|
||||||
|
|
||||||
if (x_mod != NULL)
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float portamento = instance->portamento_target + instance->portamento_mA1 * (instance->portamento_z1 - instance->portamento_target);
|
|
||||||
instance->portamento_z1 = portamento;
|
|
||||||
|
|
||||||
const float phase_inc = portamento * bw_pow2f_3(x_mod[i]);
|
|
||||||
instance->phase += phase_inc;
|
|
||||||
instance->phase -= bw_floorf(instance->phase);
|
|
||||||
|
|
||||||
y_phase_inc[i] = phase_inc;
|
|
||||||
y[i] = instance->phase;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for (int i = 0; i < n_samples; i++) {
|
|
||||||
const float portamento = instance->portamento_target + instance->portamento_mA1 * (instance->portamento_z1 - instance->portamento_target);
|
|
||||||
instance->portamento_z1 = portamento;
|
|
||||||
|
|
||||||
instance->phase += portamento;
|
|
||||||
instance->phase -= bw_floorf(instance->phase);
|
|
||||||
|
|
||||||
y_phase_inc[i] = portamento;
|
|
||||||
y[i] = instance->phase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_phase_gen_set_frequency(bw_phase_gen *instance, float value) {
|
|
||||||
if (instance->frequency != value) {
|
|
||||||
instance->frequency = value;
|
|
||||||
instance->param_changed |= PARAM_FREQUENCY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bw_phase_gen_set_portamento_tau(bw_phase_gen *instance, float value) {
|
|
||||||
if (instance->portamento_tau != value) {
|
|
||||||
instance->portamento_tau = value;
|
|
||||||
instance->param_changed |= PARAM_PORTAMENTO_TAU;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user