diff --git a/README.md b/README.md index 04ddfd6..7c79a17 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You can find information and documentation [on the official web page](https://ww ## Legal -Copyright (C) 2021, 2022 Orastron Srl unipersonale. +Copyright (C) 2021-2023 Orastron Srl unipersonale. Authors: Stefano D'Angelo, Paolo Marrone. diff --git a/TODO b/TODO index b9fcc4a..5557060 100644 --- a/TODO +++ b/TODO @@ -20,6 +20,7 @@ code: * avoid "force" in coeffs update by using inline functions? * should rather use backward Euler in bw_onepole? * Q to slope and viceversa functions in 2nd order shelf filters? keep updated values (seamless switch, syncrhonicity)? +* treat unused variable/function warnings build system: * make makefiles handle paths with spaces etc diff --git a/include/bw_hs2.h b/include/bw_hs2.h index 7a6343e..bdc408f 100644 --- a/include/bw_hs2.h +++ b/include/bw_hs2.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 @@ -135,19 +135,21 @@ static inline void bw_hs2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value); * * Default value: `0.5f`. * - * #### bw_hs2_set_dc_gain_lin() + * #### bw_hs2_set_high_gain_lin() * ```>>> */ -static inline void bw_hs2_set_dc_gain_lin(bw_hs2_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_hs2_set_high_gain_lin(bw_hs2_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` - * Sets the dc gain parameter to the given `value` (linear gain) in `coeffs`. + * Sets the high-frequency gain parameter to the given `value` (linear gain) + * in `coeffs`. * * Default value: `0.f`. * - * #### bw_hs2_set_dc_gain_dB() + * #### bw_hs2_set_high_gain_dB() * ```>>> */ -static inline void bw_hs2_set_dc_gain_dB(bw_hs2_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_hs2_set_high_gain_dB(bw_hs2_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` - * Sets the dc gain parameter to the given `value` (dB) in `coeffs`. + * Sets the high-frequency gain parameter to the given `value` (dB) in + * `coeffs`. * * Default value: `-INFINITY`. * @@ -186,7 +188,7 @@ struct _bw_hs2_coeffs { float isg; // Parameters - float gain; + float high_gain; float Q; float slope; char use_slope; @@ -197,13 +199,13 @@ struct _bw_hs2_state { bw_mm2_state mm2_state; }; -#define _BW_HS2_PARAM_GAIN 1 +#define _BW_HS2_PARAM_HIGH_GAIN 1 #define _BW_HS2_PARAM_Q (1<<1) -#define _BW_HS2_PARAM_SLOPE (1<<1) +#define _BW_HS2_PARAM_SLOPE (1<<2) static inline void bw_hs2_init(bw_hs2_coeffs *BW_RESTRICT coeffs) { bw_mm2_init(&coeffs->mm2_coeffs); - coeffs->gain = 1.f; + coeffs->high_gain = 1.f; coeffs->Q = 0.5f; coeffs->slope = 0.5f; coeffs->use_slope = 1; @@ -215,12 +217,12 @@ static inline void bw_hs2_set_sample_rate(bw_hs2_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_HS2_PARAM_GAIN) { - coeffs->sg = bw_math_sqrtf_2(coeffs->gain); + 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->gain - coeffs->sg); + bw_mm2_set_coeff_hp(&coeffs->mm2_coeffs, coeffs->high_gain - coeffs->sg); } if (coeffs->use_slope) { if (coeffs->param_changed & _BW_HS2_PARAM_SLOPE) { @@ -278,15 +280,15 @@ static inline void bw_hs2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) } } -static inline void bw_hs2_set_dc_gain_lin(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) { - if (coeffs->gain != value) { - coeffs->gain = value; - coeffs->param_changed |= _BW_HS2_PARAM_GAIN; +static inline void bw_hs2_set_high_gain_lin(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) { + if (coeffs->high_gain != value) { + coeffs->high_gain = value; + coeffs->param_changed |= _BW_HS2_PARAM_HIGH_GAIN; } } -static inline void bw_hs2_set_dc_gain_dB(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) { - bw_hs2_set_dc_gain_lin(coeffs, bw_dB2linf_3(value)); +static inline void bw_hs2_set_high_gain_dB(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) { + bw_hs2_set_high_gain_lin(coeffs, bw_dB2linf_3(value)); } static inline void bw_hs2_set_slope(bw_hs2_coeffs *BW_RESTRICT coeffs, float value) { @@ -303,9 +305,9 @@ static inline void bw_hs2_set_use_slope(bw_mm2_coeffs *BW_RESTRICT coeffs, char } } -#undef _BW_HS2_PARAM_GAIN +#undef _BW_HS2_PARAM_HIGH_GAIN #undef _BW_HS2_PARAM_Q -#undef _BW_HS2_PARAM_S +#undef _BW_HS2_PARAM_SLOPE #ifdef __cplusplus } diff --git a/include/bw_ls2.h b/include/bw_ls2.h index f1e22ac..72da079 100644 --- a/include/bw_ls2.h +++ b/include/bw_ls2.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 @@ -187,7 +187,7 @@ struct _bw_ls2_coeffs { float isg; // Parameters - float gain; + float dc_gain; float Q; float slope; char use_slope; @@ -198,13 +198,13 @@ struct _bw_ls2_state { bw_mm2_state mm2_state; }; -#define _BW_LS2_PARAM_GAIN 1 +#define _BW_LS2_PARAM_DC_GAIN 1 #define _BW_LS2_PARAM_Q (1<<1) -#define _BW_LS2_PARAM_SLOPE (1<<1) +#define _BW_LS2_PARAM_SLOPE (1<<2) static inline void bw_ls2_init(bw_ls2_coeffs *BW_RESTRICT coeffs) { bw_mm2_init(&coeffs->mm2_coeffs); - coeffs->gain = 1.f; + coeffs->dc_gain = 1.f; coeffs->Q = 0.5f; coeffs->slope = 0.5f; coeffs->use_slope = 1; @@ -216,8 +216,8 @@ 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_GAIN) { - coeffs->sg = bw_math_sqrtf_2(coeffs->gain); + 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); @@ -280,9 +280,9 @@ static inline void bw_ls2_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) } static inline void bw_ls2_set_dc_gain_lin(bw_ls2_coeffs *BW_RESTRICT coeffs, float value) { - if (coeffs->gain != value) { - coeffs->gain = value; - coeffs->param_changed |= _BW_LS2_PARAM_GAIN; + if (coeffs->dc_gain != value) { + coeffs->dc_gain = value; + coeffs->param_changed |= _BW_LS2_PARAM_DC_GAIN; } } @@ -304,9 +304,9 @@ static inline void bw_ls2_set_use_slope(bw_mm2_coeffs *BW_RESTRICT coeffs, char } } -#undef _BW_LS2_PARAM_GAIN +#undef _BW_LS2_PARAM_DC_GAIN #undef _BW_LS2_PARAM_Q -#undef _BW_LS2_PARAM_S +#undef _BW_LS2_PARAM_SLOPE #ifdef __cplusplus } diff --git a/include/bw_notch2.h b/include/bw_notch.h similarity index 55% rename from include/bw_notch2.h rename to include/bw_notch.h index 739a7be..7529071 100644 --- a/include/bw_notch2.h +++ b/include/bw_notch.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 @@ -37,8 +37,8 @@ * }}} */ -#ifndef _BW_NOTCH2_H -#define _BW_NOTCH2_H +#ifndef _BW_NOTCH_H +#define _BW_NOTCH_H #ifdef __cplusplus extern "C" { @@ -47,80 +47,80 @@ extern "C" { #include /*! api {{{ - * #### bw_notch2_coeffs + * #### bw_notch_coeffs * ```>>> */ -typedef struct _bw_notch2_coeffs bw_notch2_coeffs; +typedef struct _bw_notch_coeffs bw_notch_coeffs; /*! <<<``` * Coefficients and related. * - * #### bw_notch2_state + * #### bw_notch_state * ```>>> */ -typedef struct _bw_notch2_state bw_notch2_state; +typedef struct _bw_notch_state bw_notch_state; /*! <<<``` * Internal state and related. * - * #### bw_notch2_init() + * #### bw_notch_init() * ```>>> */ -static inline void bw_notch2_init(bw_notch2_coeffs *BW_RESTRICT coeffs); +static inline void bw_notch_init(bw_notch_coeffs *BW_RESTRICT coeffs); /*! <<<``` * Initializes input parameter values in `coeffs`. * - * #### bw_notch2_set_sample_rate() + * #### bw_notch_set_sample_rate() * ```>>> */ -static inline void bw_notch2_set_sample_rate(bw_notch2_coeffs *BW_RESTRICT coeffs, float sample_rate); +static inline void bw_notch_set_sample_rate(bw_notch_coeffs *BW_RESTRICT coeffs, float sample_rate); /*! <<<``` * Sets the `sample_rate` (Hz) value in `coeffs`. * - * #### bw_notch2_reset_coeffs() + * #### bw_notch_reset_coeffs() * ```>>> */ -static inline void bw_notch2_reset_coeffs(bw_notch2_coeffs *BW_RESTRICT coeffs); +static inline void bw_notch_reset_coeffs(bw_notch_coeffs *BW_RESTRICT coeffs); /*! <<<``` * Resets coefficients in `coeffs` to assume their target values. * - * #### bw_notch2_reset_state() + * #### bw_notch_reset_state() * ```>>> */ -static inline void bw_notch2_reset_state(const bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state); +static inline void bw_notch_reset_state(const bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state); /*! <<<``` * Resets the given `state` to its initial values using the given `coeffs`. * - * #### bw_notch2_update_coeffs_ctrl() + * #### bw_notch_update_coeffs_ctrl() * ```>>> */ -static inline void bw_notch2_update_coeffs_ctrl(bw_notch2_coeffs *BW_RESTRICT coeffs); +static inline void bw_notch_update_coeffs_ctrl(bw_notch_coeffs *BW_RESTRICT coeffs); /*! <<<``` * Triggers control-rate update of coefficients in `coeffs`. * - * #### bw_notch2_update_coeffs_audio() + * #### bw_notch_update_coeffs_audio() * ```>>> */ -static inline void bw_notch2_update_coeffs_audio(bw_notch2_coeffs *BW_RESTRICT coeffs); +static inline void bw_notch_update_coeffs_audio(bw_notch_coeffs *BW_RESTRICT coeffs); /*! <<<``` * Triggers audio-rate update of coefficients in `coeffs`. * - * #### bw_notch2_process1() + * #### bw_notch_process1() * ```>>> */ -static inline float bw_notch2_process1(const bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state, float x); +static inline float bw_notch_process1(const bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state, float x); /*! <<<``` * Processes one input sample `x` using `coeffs`, while using and updating * `state`. Returns the corresponding output sample. * - * #### bw_notch2_process() + * #### bw_notch_process() * ```>>> */ -static inline void bw_notch2_process(bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state, const float *x, float *y, int n_samples); +static inline void bw_notch_process(bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state, const float *x, float *y, int n_samples); /*! <<<``` * Processes the first `n_samples` of the input buffer `x` and fills the * first `n_samples` of the output buffer `y`, while using and updating both * `coeffs` and `state` (control and audio rate). * - * #### bw_notch2_set_cutoff() + * #### bw_notch_set_cutoff() * ```>>> */ -static inline void bw_notch2_set_cutoff(bw_notch2_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_notch_set_cutoff(bw_notch_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` * Sets the cutoff frequency `value` (Hz) in `coeffs`. * * Default value: `1e3f`. * - * #### bw_notch2_set_Q() + * #### bw_notch_set_Q() * ```>>> */ -static inline void bw_notch2_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_notch_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` * Sets the quality factor to the given `value` in `coeffs`. * @@ -136,58 +136,58 @@ static inline void bw_notch2_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float valu #include -struct _bw_notch2_coeffs { +struct _bw_notch_coeffs { // Sub-components bw_svf_coeffs svf_coeffs; }; -struct _bw_notch2_state { +struct _bw_notch_state { bw_svf_state svf_state; }; -static inline void bw_notch2_init(bw_notch2_coeffs *BW_RESTRICT coeffs) { +static inline void bw_notch_init(bw_notch_coeffs *BW_RESTRICT coeffs) { bw_svf_init(&coeffs->svf_coeffs); } -static inline void bw_notch2_set_sample_rate(bw_notch2_coeffs *BW_RESTRICT coeffs, float sample_rate) { +static inline void bw_notch_set_sample_rate(bw_notch_coeffs *BW_RESTRICT coeffs, float sample_rate) { bw_svf_set_sample_rate(&coeffs->svf_coeffs, sample_rate); } -static inline void bw_notch2_reset_coeffs(bw_notch2_coeffs *BW_RESTRICT coeffs) { +static inline void bw_notch_reset_coeffs(bw_notch_coeffs *BW_RESTRICT coeffs) { bw_svf_reset_coeffs(&coeffs->svf_coeffs); } -static inline void bw_notch2_reset_state(const bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state) { +static inline void bw_notch_reset_state(const bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state) { bw_svf_reset_state(&coeffs->svf_coeffs, &state->svf_state); } -static inline void bw_notch2_update_coeffs_ctrl(bw_notch2_coeffs *BW_RESTRICT coeffs) { +static inline void bw_notch_update_coeffs_ctrl(bw_notch_coeffs *BW_RESTRICT coeffs) { bw_svf_update_coeffs_ctrl(&coeffs->svf_coeffs); } -static inline void bw_notch2_update_coeffs_audio(bw_notch2_coeffs *BW_RESTRICT coeffs) { +static inline void bw_notch_update_coeffs_audio(bw_notch_coeffs *BW_RESTRICT coeffs) { bw_svf_update_coeffs_audio(&coeffs->svf_coeffs); } -static inline float bw_notch2_process1(const bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state, float x) { +static inline float bw_notch_process1(const bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state, float x) { float lp, bp, hp; bw_svf_process1(&coeffs->svf_coeffs, &state->svf_state, x, &lp, &bp, &hp); return lp + hp; } -static inline void bw_notch2_process(bw_notch2_coeffs *BW_RESTRICT coeffs, bw_notch2_state *BW_RESTRICT state, const float *x, float *y, int n_samples) { - bw_notch2_update_coeffs_ctrl(coeffs); +static inline void bw_notch_process(bw_notch_coeffs *BW_RESTRICT coeffs, bw_notch_state *BW_RESTRICT state, const float *x, float *y, int n_samples) { + bw_notch_update_coeffs_ctrl(coeffs); for (int i = 0; i < n_samples; i++) { - bw_notch2_update_coeffs_audio(coeffs); - y[i] = bw_notch2_process1(coeffs, state, x[i]); + bw_notch_update_coeffs_audio(coeffs); + y[i] = bw_notch_process1(coeffs, state, x[i]); } } -static inline void bw_notch2_set_cutoff(bw_notch2_coeffs *BW_RESTRICT coeffs, float value) { +static inline void bw_notch_set_cutoff(bw_notch_coeffs *BW_RESTRICT coeffs, float value) { bw_svf_set_cutoff(&coeffs->svf_coeffs, value); } -static inline void bw_notch2_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value) { +static inline void bw_notch_set_Q(bw_svf_coeffs *BW_RESTRICT coeffs, float value) { bw_svf_set_Q(&coeffs->svf_coeffs, value); } diff --git a/include/bw_peak.h b/include/bw_peak.h new file mode 100644 index 0000000..ae65be2 --- /dev/null +++ b/include/bw_peak.h @@ -0,0 +1,317 @@ +/* + * Brickworks + * + * Copyright (C) 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 + * 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 + * along with Brickworks. If not, see . + * + * File author: Stefano D'Angelo + */ + +/*! + * module_type {{{ dsp }}} + * version {{{ 0.3.0 }}} + * requires {{{ + * bw_config bw_common bw_gain bw_math bw_mm2 bw_one_pole bw_svf + * }}} + * description {{{ + * Second-order peak filter with unitary gain at DC and asymptotically + * as frequency increases. + * + * The quality factor of the underlying bandpass filter can be either + * directly controlled via the Q parameter or indirectly through the + * bandwidth parameter, which designates the distance in octaves between + * midpoint gain frequencies, i.e., frequencies with gain = peak gain / 2 in + * dB terms. The use_bandiwdth parameter allows you to choose which + * parameterization to use. + * }}} + * changelog {{{ + *
    + *
  • Version 0.3.0: + *
      + *
    • First release.
    • + *
    + *
  • + *
+ * }}} + */ + +#ifndef _BW_PEAK_H +#define _BW_PEAK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! api {{{ + * #### bw_peak_coeffs + * ```>>> */ +typedef struct _bw_peak_coeffs bw_peak_coeffs; +/*! <<<``` + * Coefficients and related. + * + * #### bw_peak_state + * ```>>> */ +typedef struct _bw_peak_state bw_peak_state; +/*! <<<``` + * Internal state and related. + * + * #### bw_peak_init() + * ```>>> */ +static inline void bw_peak_init(bw_peak_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Initializes input parameter values in `coeffs`. + * + * #### bw_peak_set_sample_rate() + * ```>>> */ +static inline void bw_peak_set_sample_rate(bw_peak_coeffs *BW_RESTRICT coeffs, float sample_rate); +/*! <<<``` + * Sets the `sample_rate` (Hz) value in `coeffs`. + * + * #### bw_peak_reset_coeffs() + * ```>>> */ +static inline void bw_peak_reset_coeffs(bw_peak_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Resets coefficients in `coeffs` to assume their target values. + * + * #### bw_peak_reset_state() + * ```>>> */ +static inline void bw_peak_reset_state(const bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state); +/*! <<<``` + * Resets the given `state` to its initial values using the given `coeffs`. + * + * #### bw_peak_update_coeffs_ctrl() + * ```>>> */ +static inline void bw_peak_update_coeffs_ctrl(bw_peak_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers control-rate update of coefficients in `coeffs`. + * + * #### bw_peak_update_coeffs_audio() + * ```>>> */ +static inline void bw_peak_update_coeffs_audio(bw_peak_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers audio-rate update of coefficients in `coeffs`. + * + * #### bw_peak_process1() + * ```>>> */ +static inline float bw_peak_process1(const bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state, float x); +/*! <<<``` + * Processes one input sample `x` using `coeffs`, while using and updating + * `state`. Returns the corresponding output sample. + * + * #### bw_peak_process() + * ```>>> */ +static inline void bw_peak_process(bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state, const float *x, float *y, int n_samples); +/*! <<<``` + * Processes the first `n_samples` of the input buffer `x` and fills the + * first `n_samples` of the output buffer `y`, while using and updating both + * `coeffs` and `state` (control and audio rate). + * + * #### bw_peak_set_cutoff() + * ```>>> */ +static inline void bw_peak_set_cutoff(bw_peak_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the cutoff frequency `value` (Hz) in `coeffs`. + * + * Default value: `1e3f`. + * + * #### bw_peak_set_Q() + * ```>>> */ +static inline void bw_peak_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the quality factor to the given `value` in `coeffs`. + * + * `value` must be equal or bigger than `0.5f`. + * + * Default value: `0.5f`. + * + * #### bw_peak_set_gain_lin() + * ```>>> */ +static inline void bw_peak_set_peak_gain_lin(bw_peak_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the peak gain parameter to the given `value` (linear gain) in + * `coeffs`. + * + * Default value: `0.f`. + * + * #### bw_peak_set_dc_gain_dB() + * ```>>> */ +static inline void bw_peak_set_peak_gain_dB(bw_peak_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the peak gain parameter to the given `value` (dB) in `coeffs`. + * + * Default value: `-INFINITY`. + * + * #### bw_peak_set_bandiwdth() + * ```>>> */ +static inline void bw_peak_set_bandwidth(bw_peak_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the bandwidth `value` (octaves) in `coeffs`. + * + * Default value: `0.5f`. + * + * #### bw_peak_set_use_slope() + * ```>>> */ +static inline void bw_peak_set_use_bandwidth(bw_mm2_coeffs *BW_RESTRICT coeffs, char value); +/*! <<<``` + * Sets whether the quality factor should be controlled via the bandwidth + * parameter (`value` non-`0`) or via the Q parameter (`0`). + * + * Default value: non-`0` (use bandwidth parameter). + * }}} */ + +/*** Implementation ***/ + +/* WARNING: This part of the file is not part of the public API. Its content may + * change at any time in future versions. Please, do not use it directly. */ + +#include +#include + +struct _bw_peak_coeffs { + // Sub-components + bw_mm2_coeffs mm2_coeffs; + + // Coefficients + float sg; + float isg; + + // Parameters + float peak_gain; + float Q; + float bandwidth; + char use_bandwidth; + int param_changed; +}; + +struct _bw_peak_state { + bw_mm2_state mm2_state; +}; + +#define _BW_PEAK_PARAM_PEAK_GAIN 1 +#define _BW_PEAK_PARAM_Q (1<<1) +#define _BW_PEAK_PARAM_BANDWIDTH (1<<2) + +static inline void bw_peak_init(bw_peak_coeffs *BW_RESTRICT coeffs) { + bw_mm2_init(&coeffs->mm2_coeffs); + coeffs->peak_gain = 1.f; + coeffs->Q = 0.5f; + coeffs->bandwidth = ?; //Q=sqrt(gain)*k/(k^2-1), k=ratio f_half/f_peak + coeffs->use_bandwidth = 1; +} + +static inline void bw_peak_set_sample_rate(bw_peak_coeffs *BW_RESTRICT coeffs, float sample_rate) { + bw_mm2_set_sample_rate(&coeffs->mm2_coeffs, sample_rate); +} + +static inline void _bw_ls2_update_mm2_params(bw_ls1_coeffs *BW_RESTRICT coeffs) { + if (coeffs->param_changed) { + if (coeffs->param_changed & _BW_HS2_PARAM_GAIN) { + coeffs->sg = bw_math_sqrtf_2(coeffs->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->gain - coeffs->sg); + } + if (coeffs->use_slope) { + if (coeffs->param_changed & _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))); + } + } + else { + if (coeffs->param_changed & _BW_HS2_PARAM_Q) + bw_mm2_set_Q(&coeffs->mm2_coeffs, coeffs->Q); + } + coeffs->param_changed = 0; + } +} + +static inline void bw_peak_reset_coeffs(bw_peak_coeffs *BW_RESTRICT coeffs) { + coeffs->param_changed = ~0; + _bw_peak_update_mm2_params(coeffs); + bw_mm2_reset_coeffs(&coeffs->mm2_coeffs); +} + +static inline void bw_peak_reset_state(const bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state) { + bw_mm2_reset_state(&coeffs->mm2_coeffs, &state->mm2_state); +} + +static inline void bw_peak_update_coeffs_ctrl(bw_peak_coeffs *BW_RESTRICT coeffs) { + _bw_peak_update_mm2_params(coeffs); + bw_mm2_update_coeffs_ctrl(&coeffs->mm2_coeffs); +} + +static inline void bw_peak_update_coeffs_audio(bw_peak_coeffs *BW_RESTRICT coeffs) { + bw_mm2_update_coeffs_audio(&coeffs->mm2_coeffs); +} + +static inline float bw_peak_process1(const bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state, float x) { + return bw_mm2_process1(&coeffs->mm2_coeffs, &state->mm2_state, x); +} + +static inline void bw_peak_process(bw_peak_coeffs *BW_RESTRICT coeffs, bw_peak_state *BW_RESTRICT state, const float *x, float *y, int n_samples) { + bw_peak_update_coeffs_ctrl(coeffs); + for (int i = 0; i < n_samples; i++) { + bw_peak_update_coeffs_audio(coeffs); + y[i] = bw_peak_process1(coeffs, state, x[i]); + } +} + +static inline void bw_peak_set_cutoff(bw_peak_coeffs *BW_RESTRICT coeffs, float value) { + bw_mm2_set_cutoff(&coeffs->mm2_coeffs, value); +} + +static inline void bw_peak_set_Q(bw_mm2_coeffs *BW_RESTRICT coeffs, float value) { + if (coeffs->Q != value) { + coeffs->Q = value; + coeffs->param_changed |= _BW_HS2_PARAM_Q; + } +} + +static inline void bw_peak_set_dc_gain_lin(bw_peak_coeffs *BW_RESTRICT coeffs, float value) { + if (coeffs->gain != value) { + coeffs->gain = value; + coeffs->param_changed |= _BW_HS2_PARAM_GAIN; + } +} + +static inline void bw_peak_set_dc_gain_dB(bw_peak_coeffs *BW_RESTRICT coeffs, float value) { + bw_peak_set_dc_gain_lin(coeffs, bw_dB2linf_3(value)); +} + +static inline void bw_peak_set_slope(bw_peak_coeffs *BW_RESTRICT coeffs, float value) { + if (coeffs->slope != value) { + coeffs->slope = value; + coeffs->param_changed |= _BW_HS2_PARAM_SLOPE; + } +} + +static inline void bw_peak_set_use_slope(bw_mm2_coeffs *BW_RESTRICT coeffs, char value) { + if ((coeffs->use_slope && !value) || (!coeffs->use_slope && value)) { + coeffs->use_slope = value; + coeffs->param_changed |= _BW_HS2_PARAM_Q | _BW_HS2_PARAM_SLOPE; + } +} + +#undef _BW_PEAK_PARAM_GAIN +#undef _BW_PEAK_PARAM_Q +#undef _BW_PEAK_PARAM_BANDWIDTH + +#ifdef __cplusplus +} +#endif + +#endif