bw_reverb WIP (broken)
This commit is contained in:
parent
5d988b0c05
commit
1b6cb5a029
1
TODO
1
TODO
@ -45,6 +45,7 @@ code:
|
||||
* bw_fuzz gain compensation?
|
||||
* remove union value = {.f = v};? (std c++ latest)
|
||||
* make gain of distortions homogeneous?
|
||||
* max_delay -> set sample rate? see reverb
|
||||
|
||||
build system:
|
||||
* make makefiles handle paths with spaces etc
|
||||
|
@ -22,7 +22,8 @@
|
||||
* module_type {{{ dsp }}}
|
||||
* version {{{ 0.5.0 }}}
|
||||
* requires {{{
|
||||
* bw_buf bw_common bw_config bw_delay bw_drywet bw_gain bw_math bw_one_pole
|
||||
* bw_buf bw_common bw_config bw_delay bw_drywet bw_gain bw_lp1 bw_math
|
||||
* bw_one_pole
|
||||
* }}}
|
||||
* description {{{
|
||||
* Stereo reverb.
|
||||
@ -180,61 +181,217 @@ static inline void bw_reverb_set_wet(bw_reverb_coeffs *BW_RESTRICT coeffs, float
|
||||
* change at any time in future versions. Please, do not use it directly. */
|
||||
|
||||
#include <bw_delay.h>
|
||||
#include <bw_lp1.h>
|
||||
#include <bw_drywet.h>
|
||||
#include <bw_one_pole.h>
|
||||
#include <bw_math.h>
|
||||
|
||||
struct _bw_reverb_coeffs {
|
||||
// Sub-components
|
||||
bw_delay_coeffs predelay_coeffs;
|
||||
bw_lp1_coeffs bandwidth_coeffs;
|
||||
bw_delay_coeffs delay_id1_coeffs;
|
||||
bw_delay_coeffs delay_id2_coeffs;
|
||||
bw_delay_coeffs delay_id3_coeffs;
|
||||
bw_delay_coeffs delay_id4_coeffs;
|
||||
bw_delay_coeffs delay_dd1_coeffs;
|
||||
bw_delay_coeffs delay_dd2_coeffs;
|
||||
bw_delay_coeffs delay_dd3_coeffs;
|
||||
bw_delay_coeffs delay_dd4_coeffs;
|
||||
bw_delay_coeffs delay_d1_coeffs;
|
||||
bw_delay_coeffs delay_d2_coeffs;
|
||||
bw_delay_coeffs delay_d3_coeffs;
|
||||
bw_delay_coeffs delay_d4_coeffs;
|
||||
bw_drywet_coeffs drywet_coeffs;
|
||||
bw_one_pole_coeffs smooth_coeffs;
|
||||
bw_one_pole_state smooth_predelay_state;
|
||||
|
||||
// Coefficients
|
||||
float fs;
|
||||
float T;
|
||||
BW_SIZE_T id1;
|
||||
BW_SIZE_T id2;
|
||||
BW_SIZE_T id3;
|
||||
BW_SIZE_T id4;
|
||||
BW_SIZE_T dd2;
|
||||
BW_SIZE_T dd4;
|
||||
BW_SIZE_T d1;
|
||||
BW_SIZE_T d2;
|
||||
BW_SIZE_T d3;
|
||||
BW_SIZE_T d4;
|
||||
|
||||
// Parameters
|
||||
float predelay;
|
||||
};
|
||||
|
||||
struct _bw_reverb_state {
|
||||
bw_delay_state predelay_state;
|
||||
bw_lp1_state bandwidth_state;
|
||||
};
|
||||
|
||||
static inline void bw_reverb_init(bw_reverb_coeffs *BW_RESTRICT coeffs) {
|
||||
bw_delay_init(&coeffs->predelay_coeffs, 0.1f);
|
||||
bw_lp1_init(&coeffs->bandwidth_coeffs);
|
||||
bw_delay_init(&coeffs->delay_id1_coeffs, 142.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_id2_coeffs, 107.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_id3_coeffs, 379.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_id4_coeffs, 277.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_dd1_coeffs, (672.f + 16.f) / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_dd2_coeffs, 1800.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_dd3_coeffs, (908.f + 16.f) / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_dd4_coeffs, 2656.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_d1_coeffs, 4453.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_d2_coeffs, 3720.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_d3_coeffs, 4217.f / 29761.f);
|
||||
bw_delay_init(&coeffs->delay_d4_coeffs, 3163.f / 29761.f);
|
||||
bw_drywet_init(&coeffs->drywet_coeffs);
|
||||
bw_one_pole_init(&coeffs->smooth_coeffs);
|
||||
|
||||
bw_lp1_set_cutoff(&coeffs->bandwidth_coeffs, 20e3f);
|
||||
bw_drywet_set_wet(&coeffs->drywet_coeffs, 0.5f);
|
||||
bw_one_pole_set_tau(&coeffs->smooth_coeffs, 0.05f);
|
||||
bw_one_pole_set_sticky_thresh(&coeffs->smooth_coeffs, 1e-6f);
|
||||
|
||||
coeffs->predelay = 0.f;
|
||||
}
|
||||
|
||||
static inline void bw_reverb_set_sample_rate(bw_reverb_coeffs *BW_RESTRICT coeffs, float sample_rate) {
|
||||
bw_delay_set_sample_rate(&coeffs->predelay_coeffs, sample_rate);
|
||||
bw_lp1_set_sample_rate(&coeffs->bandwidth_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_id1_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_id2_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_id3_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_id4_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_dd1_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_dd2_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_dd3_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_dd4_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_d1_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_d2_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_d3_coeffs, sample_rate);
|
||||
bw_delay_set_sample_rate(&coeffs->delay_d4_coeffs, sample_rate);
|
||||
bw_drywet_set_sample_rate(&coeffs->drywet_coeffs, sample_rate);
|
||||
bw_one_pole_set_sample_rate(&coeffs->smooth_coeffs, sample_rate);
|
||||
bw_one_pole_reset_coeffs(&coeffs->smooth_coeffs);
|
||||
coeffs->fs = sample_rate;
|
||||
coeffs->T = 1.f / sample_rate;
|
||||
coeffs->id1 = (BW_SIZE_T)bw_roundf(coeffs->fs * (142.f / 29761.f));
|
||||
coeffs->id2 = (BW_SIZE_T)bw_roundf(coeffs->fs * (107.f / 29761.f));
|
||||
coeffs->id3 = (BW_SIZE_T)bw_roundf(coeffs->fs * (379.f / 29761.f));
|
||||
coeffs->id4 = (BW_SIZE_T)bw_roundf(coeffs->fs * (277.f / 29761.f));
|
||||
coeffs->dd2 = (BW_SIZE_T)bw_roundf(coeffs->fs * (1800.f / 29761.f));
|
||||
coeffs->dd4 = (BW_SIZE_T)bw_roundf(coeffs->fs * (2656.f / 29761.f));
|
||||
coeffs->d1 = (BW_SIZE_T)bw_roundf(coeffs->fs * (4453.f / 29761.f));
|
||||
coeffs->d2 = (BW_SIZE_T)bw_roundf(coeffs->fs * (3720.f / 29761.f));
|
||||
coeffs->d3 = (BW_SIZE_T)bw_roundf(coeffs->fs * (4217.f / 29761.f));
|
||||
coeffs->d4 = (BW_SIZE_T)bw_roundf(coeffs->fs * (3163.f / 29761.f));
|
||||
//set delay...
|
||||
}
|
||||
|
||||
static inline BW_SIZE_T bw_reverb_mem_req(bw_reverb_coeffs *BW_RESTRICT coeffs) {
|
||||
return bw_delay_mem_req(&coeffs->predelay_coeffs);
|
||||
return bw_delay_mem_req(&coeffs->predelay_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_id1_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_id2_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_id3_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_id4_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_dd1_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_dd2_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_dd3_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_dd4_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_d1_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_d2_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_d3_coeffs)
|
||||
+ bw_delay_mem_req(&coeffs->delay_d4_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_mem_set(bw_reverb_state *BW_RESTRICT state, void *mem) {
|
||||
bw_delay_mem_set(&state->predelay_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->predelay_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_id1_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_id1_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_id2_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_id2_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_id3_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_id3_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_id4_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_id4_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_dd1_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_dd1_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_dd2_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_dd2_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_dd3_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_dd3_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_dd4_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_dd4_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_d1_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_d1_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_d2_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_d2_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_d3_state, mem);
|
||||
mem += bw_delay_mem_req(&coeffs->delay_d3_coeffs) * sizeof(float);
|
||||
bw_delay_mem_set(&state->delay_d4_state, mem);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_reset_coeffs(bw_reverb_coeffs *BW_RESTRICT coeffs) {
|
||||
bw_delay_reset_coeffs(&coeffs->predelay_coeffs);
|
||||
bw_lp1_reset_coeffs(&coeffs->bandwidth_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_id1_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_id2_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_id3_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_id4_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_dd1_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_dd2_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_dd3_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_dd4_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_d1_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_d2_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_d3_coeffs);
|
||||
bw_delay_reset_coeffs(&coeffs->delay_d4_coeffs);
|
||||
bw_drywet_reset_coeffs(&coeffs->drywet_coeffs);
|
||||
bw_reverb_set_predelay(coeffs, coeffs->predelay); // to get it rounded
|
||||
bw_one_pole_reset_state(&coeffs->smooth_coeffs, &coeffs->smooth_predelay_state, coeffs->predelay);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_reset_state(const bw_reverb_coeffs *BW_RESTRICT coeffs, bw_reverb_state *BW_RESTRICT state) {
|
||||
bw_delay_reset_state(&coeffs->predelay_coeffs, &state->predelay_state);
|
||||
bw_lp1_reset_state(&coeffs->bandwidth_coeffs, &state->bandwidth_state, 0.f);
|
||||
bw_delay_reset_state(&coeffs->delay_id1_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_id2_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_id3_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_id4_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_dd1_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_dd2_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_dd3_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_dd4_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_d1_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_d2_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_d3_coeffs, &state->predelay_state);
|
||||
bw_delay_reset_state(&coeffs->delay_d4_coeffs, &state->predelay_state);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_update_coeffs_ctrl(bw_reverb_coeffs *BW_RESTRICT coeffs) {
|
||||
bw_delay_update_coeffs_ctrl(&coeffs->predelay_coeffs);
|
||||
bw_drywet_update_coeffs_ctrl(&coeffs->drywet_coeffs);
|
||||
bw_lp1_update_coeffs_ctrl(&coeffs->bandwidth_coeffs);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_update_coeffs_audio(bw_reverb_coeffs *BW_RESTRICT coeffs) {
|
||||
bw_delay_update_coeffs_audio(&coeffs->predelay_coeffs);
|
||||
bw_lp1_update_coeffs_audio(&coeffs->bandwidth_coeffs);
|
||||
bw_drywet_update_coeffs_audio(&coeffs->drywet_coeffs);
|
||||
const float pd = bw_one_pole_process1_sticky_abs(&coeffs->smooth_coeffs, &coeffs->smooth_predelay_state, coeffs->predelay);
|
||||
bw_delay_set_delay(&coeffs->predelay_coeffs, pd);
|
||||
bw_delay_update_coeffs_ctrl(&coeffs->predelay_coeffs);
|
||||
bw_delay_update_coeffs_audio(&coeffs->predelay_coeffs);
|
||||
//...
|
||||
}
|
||||
|
||||
static inline void bw_reverb_process1(const bw_reverb_coeffs *BW_RESTRICT coeffs, bw_reverb_state *BW_RESTRICT state, float xl, float xr, float *yl, float *yr) {
|
||||
const float i = 0.5f * (xl + xr);
|
||||
const float pd = bw_delay_process1(&coeffs->predelay_coeffs, &state->predelay_state, i);
|
||||
*yl = bw_drywet_process1(&coeffs->drywet_coeffs, xl, pd);
|
||||
*yr = bw_drywet_process1(&coeffs->drywet_coeffs, xr, pd);
|
||||
const float bw = bw_lp1_process1(&coeffs->bandwidth_coeffs, &state->bandwidth_state, pd);
|
||||
//...
|
||||
*yl = bw_drywet_process1(&coeffs->drywet_coeffs, xl, bw);
|
||||
*yr = bw_drywet_process1(&coeffs->drywet_coeffs, xr, bw);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_process(bw_reverb_coeffs *BW_RESTRICT coeffs, bw_reverb_state *BW_RESTRICT state, const float *xl, const float *xr, float *yl, float *yr, int n_samples) {
|
||||
@ -246,10 +403,11 @@ static inline void bw_reverb_process(bw_reverb_coeffs *BW_RESTRICT coeffs, bw_re
|
||||
}
|
||||
|
||||
static inline void bw_reverb_set_predelay(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
bw_delay_set_delay(&coeffs->predelay_coeffs, value);
|
||||
coeffs->predelay = coeffs->T * bw_roundf(coeffs->fs * value);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_set_bandwidth(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
bw_lp1_set_cutoff(&coeffs->bandwidth_coeffs, value);
|
||||
}
|
||||
|
||||
static inline void bw_reverb_set_damping(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) {
|
||||
|
Loading…
Reference in New Issue
Block a user