bw_reverb WIP (broken)

This commit is contained in:
Stefano D'Angelo 2023-06-01 17:41:05 +02:00
parent 5d988b0c05
commit 1b6cb5a029
2 changed files with 165 additions and 6 deletions

1
TODO
View File

@ -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

View File

@ -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) {