diff --git a/include/bw_hs2.h b/include/bw_hs2.h index 95a4bce..736e998 100644 --- a/include/bw_hs2.h +++ b/include/bw_hs2.h @@ -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 diff --git a/include/bw_ls2.h b/include/bw_ls2.h index 72da079..c7f9bca 100644 --- a/include/bw_ls2.h +++ b/include/bw_ls2.h @@ -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 diff --git a/include/bw_mm1.h b/include/bw_mm1.h index a6ebde8..0d39914 100644 --- a/include/bw_mm1.h +++ b/include/bw_mm1.h @@ -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); diff --git a/include/bw_mm2.h b/include/bw_mm2.h index ddb097c..72de5fb 100644 --- a/include/bw_mm2.h +++ b/include/bw_mm2.h @@ -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); }