diff --git a/examples/fx_trem/daisy-seed/Makefile b/examples/fx_trem/daisy-seed/Makefile new file mode 100644 index 0000000..a369483 --- /dev/null +++ b/examples/fx_trem/daisy-seed/Makefile @@ -0,0 +1,7 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +TARGET = bw_example_fx_trem + +C_SOURCES += ${ROOT_DIR}/../src/bw_example_fx_trem.c + +include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk diff --git a/examples/fx_trem/daisy-seed/config_daisy_seed.h b/examples/fx_trem/daisy-seed/config_daisy_seed.h new file mode 100644 index 0000000..c56c264 --- /dev/null +++ b/examples/fx_trem/daisy-seed/config_daisy_seed.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 + */ + +#ifndef _CONFIG_DAISY_SEED_H +#define _CONFIG_DAISY_SEED_H + +struct config_pin { + int param_index; + int pin; +}; + +#define NUM_PINS 2 + +static struct config_pin config_pins[NUM_PINS] = { + { 0, 15 }, + { 1, 16 } +}; + +#endif diff --git a/examples/fx_trem/src/bw_example_fx_trem.c b/examples/fx_trem/src/bw_example_fx_trem.c new file mode 100644 index 0000000..5f5bbcf --- /dev/null +++ b/examples/fx_trem/src/bw_example_fx_trem.c @@ -0,0 +1,54 @@ +/* + * 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_trem.h" + +void bw_example_fx_trem_init(bw_example_fx_trem *instance) { + bw_trem_init(&instance->trem_coeffs); +} + +void bw_example_fx_trem_set_sample_rate(bw_example_fx_trem *instance, float sample_rate) { + bw_trem_set_sample_rate(&instance->trem_coeffs, sample_rate); +} + +void bw_example_fx_trem_reset(bw_example_fx_trem *instance) { + bw_trem_reset_coeffs(&instance->trem_coeffs); + bw_trem_reset_state(&instance->trem_coeffs, &instance->trem_state); +} + +void bw_example_fx_trem_process(bw_example_fx_trem *instance, const float** x, float** y, int n_samples) { + bw_trem_process(&instance->trem_coeffs, &instance->trem_state, x[0], y[0], n_samples); +} + +void bw_example_fx_trem_set_parameter(bw_example_fx_trem *instance, int index, float value) { + instance->params[index] = value; + switch (index) { + case p_speed: + bw_trem_set_frequency(&instance->trem_coeffs, (20.f - 1.f) * value * value * value + 1.f); + break; + case p_amount: + bw_trem_set_amount(&instance->trem_coeffs, value); + break; + } +} + +float bw_example_fx_trem_get_parameter(bw_example_fx_trem *instance, int index) { + return instance->params[index]; +} diff --git a/examples/fx_trem/src/bw_example_fx_trem.h b/examples/fx_trem/src/bw_example_fx_trem.h new file mode 100644 index 0000000..b600424 --- /dev/null +++ b/examples/fx_trem/src/bw_example_fx_trem.h @@ -0,0 +1,57 @@ +/* + * 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_TREM_H +#define _BW_EXAMPLE_FX_TREM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum { + p_speed, + p_amount, + p_n +}; + +struct _bw_example_fx_trem { + // Sub-components + bw_trem_coeffs trem_coeffs; + bw_trem_state trem_state; + + // Parameters + float params[p_n]; +}; +typedef struct _bw_example_fx_trem bw_example_fx_trem; + +void bw_example_fx_trem_init(bw_example_fx_trem *instance); +void bw_example_fx_trem_set_sample_rate(bw_example_fx_trem *instance, float sample_rate); +void bw_example_fx_trem_reset(bw_example_fx_trem *instance); +void bw_example_fx_trem_process(bw_example_fx_trem *instance, const float** x, float** y, int n_samples); +void bw_example_fx_trem_set_parameter(bw_example_fx_trem *instance, int index, float value); +float bw_example_fx_trem_get_parameter(bw_example_fx_trem *instance, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/fx_trem/src/config.h b/examples/fx_trem/src/config.h new file mode 100644 index 0000000..b20c6bf --- /dev/null +++ b/examples/fx_trem/src/config.h @@ -0,0 +1,88 @@ +/* + * 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_trem" +#define PLUGIN_VERSION "0.3.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_MONO } +}; + +static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = { + { "Audio out", 1, 0, 0, IO_MONO } +}; + +#define NUM_PARAMETERS 2 + +static struct config_parameter config_parameters[NUM_PARAMETERS] = { + { "Speed", "Speed", "", 0, 0, 0, 0.5f }, + { "Amount", "Amount", "", 0, 0, 0, 0.5f } +}; + +// Internal API + +#include "bw_example_fx_trem.h" + +#define P_TYPE bw_example_fx_trem +#define P_INIT bw_example_fx_trem_init +#define P_SET_SAMPLE_RATE bw_example_fx_trem_set_sample_rate +#define P_RESET bw_example_fx_trem_reset +#define P_PROCESS bw_example_fx_trem_process +#define P_SET_PARAMETER bw_example_fx_trem_set_parameter +#define P_GET_PARAMETER bw_example_fx_trem_get_parameter + +#endif diff --git a/examples/fx_trem/vst3/Makefile b/examples/fx_trem/vst3/Makefile new file mode 100644 index 0000000..4618a88 --- /dev/null +++ b/examples/fx_trem/vst3/Makefile @@ -0,0 +1,6 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +NAME := bw_example_fx_trem +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_trem.c + +include ${ROOT_DIR}/../../common/vst3/vst3.mk diff --git a/examples/fx_trem/vst3/config_vst3.h b/examples/fx_trem/vst3/config_vst3.h new file mode 100644 index 0000000..bd161a5 --- /dev/null +++ b/examples/fx_trem/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|Modulation" + +#define PLUGIN_GUID_1 0xf26324d0 +#define PLUGIN_GUID_2 0x66ed4652 +#define PLUGIN_GUID_3 0x9197bb20 +#define PLUGIN_GUID_4 0xf6bfc407 + +#define CTRL_GUID_1 0x17fcf5e1 +#define CTRL_GUID_2 0x93154192 +#define CTRL_GUID_3 0x8264849e +#define CTRL_GUID_4 0x22e52112 + +#endif diff --git a/examples/fx_trem/web/Makefile b/examples/fx_trem/web/Makefile new file mode 100644 index 0000000..b82dfd0 --- /dev/null +++ b/examples/fx_trem/web/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_trem.c + +include ${ROOT_DIR}/../../common/web/web.mk diff --git a/examples/fx_trem/web/config.js b/examples/fx_trem/web/config.js new file mode 100644 index 0000000..1b18f5b --- /dev/null +++ b/examples/fx_trem/web/config.js @@ -0,0 +1,43 @@ +/* + * 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: "Speed", + output: false, + defaultValue: 0.5 + }, + { + name: "Amount", + output: false, + defaultValue: 0.5 + } +]; diff --git a/include/bw_ringmod.h b/include/bw_ringmod.h index 8de3d38..5daca28 100644 --- a/include/bw_ringmod.h +++ b/include/bw_ringmod.h @@ -98,9 +98,9 @@ static inline void bw_ringmod_process(bw_ringmod_coeffs *BW_RESTRICT coeffs, con * output buffer `y`, while using and updating `coeffs` (control and audio * rate). * - * #### bw_ringmod_set_mod_amount() + * #### bw_ringmod_set_amount() * ```>>> */ -static inline void bw_ringmod_set_mod_amount(bw_ringmod_coeffs *BW_RESTRICT coeffs, float value); +static inline void bw_ringmod_set_amount(bw_ringmod_coeffs *BW_RESTRICT coeffs, float value); /*! <<<``` * Sets the modulation amount parameter to the given `value` (`0.f` = no * modulation, `1.f` = full modulation, `-1.f` = full modulation with @@ -159,7 +159,7 @@ static inline void bw_ringmod_process(bw_ringmod_coeffs *BW_RESTRICT coeffs, con } } -static inline void bw_ringmod_set_mod_amount(bw_ringmod_coeffs *BW_RESTRICT coeffs, float value) { +static inline void bw_ringmod_set_amount(bw_ringmod_coeffs *BW_RESTRICT coeffs, float value) { coeffs->mod_amount = value; } diff --git a/include/bw_trem.h b/include/bw_trem.h new file mode 100644 index 0000000..e3162ed --- /dev/null +++ b/include/bw_trem.h @@ -0,0 +1,211 @@ +/* + * 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.4.0 }}} + * requires {{{ + * bw_config bw_common bw_math bw_one_pole bw_osc_sin bw_phase_gen bw_ringmod + * }}} + * description {{{ + * Tremolo with variable speed and amount. + * }}} + * changelog {{{ + *
    + *
  • Version 0.4.0: + *
      + *
    • First release.
    • + *
    + *
  • + *
+ * }}} + */ + +#ifndef _BW_TREM_H +#define _BW_TREM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*! api {{{ + * #### bw_trem_coeffs + * ```>>> */ +typedef struct _bw_trem_coeffs bw_trem_coeffs; +/*! <<<``` + * Coefficients and related. + * + * ### bw_trem_state + * ```>>> */ +typedef struct _bw_trem_state bw_trem_state; +/*! <<<``` + * Internal state and related. + * + * #### bw_trem_init() + * ```>>> */ +static inline void bw_trem_init(bw_trem_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Initializes input parameter values in `coeffs`. + * + * #### bw_trem_set_sample_rate() + * ```>>> */ +static inline void bw_trem_set_sample_rate(bw_trem_coeffs *BW_RESTRICT coeffs, float sample_rate); +/*! <<<``` + * Sets the `sample_rate` (Hz) value in `coeffs`. + * + * #### bw_trem_reset_coeffs() + * ```>>> */ +static inline void bw_trem_reset_coeffs(bw_trem_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Resets coefficients in `coeffs` to assume their target values. + * + * #### bw_trem_reset_state() + * ```>>> */ +static inline void bw_trem_reset_state(const bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_state *BW_RESTRICT state); +/*! <<<``` + * Resets the given `state` to its initial values using the given `coeffs`. + * + * #### bw_trem_update_coeffs_ctrl() + * ```>>> */ +static inline void bw_trem_update_coeffs_ctrl(bw_trem_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers control-rate update of coefficients in `coeffs`. + * + * #### bw_trem_update_coeffs_audio() + * ```>>> */ +static inline void bw_trem_update_coeffs_audio(bw_trem_coeffs *BW_RESTRICT coeffs); +/*! <<<``` + * Triggers audio-rate update of coefficients in `coeffs`. + * + * #### bw_trem_process1() + * ```>>> */ +static inline float bw_trem_process1(const bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_state *BW_RESTRICT state, float x); +/*! <<<``` + * Processes one input sample `x` using `coeffs`, while using and updating + * `state`. Returns the corresponding output sample. + * + * #### bw_trem_process() + * ```>>> */ +static inline void bw_trem_process(bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_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_trem_set_speed() + * ```>>> */ +static inline void bw_trem_set_frequency(bw_trem_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the modulation frequency (speed) `value` (Hz) in `coeffs`. + * + * Default value: `1.f`. + * + * #### bw_trem_set_thresh_dBFS() + * ```>>> */ +static inline void bw_trem_set_amount(bw_trem_coeffs *BW_RESTRICT coeffs, float value); +/*! <<<``` + * Sets the amount parameter to the given `value` (`0.f` = no tremolo, `1.f` + * = full tremolo, `-1.f` = full tremolo with inverted polarity) in `coeffs`. + * + * Default value: `1.f`. + * }}} */ + +/*** 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 +#include + +struct _bw_trem_coeffs { + // Sub-components + bw_phase_gen_coeffs phase_gen_coeffs; + bw_ringmod_coeffs ringmod_coeffs; + + // Coefficients + + // Parameters +}; + +struct _bw_trem_state { + bw_phase_gen_state phase_gen_state; +}; + +static inline void bw_trem_init(bw_trem_coeffs *BW_RESTRICT coeffs) { + bw_phase_gen_init(&coeffs->phase_gen_coeffs); + bw_ringmod_init(&coeffs->ringmod_coeffs); +} + +static inline void bw_trem_set_sample_rate(bw_trem_coeffs *BW_RESTRICT coeffs, float sample_rate) { + bw_phase_gen_set_sample_rate(&coeffs->phase_gen_coeffs, sample_rate); + bw_ringmod_set_sample_rate(&coeffs->ringmod_coeffs, sample_rate); +} + +static inline void bw_trem_reset_coeffs(bw_trem_coeffs *BW_RESTRICT coeffs) { + bw_phase_gen_reset_coeffs(&coeffs->phase_gen_coeffs); + bw_ringmod_reset_coeffs(&coeffs->ringmod_coeffs); +} + +static inline void bw_trem_reset_state(const bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_state *BW_RESTRICT state) { + bw_phase_gen_reset_state(&coeffs->phase_gen_coeffs, &state->phase_gen_state, 0.f); +} + +static inline void bw_trem_update_coeffs_ctrl(bw_trem_coeffs *BW_RESTRICT coeffs) { + bw_phase_gen_update_coeffs_ctrl(&coeffs->phase_gen_coeffs); + bw_ringmod_update_coeffs_ctrl(&coeffs->ringmod_coeffs); +} + +static inline void bw_trem_update_coeffs_audio(bw_trem_coeffs *BW_RESTRICT coeffs) { + bw_phase_gen_update_coeffs_audio(&coeffs->phase_gen_coeffs); + bw_ringmod_update_coeffs_audio(&coeffs->ringmod_coeffs); +} + +static inline float bw_trem_process1(const bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_state *BW_RESTRICT state, float x) { + float p, pi; + bw_phase_gen_process1(&coeffs->phase_gen_coeffs, &state->phase_gen_state, &p, &pi); + const float c = bw_osc_sin_process1(p); + return bw_ringmod_process1(&coeffs->ringmod_coeffs, x, 1.f + c); +} + +static inline void bw_trem_process(bw_trem_coeffs *BW_RESTRICT coeffs, bw_trem_state *BW_RESTRICT state, const float *x, float *y, int n_samples) { + bw_trem_update_coeffs_ctrl(coeffs); + for (int i = 0; i < n_samples; i++) { + bw_trem_update_coeffs_audio(coeffs); + y[i] = bw_trem_process1(coeffs, state, x[i]); + } +} + +static inline void bw_trem_set_frequency(bw_trem_coeffs *BW_RESTRICT coeffs, float value) { + bw_phase_gen_set_frequency(&coeffs->phase_gen_coeffs, value); +} + +static inline void bw_trem_set_amount(bw_trem_coeffs *BW_RESTRICT coeffs, float value) { + bw_ringmod_set_amount(&coeffs->ringmod_coeffs, value); +} + +#ifdef __cplusplus +} +#endif + +#endif