custom prewarping in bw_mm2 + using it in bw_{l,h}s2 + fix doc in bw_mm1

This commit is contained in:
Stefano D'Angelo 2023-01-13 12:18:36 +01:00
parent 87cb193a48
commit 3254074efc
4 changed files with 81 additions and 22 deletions

View File

@ -186,9 +186,11 @@ struct _bw_hs2_coeffs {
// Coefficients
float sg;
float isg;
float ssg;
// Parameters
float high_gain;
float cutoff;
float Q;
float slope;
char use_slope;
@ -200,12 +202,15 @@ struct _bw_hs2_state {
};
#define _BW_HS2_PARAM_HIGH_GAIN 1
#define _BW_HS2_PARAM_Q (1<<1)
#define _BW_HS2_PARAM_SLOPE (1<<2)
#define _BW_HS2_PARAM_CUTOFF (1<<1)
#define _BW_HS2_PARAM_Q (1<<2)
#define _BW_HS2_PARAM_SLOPE (1<<3)
static inline void bw_hs2_init(bw_hs2_coeffs *BW_RESTRICT coeffs) {
bw_mm2_init(&coeffs->mm2_coeffs);
bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0);
coeffs->high_gain = 1.f;
coeffs->cutoff = 1e3f;
coeffs->Q = 0.5f;
coeffs->slope = 0.5f;
coeffs->use_slope = 1;
@ -217,15 +222,21 @@ static inline void bw_hs2_set_sample_rate(bw_hs2_coeffs *BW_RESTRICT coeffs, flo
static inline void _bw_hs2_update_mm2_params(bw_ls1_coeffs *BW_RESTRICT coeffs) {
if (coeffs->param_changed) {
if (coeffs->param_changed & _BW_HS2_PARAM_HIGH_GAIN) {
coeffs->sg = bw_math_sqrtf_2(coeffs->high_gain);
coeffs->isg = bw_rcpf_2(coeffs->sg);
bw_mm2_set_coeff_x(&coeffs->mm2_coeffs, coeffs->sg);
bw_mm2_set_coeff_lp(&coeffs->mm2_coeffs, 1.f - coeffs->sg);
bw_mm2_set_coeff_hp(&coeffs->mm2_coeffs, coeffs->high_gain - coeffs->sg);
if (coeffs->param_changed & (_BW_HS2_PARAM_DC_GAIN | _BW_HS2_PARAM_CUTOFF)) {
if (coeffs->param_changed & _BW_HS2_PARAM_DC_GAIN) {
coeffs->sg = bw_sqrtf_2(coeffs->high_gain);
coeffs->isg = bw_rcpf_2(coeffs->sg);
coeffs->ssg = bw_sqrtf_2(coeffs->sg);
bw_mm2_set_coeff_x(&coeffs->mm2_coeffs, coeffs->sg);
bw_mm2_set_coeff_lp(&coeffs->mm2_coeffs, 1.f - coeffs->sg);
bw_mm2_set_coeff_hp(&coeffs->mm2_coeffs, coeffs->high_gain - coeffs->sg);
}
if (coeffs->param_changed & _BW_HS2_PARAM_CUTOFF)
bw_mm2_set_prewarp_freq(&coeffs->mm2_coeffs, coeffs->cutoff);
bw_mm2_set_cutoff(&coeffs->mm2_coeffs, coeffs->cutoff * coeffs->ssg);
}
if (coeffs->use_slope) {
if (coeffs->param_changed & _BW_HS2_PARAM_SLOPE) {
if (coeffs->param_changed & (_BW_HS2_PARAM_DC_GAIN | _BW_HS2_PARAM_SLOPE)) {
const float k = coeffs->sg + coeffs->isg;
bw_mm2_set_Q(&coeffs->mm2_coeffs, bw_sqrtf_2(coeffs->slope * bw_rcpf_2(coeffs->slope + coeffs->slope + k - k * coeffs->slope)));
}
@ -270,7 +281,10 @@ static inline void bw_hs2_process(bw_hs2_coeffs *BW_RESTRICT coeffs, bw_hs2_stat
}
static inline void bw_hs2_set_cutoff(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) {
bw_mm2_set_cutoff(&coeffs->mm2_coeffs, value);
if (coeffs->cutoff) {
coeffs->cutoff = value;
coeffs->param_changed |= _BW_HS2_PARAM_CUTOFF;
}
}
static inline void bw_hs2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) {
@ -306,6 +320,7 @@ static inline void bw_hs2_set_use_slope(bw_mm2_coeffs *BW_RESTRICT coeffs, char
}
#undef _BW_HS2_PARAM_HIGH_GAIN
#undef _BW_HS2_PARAM_CUTOFF
#undef _BW_HS2_PARAM_Q
#undef _BW_HS2_PARAM_SLOPE

View File

@ -185,9 +185,11 @@ struct _bw_ls2_coeffs {
// Coefficients
float sg;
float isg;
float issg;
// Parameters
float dc_gain;
float cutoff;
float Q;
float slope;
char use_slope;
@ -199,12 +201,15 @@ struct _bw_ls2_state {
};
#define _BW_LS2_PARAM_DC_GAIN 1
#define _BW_LS2_PARAM_Q (1<<1)
#define _BW_LS2_PARAM_SLOPE (1<<2)
#define _BW_LS2_PARAM_CUTOFF (1<<1)
#define _BW_LS2_PARAM_Q (1<<2)
#define _BW_LS2_PARAM_SLOPE (1<<3)
static inline void bw_ls2_init(bw_ls2_coeffs *BW_RESTRICT coeffs) {
bw_mm2_init(&coeffs->mm2_coeffs);
bw_mm2_set_prewarp_at_cutoff(&coeffs->mm2_coeffs, 0);
coeffs->dc_gain = 1.f;
coeffs->cutoff = 1e3f;
coeffs->Q = 0.5f;
coeffs->slope = 0.5f;
coeffs->use_slope = 1;
@ -216,15 +221,21 @@ static inline void bw_ls2_set_sample_rate(bw_ls2_coeffs *BW_RESTRICT coeffs, flo
static inline void _bw_ls2_update_mm2_params(bw_ls1_coeffs *BW_RESTRICT coeffs) {
if (coeffs->param_changed) {
if (coeffs->param_changed & _BW_LS2_PARAM_DC_GAIN) {
coeffs->sg = bw_math_sqrtf_2(coeffs->dc_gain);
coeffs->isg = bw_rcpf_2(coeffs->sg);
bw_mm2_set_coeff_x(&coeffs->mm2_coeffs, coeffs->sg);
bw_mm2_set_coeff_lp(&coeffs->mm2_coeffs, 1.f - coeffs->isg);
bw_mm2_set_coeff_hp(&coeffs->mm2_coeffs, 1.f - sg);
if (coeffs->param_changed & (_BW_LS2_PARAM_DC_GAIN | _BW_LS2_PARAM_CUTOFF)) {
if (coeffs->param_changed & _BW_LS2_PARAM_DC_GAIN) {
coeffs->sg = bw_sqrtf_2(coeffs->dc_gain);
coeffs->isg = bw_rcpf_2(coeffs->sg);
coeffs->issg = bw_sqrtf_2(coeffs->isg);
bw_mm2_set_coeff_x(&coeffs->mm2_coeffs, coeffs->sg);
bw_mm2_set_coeff_lp(&coeffs->mm2_coeffs, coeffs->dc_gain - coeffs->sg);
bw_mm2_set_coeff_hp(&coeffs->mm2_coeffs, 1.f - coeffs->sg);
}
if (coeffs->param_changed & _BW_LS2_PARAM_CUTOFF)
bw_mm2_set_prewarp_freq(&coeffs->mm2_coeffs, coeffs->cutoff);
bw_mm2_set_cutoff(&coeffs->mm2_coeffs, coeffs->cutoff * coeffs->issg);
}
if (coeffs->use_slope) {
if (coeffs->param_changed & _BW_LS2_PARAM_SLOPE) {
if (coeffs->param_changed & (_BW_LS2_PARAM_DC_GAIN | _BW_LS2_PARAM_SLOPE)) {
const float k = coeffs->sg + coeffs->isg;
bw_mm2_set_Q(&coeffs->mm2_coeffs, bw_sqrtf_2(coeffs->slope * bw_rcpf_2(coeffs->slope + coeffs->slope + k - k * coeffs->slope)));
}
@ -269,7 +280,10 @@ static inline void bw_ls2_process(bw_ls2_coeffs *BW_RESTRICT coeffs, bw_ls2_stat
}
static inline void bw_ls2_set_cutoff(bw_ls2_coeffs *BW_RESTRICT coeffs, float value) {
bw_mm2_set_cutoff(&coeffs->mm2_coeffs, value);
if (coeffs->cutoff != value) {
coeffs->cutoff = value;
coeffs->param_changed |= _BW_LS2_PARAM_CUTOFF;
}
}
static inline void bw_ls2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) {
@ -305,6 +319,7 @@ static inline void bw_ls2_set_use_slope(bw_mm2_coeffs *BW_RESTRICT coeffs, char
}
#undef _BW_LS2_PARAM_DC_GAIN
#undef _BW_LS2_PARAM_CUTOFF
#undef _BW_LS2_PARAM_Q
#undef _BW_LS2_PARAM_SLOPE

View File

@ -1,7 +1,7 @@
/*
* Brickworks
*
* Copyright (C) 2022 Orastron Srl unipersonale
* Copyright (C) 2022, 2023 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
@ -134,6 +134,8 @@ static inline void bw_mm1_set_prewarp_freq(bw_mm1_coeffs *BW_RESTRICT coeffs, fl
*
* Only used when the prewarp\_at\_cutoff parameter is off.
*
* Default value: `1e3f`.
*
* #### bw_mm1_set_coeff_x()
* ```>>> */
static inline void bw_mm1_set_coeff_x(bw_mm1_coeffs *BW_RESTRICT coeffs, float value);

View File

@ -1,7 +1,7 @@
/*
* Brickworks
*
* Copyright (C) 2022 Orastron Srl unipersonale
* Copyright (C) 2022, 2023 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
@ -127,6 +127,25 @@ static inline void bw_mm2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value);
*
* Default value: `0.5f`.
*
* #### bw_mm2_set_prewarp_at_cutoff()
* ```>>> */
static inline void bw_mm2_set_prewarp_at_cutoff(bw_mm2_coeffs *BW_RESTRICT coeffs, char value);
/*! <<<```
* Sets whether bilinear transform prewarping frequency should match the
* cutoff frequency (non-`0`) or not (`0`).
*
* Default value: non-`0` (on).
*
* #### bw_mm2_set_prewarp_freq()
* ```>>> */
static inline void bw_mm2_set_prewarp_freq(bw_mm2_coeffs *BW_RESTRICT coeffs, float value);
/*! <<<```
* Sets the prewarping frequency `value` (Hz) in `coeffs`.
*
* Only used when the prewarp\_at\_cutoff parameter is off.
*
* Default value: `1e3f`.
*
* #### bw_mm2_set_coeff_x()
* ```>>> */
static inline void bw_mm2_set_coeff_x(bw_mm2_coeffs *BW_RESTRICT coeffs, float value);
@ -259,6 +278,14 @@ static inline void bw_mm2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value)
bw_svf_set_Q(&coeffs->svf_coeffs, value);
}
static inline void bw_mm2_set_prewarp_at_cutoff(bw_mm2_coeffs *BW_RESTRICT coeffs, char value) {
bw_svf_set_prewarp_at_cutoff(&coeffs->svf_coeffs, value);
}
static inline void bw_mm2_set_prewarp_freq(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) {
bw_svf_set_prewarp_freq(&coeffs->svf_coeffs, value);
}
static inline void bw_mm2_set_coeff_x(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) {
bw_gain_set_gain_lin(&coeffs->gain_x_coeffs, value);
}