From 5d988b0c0560e492c63d6089a4fdc2f88417900e Mon Sep 17 00:00:00 2001 From: Stefano D'Angelo Date: Thu, 1 Jun 2023 13:39:47 +0200 Subject: [PATCH] bw_drywet fixed + beginning of bw_reverb, fx_reverb --- examples/fx_reverb/daisy-seed/Makefile | 7 + .../fx_reverb/daisy-seed/config_daisy_seed.h | 35 +++ examples/fx_reverb/src/bw_example_fx_reverb.c | 71 +++++ examples/fx_reverb/src/bw_example_fx_reverb.h | 62 ++++ examples/fx_reverb/src/config.h | 93 ++++++ examples/fx_reverb/vst3/Makefile | 6 + examples/fx_reverb/vst3/config_vst3.h | 36 +++ examples/fx_reverb/web/Makefile | 5 + examples/fx_reverb/web/config.js | 58 ++++ include/bw_drywet.h | 24 +- include/bw_reverb.h | 269 ++++++++++++++++++ 11 files changed, 648 insertions(+), 18 deletions(-) create mode 100644 examples/fx_reverb/daisy-seed/Makefile create mode 100644 examples/fx_reverb/daisy-seed/config_daisy_seed.h create mode 100644 examples/fx_reverb/src/bw_example_fx_reverb.c create mode 100644 examples/fx_reverb/src/bw_example_fx_reverb.h create mode 100644 examples/fx_reverb/src/config.h create mode 100644 examples/fx_reverb/vst3/Makefile create mode 100644 examples/fx_reverb/vst3/config_vst3.h create mode 100644 examples/fx_reverb/web/Makefile create mode 100644 examples/fx_reverb/web/config.js create mode 100644 include/bw_reverb.h diff --git a/examples/fx_reverb/daisy-seed/Makefile b/examples/fx_reverb/daisy-seed/Makefile new file mode 100644 index 0000000..39f6e7a --- /dev/null +++ b/examples/fx_reverb/daisy-seed/Makefile @@ -0,0 +1,7 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +TARGET = bw_example_fx_delay + +C_SOURCES += ${ROOT_DIR}/../src/bw_example_fx_delay.c + +include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk diff --git a/examples/fx_reverb/daisy-seed/config_daisy_seed.h b/examples/fx_reverb/daisy-seed/config_daisy_seed.h new file mode 100644 index 0000000..466205b --- /dev/null +++ b/examples/fx_reverb/daisy-seed/config_daisy_seed.h @@ -0,0 +1,35 @@ +/* + * 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 authors: Stefano D'Angelo + */ + +#ifndef _CONFIG_DAISY_SEED_H +#define _CONFIG_DAISY_SEED_H + +struct config_pin { + int param_index; + int pin; +}; + +#define NUM_PINS 1 + +static struct config_pin config_pins[NUM_PINS] = { + { 0, 15 } +}; + +#endif diff --git a/examples/fx_reverb/src/bw_example_fx_reverb.c b/examples/fx_reverb/src/bw_example_fx_reverb.c new file mode 100644 index 0000000..f517e94 --- /dev/null +++ b/examples/fx_reverb/src/bw_example_fx_reverb.c @@ -0,0 +1,71 @@ +/* + * 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 + */ + +#include "bw_example_fx_reverb.h" + +void bw_example_fx_reverb_init(bw_example_fx_reverb *instance) { + bw_reverb_init(&instance->reverb_coeffs); +} + +void bw_example_fx_reverb_set_sample_rate(bw_example_fx_reverb *instance, float sample_rate) { + bw_reverb_set_sample_rate(&instance->reverb_coeffs, sample_rate); +} + +BW_SIZE_T bw_example_fx_reverb_mem_req(bw_example_fx_reverb *instance) { + return bw_reverb_mem_req(&instance->reverb_coeffs); +} + +void bw_example_fx_reverb_mem_set(bw_example_fx_reverb *instance, void *mem) { + bw_reverb_mem_set(&instance->reverb_state, mem); +} + +void bw_example_fx_reverb_reset(bw_example_fx_reverb *instance) { + bw_reverb_reset_coeffs(&instance->reverb_coeffs); + bw_reverb_reset_state(&instance->reverb_coeffs, &instance->reverb_state); +} + +void bw_example_fx_reverb_process(bw_example_fx_reverb *instance, const float** x, float** y, int n_samples) { + bw_reverb_process(&instance->reverb_coeffs, &instance->reverb_state, x[0], x[1], y[0], y[1], n_samples); +} + +void bw_example_fx_reverb_set_parameter(bw_example_fx_reverb *instance, int index, float value) { + instance->params[index] = value; + switch (index) { + case p_predelay: + bw_reverb_set_predelay(&instance->reverb_coeffs, 0.1f * value); + break; + case p_bandwidth: + bw_reverb_set_bandwidth(&instance->reverb_coeffs, 20.f + (20e3f - 20.f) * value * value * value); + break; + case p_damping: + bw_reverb_set_damping(&instance->reverb_coeffs, 20.f + (20e3f - 20.f) * value * value * value); + break; + case p_decay: + bw_reverb_set_decay(&instance->reverb_coeffs, bw_minf(value, 0.999f)); + break; + case p_drywet: + bw_reverb_set_wet(&instance->reverb_coeffs, value); + break; + } +} + +float bw_example_fx_reverb_get_parameter(bw_example_fx_reverb *instance, int index) { + return instance->params[index]; +} diff --git a/examples/fx_reverb/src/bw_example_fx_reverb.h b/examples/fx_reverb/src/bw_example_fx_reverb.h new file mode 100644 index 0000000..fa65eee --- /dev/null +++ b/examples/fx_reverb/src/bw_example_fx_reverb.h @@ -0,0 +1,62 @@ +/* + * 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 + */ + +#ifndef _BW_EXAMPLE_FX_REVERB_H +#define _BW_EXAMPLE_FX_REVERB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum { + p_predelay, + p_bandwidth, + p_damping, + p_decay, + p_drywet, + p_n +}; + +struct _bw_example_fx_reverb { + // Sub-components + bw_reverb_coeffs reverb_coeffs; + bw_reverb_state reverb_state; + + // Parameters + float params[p_n]; +}; +typedef struct _bw_example_fx_reverb bw_example_fx_reverb; + +void bw_example_fx_reverb_init(bw_example_fx_reverb *instance); +void bw_example_fx_reverb_set_sample_rate(bw_example_fx_reverb *instance, float sample_rate); +BW_SIZE_T bw_example_fx_reverb_mem_req(bw_example_fx_reverb *instance); +void bw_example_fx_reverb_mem_set(bw_example_fx_reverb *instance, void *mem); +void bw_example_fx_reverb_reset(bw_example_fx_reverb *instance); +void bw_example_fx_reverb_process(bw_example_fx_reverb *instance, const float** x, float** y, int n_samples); +void bw_example_fx_reverb_set_parameter(bw_example_fx_reverb *instance, int index, float value); +float bw_example_fx_reverb_get_parameter(bw_example_fx_reverb *instance, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/fx_reverb/src/config.h b/examples/fx_reverb/src/config.h new file mode 100644 index 0000000..9c9592d --- /dev/null +++ b/examples/fx_reverb/src/config.h @@ -0,0 +1,93 @@ +/* + * 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 authors: Stefano D'Angelo + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +// Definitions + +#define IO_MONO 1 +#define IO_STEREO (1<<1) + +struct config_io_bus { + const char *name; + char out; + char aux; + char cv; + char configs; +}; + +struct config_parameter { + const char *name; + const char *shortName; + const char *units; + char out; + char bypass; + int steps; + float defaultValueUnmapped; +}; + +// Data + +#define COMPANY_NAME "Orastron" +#define COMPANY_WEBSITE "https://www.orastron.com/" +#define COMPANY_MAILTO "mailto:info@orastron.com" + +#define PLUGIN_NAME "bw_example_fx_reverb" +#define PLUGIN_VERSION "0.5.0" + +#define NUM_BUSES_IN 1 +#define NUM_BUSES_OUT 1 +#define NUM_CHANNELS_IN 1 +#define NUM_CHANNELS_OUT 1 + +static struct config_io_bus config_buses_in[NUM_BUSES_IN] = { + { "Audio in", 0, 0, 0, IO_STEREO } +}; + +static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = { + { "Audio out", 1, 0, 0, IO_STEREO } +}; + +#define NUM_PARAMETERS 5 + +static struct config_parameter config_parameters[NUM_PARAMETERS] = { + { "Predelay", "Predelay", "", 0, 0, 0, 0.f }, + { "Bandwidth", "Bandwidth", "", 0, 0, 0, 1.f }, + { "Damping", "Damping", "", 0, 0, 0, 1.f }, + { "Decay rate", "Decay", "", 0, 0, 0, 0.5f }, + { "Dry/wet", "Dry/wet", "", 0, 0, 0, 0.5f } +}; + +// Internal API + +#include "bw_example_fx_reverb.h" + +#define P_TYPE bw_example_fx_reverb +#define P_INIT bw_example_fx_reverb_init +#define P_SET_SAMPLE_RATE bw_example_fx_reverb_set_sample_rate +#define P_MEM_REQ bw_example_fx_reverb_mem_req +#define P_MEM_SET bw_example_fx_reverb_mem_set +#define P_RESET bw_example_fx_reverb_reset +#define P_PROCESS bw_example_fx_reverb_process +#define P_SET_PARAMETER bw_example_fx_reverb_set_parameter +#define P_GET_PARAMETER bw_example_fx_reverb_get_parameter + +#endif diff --git a/examples/fx_reverb/vst3/Makefile b/examples/fx_reverb/vst3/Makefile new file mode 100644 index 0000000..20c0ccf --- /dev/null +++ b/examples/fx_reverb/vst3/Makefile @@ -0,0 +1,6 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +NAME := bw_example_fx_delay +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_delay.c + +include ${ROOT_DIR}/../../common/vst3/vst3.mk diff --git a/examples/fx_reverb/vst3/config_vst3.h b/examples/fx_reverb/vst3/config_vst3.h new file mode 100644 index 0000000..358be00 --- /dev/null +++ b/examples/fx_reverb/vst3/config_vst3.h @@ -0,0 +1,36 @@ +/* + * 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 authors: Stefano D'Angelo, Paolo Marrone + */ + +#ifndef _VST3_CONFIG_H +#define _VST3_CONFIG_H + +#define PLUGIN_SUBCATEGORY "Fx|Delay" + +#define PLUGIN_GUID_1 0x30a47806 +#define PLUGIN_GUID_2 0x850f445c +#define PLUGIN_GUID_3 0x9f13660d +#define PLUGIN_GUID_4 0x0e26f2dc + +#define CTRL_GUID_1 0xfd1e3d99 +#define CTRL_GUID_2 0xd2cb4d57 +#define CTRL_GUID_3 0x82e54aaf +#define CTRL_GUID_4 0x5e1a5bd5 + +#endif diff --git a/examples/fx_reverb/web/Makefile b/examples/fx_reverb/web/Makefile new file mode 100644 index 0000000..e9486d5 --- /dev/null +++ b/examples/fx_reverb/web/Makefile @@ -0,0 +1,5 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_reverb.c +NEEDS_MEMSET := yes + +include ${ROOT_DIR}/../../common/web/web.mk diff --git a/examples/fx_reverb/web/config.js b/examples/fx_reverb/web/config.js new file mode 100644 index 0000000..631467d --- /dev/null +++ b/examples/fx_reverb/web/config.js @@ -0,0 +1,58 @@ +/* + * 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 + */ + +var buses = [ + { + stereo: false, + output: false + }, + { + stereo: false, + output: true + } +]; + +var parameters = [ + { + name: "Predelay", + output: false, + defaultValue: 0.0 + }, + { + name: "Bandwidth", + output: false, + defaultValue: 1.0 + }, + { + name: "Damping", + output: false, + defaultValue: 1.0 + }, + { + name: "Decay rate", + output: false, + defaultValue: 0.5 + }, + { + name: "Dry/wet", + output: false, + defaultValue: 0.5 + } +]; diff --git a/include/bw_drywet.h b/include/bw_drywet.h index 987f13f..084dd07 100644 --- a/include/bw_drywet.h +++ b/include/bw_drywet.h @@ -97,22 +97,14 @@ static inline void bw_drywet_process(bw_drywet_coeffs *BW_RESTRICT coeffs, const * wet input buffer `x_wet` and fills the first `n_samples` of the output * buffer `y`, while using and updating `coeffs` (control and audio rate). * - * #### bw_drywet_set_wet_lin() + * #### bw_drywet_set_wet() * ```>>> */ -static inline void bw_drywet_set_wet_lin(bw_drywet_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_drywet_set_wet(bw_drywet_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` * Sets the wet gain parameter to the given `value` (linear gain) in `coeffs`. * * Default value: `1.f`. * - * #### bw_drywet_set_wet_dB() - * ```>>> */ -static inline void bw_drywet_set_wet_dB(bw_drywet_coeffs *BW_RESTRICT coeffs, float value); -/*! <<<``` - * Sets the wet gain parameter to the given `value` (dB) in `coeffs`. - * - * Default value: `0.f`. - * * #### bw_drywet_set_smooth_tau() * ```>>> */ static inline void bw_drywet_set_smooth_tau(bw_drywet_coeffs *BW_RESTRICT coeffs, float value); @@ -131,7 +123,7 @@ static inline void bw_drywet_set_smooth_tau(bw_drywet_coeffs *BW_RESTRICT coeffs struct _bw_drywet_coeffs { // Sub-components - bw_gain gain_coeffs; + bw_gain_coeffs gain_coeffs; }; static inline void bw_drywet_init(bw_drywet_coeffs *BW_RESTRICT coeffs) { @@ -139,7 +131,7 @@ static inline void bw_drywet_init(bw_drywet_coeffs *BW_RESTRICT coeffs) { } static inline void bw_drywet_set_sample_rate(bw_drywet_coeffs *BW_RESTRICT coeffs, float sample_rate) { - bw_gain_sample_rate(&coeffs->smooth_coeffs, sample_rate); + bw_gain_set_sample_rate(&coeffs->gain_coeffs, sample_rate); } static inline void bw_drywet_reset_coeffs(bw_drywet_coeffs *BW_RESTRICT coeffs) { @@ -155,7 +147,7 @@ static inline void bw_drywet_update_coeffs_audio(bw_drywet_coeffs *BW_RESTRICT c } static inline float bw_drywet_process1(const bw_drywet_coeffs *BW_RESTRICT coeffs, float x_dry, float x_wet) { - return bw_gain_get_gain(coeffs->gain_coeffs) * (x_wet - x_dry) + x_dry; + return bw_gain_get_gain(&coeffs->gain_coeffs) * (x_wet - x_dry) + x_dry; } static inline void bw_drywet_process(bw_drywet_coeffs *BW_RESTRICT coeffs, const float *x_dry, const float *x_wet, float *y, int n_samples) { @@ -166,14 +158,10 @@ static inline void bw_drywet_process(bw_drywet_coeffs *BW_RESTRICT coeffs, const } } -static inline void bw_drywet_set_drywet_lin(bw_drywet_coeffs *BW_RESTRICT coeffs, float value) { +static inline void bw_drywet_set_wet(bw_drywet_coeffs *BW_RESTRICT coeffs, float value) { bw_gain_set_gain_lin(&coeffs->gain_coeffs, value); } -static inline void bw_drywet_set_drywet_dB(bw_drywet_coeffs *BW_RESTRICT coeffs, float value) { - bw_gain_set_gain_dB(&coeffs->gain_coeffs, value); -} - static inline void bw_drywet_set_smooth_tau(bw_drywet_coeffs *BW_RESTRICT coeffs, float value) { bw_gain_set_smooth_tau(&coeffs->gain_coeffs, value); } diff --git a/include/bw_reverb.h b/include/bw_reverb.h new file mode 100644 index 0000000..2b4349e --- /dev/null +++ b/include/bw_reverb.h @@ -0,0 +1,269 @@ +/* + * 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.5.0 }}} + * requires {{{ + * bw_buf bw_common bw_config bw_delay bw_drywet bw_gain bw_math bw_one_pole + * }}} + * description {{{ + * Stereo reverb. + * + * Essentially an implementation of the structure described in + * + * J. Dattorro, "Effect Design, Part 1: Reverberator and Other Filters", + * J. Audio Eng. Soc., vol. 45, no. 9, pp. 660-684, September 1997. + * }}} + * changelog {{{ + *
    + *
  • Version 0.5.0: + *
      + *
    • First release.
    • + *
    + *
  • + *
+ * }}} + */ + +#ifndef _BW_REVERB_H +#define _BW_REVERB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! api {{{ + * #### bw_reverb_coeffs + * ```>>> */ +typedef struct _bw_reverb_coeffs bw_reverb_coeffs; +/*! <<<``` + * Coefficients and related. + * + * #### bw_reverb_state + * ```>>> */ +typedef struct _bw_reverb_state bw_reverb_state; +/*! <<<``` + * Internal state and related. + * + * #### bw_reverb_init() + * ```>>> */ +static inline void bw_reverb_init(bw_reverb_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Initializes input parameter values in `coeffs`. + * + * #### bw_reverb_set_sample_rate() + * ```>>> */ +static inline void bw_reverb_set_sample_rate(bw_reverb_coeffs *BW_RESTRICT coeffs, float sample_rate); +/*! <<<``` + * Sets the `sample_rate` (Hz) value in `coeffs`. + * + * #### bw_reverb_mem_req() + * ```>>> */ +static inline BW_SIZE_T bw_reverb_mem_req(bw_reverb_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Returns the size, in bytes, of contiguous memory to be supplied to + * `bw_reverb_mem_set()` using `coeffs`. + * + * #### bw_reverb_mem_set() + * ```>>> */ +static inline void bw_reverb_mem_set(bw_reverb_state *BW_RESTRICT state, void *mem); +/*! <<<``` + * Associates the contiguous memory block `mem` to the given `state`. + * + * #### bw_reverb_reset_coeffs() + * ```>>> */ +static inline void bw_reverb_reset_coeffs(bw_reverb_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Resets coefficients in `coeffs` to assume their target values. + * + * #### bw_reverb_reset_state() + * ```>>> */ +static inline void bw_reverb_reset_state(const bw_reverb_coeffs *BW_RESTRICT coeffs, bw_reverb_state *BW_RESTRICT state); +/*! <<<``` + * Resets the given `state` to its initial values using the given `coeffs`. + * + * #### bw_reverb_update_coeffs_ctrl() + * ```>>> */ +static inline void bw_reverb_update_coeffs_ctrl(bw_reverb_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers control-rate update of coefficients in `coeffs`. + * + * #### bw_reverb_update_coeffs_audio() + * ```>>> */ +static inline void bw_reverb_update_coeffs_audio(bw_reverb_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers audio-rate update of coefficients in `coeffs`. + * + * #### bw_reverb_process1() + * ```>>> */ +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); +/*! <<<``` + * Processes two input samples `xl` and `xr` using `coeffs`, while using and + * updating `state`. Writes the corresponding output samples `yl` and `yr`. + * + * #### bw_reverb_process() + * ```>>> */ +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); +/*! <<<``` + * Processes the first `n_samples` of the input buffers `xl` and `xr` and + * fills the first `n_samples` of the output buffers `yl` and `yr`, while + * using and updating both `coeffs` and `state` (control and audio rate). + * + * #### bw_reverb_set_predelay() + * ```>>> */ +static inline void bw_reverb_set_predelay(bw_reverb_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the predelay time `value` (s) in `coeffs`. + * + * Valid input range: [`0.f`, `0.1f`]. + * + * Default value: `0.f`. + * + * #### bw_reverb_set_bandwidth() + * ```>>> */ +static inline void bw_reverb_set_bandwidth(bw_reverb_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the input high-frequency attenuation `value` (Hz) in `coeffs`. + * + * Default value: `20e3f`. + * + * #### bw_reverb_set_damping() + * ```>>> */ +static inline void bw_reverb_set_damping(bw_reverb_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the high-frequency damping `value` (Hz) in `coeffs`. + * + * Default value: `20e3f`. + * + * #### bw_reverb_set_decay() + * ```>>> */ +static inline void bw_reverb_set_decay(bw_reverb_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the decay rate `value` in `coeffs`. + * + * Valid input range: [`0.f`, `1.f`). + * + * Default value: `0.5f`. + * + * #### bw_reverb_set_wet() + * ```>>> */ +static inline void bw_reverb_set_wet(bw_reverb_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the output wet mixing `value` (linear gain) in `coeffs`. + * + * Default value: `0.5f`. + * }}} */ + +/*** 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_reverb_coeffs { + // Sub-components + bw_delay_coeffs predelay_coeffs; + bw_drywet_coeffs drywet_coeffs; +}; + +struct _bw_reverb_state { + bw_delay_state predelay_state; +}; + +static inline void bw_reverb_init(bw_reverb_coeffs *BW_RESTRICT coeffs) { + bw_delay_init(&coeffs->predelay_coeffs, 0.1f); + bw_drywet_init(&coeffs->drywet_coeffs); + bw_drywet_set_wet(&coeffs->drywet_coeffs, 0.5f); +} + +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_drywet_set_sample_rate(&coeffs->drywet_coeffs, sample_rate); +} + +static inline BW_SIZE_T bw_reverb_mem_req(bw_reverb_coeffs *BW_RESTRICT coeffs) { + return bw_delay_mem_req(&coeffs->predelay_coeffs); +} + +static inline void bw_reverb_mem_set(bw_reverb_state *BW_RESTRICT state, void *mem) { + bw_delay_mem_set(&state->predelay_state, mem); +} + +static inline void bw_reverb_reset_coeffs(bw_reverb_coeffs *BW_RESTRICT coeffs) { + bw_delay_reset_coeffs(&coeffs->predelay_coeffs); + bw_drywet_reset_coeffs(&coeffs->drywet_coeffs); +} + +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); +} + +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); +} + +static inline void bw_reverb_update_coeffs_audio(bw_reverb_coeffs *BW_RESTRICT coeffs) { + bw_delay_update_coeffs_audio(&coeffs->predelay_coeffs); + bw_drywet_update_coeffs_audio(&coeffs->drywet_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); +} + +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) { + bw_reverb_update_coeffs_ctrl(coeffs); + for (int i = 0; i < n_samples; i++) { + bw_reverb_update_coeffs_audio(coeffs); + bw_reverb_process1(coeffs, state, xl[i], xr[i], yl + i, yr + i); + } +} + +static inline void bw_reverb_set_predelay(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) { + bw_delay_set_delay(&coeffs->predelay_coeffs, value); +} + +static inline void bw_reverb_set_bandwidth(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) { +} + +static inline void bw_reverb_set_damping(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) { +} + +static inline void bw_reverb_set_decay(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) { +} + +static inline void bw_reverb_set_wet(bw_reverb_coeffs *BW_RESTRICT coeffs, float value) { + bw_drywet_set_wet(&coeffs->drywet_coeffs, value); +} + +#ifdef __cplusplus +} +#endif + +#endif