From 0f204c3aa94e05cb5de478af0d5bc3762eb0ec8f Mon Sep 17 00:00:00 2001 From: Stefano D'Angelo <stefano.dangelo@orastron.com> Date: Tue, 24 Jan 2023 17:27:56 +0100 Subject: [PATCH] new fx pan example + fix bw_pan, copyright, web code (vst3 broken) --- examples/common/web/index-fx.html | 8 +- examples/common/web/index-synth.html | 8 +- examples/common/web/memset.c | 2 +- examples/common/web/wrapper.c | 16 ++-- examples/fx_pan/src/bw_example_fx_pan.c | 112 ++++++++++++++++++++++++ examples/fx_pan/src/bw_example_fx_pan.h | 42 +++++++++ examples/fx_pan/src/config.h | 90 +++++++++++++++++++ examples/fx_pan/vst3/Makefile | 6 ++ examples/fx_pan/vst3/config_vst3.h | 36 ++++++++ examples/fx_pan/web/Makefile | 4 + examples/fx_pan/web/config.js | 48 ++++++++++ include/bw_pan.h | 14 +-- include/bw_ppm.h | 2 +- 13 files changed, 366 insertions(+), 22 deletions(-) create mode 100644 examples/fx_pan/src/bw_example_fx_pan.c create mode 100644 examples/fx_pan/src/bw_example_fx_pan.h create mode 100644 examples/fx_pan/src/config.h create mode 100644 examples/fx_pan/vst3/Makefile create mode 100644 examples/fx_pan/vst3/config_vst3.h create mode 100644 examples/fx_pan/web/Makefile create mode 100644 examples/fx_pan/web/config.js diff --git a/examples/common/web/index-fx.html b/examples/common/web/index-fx.html index a8874e5..74a01a6 100644 --- a/examples/common/web/index-fx.html +++ b/examples/common/web/index-fx.html @@ -3,7 +3,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 @@ -50,9 +50,9 @@ var Effect = { if (!this.node) this.node = new AudioWorkletNode(audioCtx, "BWExample", { - numberOfInputs: 1, - numberOfOutputs: 1, - outputChannelCount: [ 1 ], + numberOfInputs: buses.filter(function (b) { return !b.output; }).length, + numberOfOutputs: buses.filter(function (b) { return b.output; }).length, + outputChannelCount: buses.filter(function (b) { return b.output}).map(function (b) { return b.stereo ? 2 : 1 }), processorOptions: { wasmBytes: this.wasmBytes } diff --git a/examples/common/web/index-synth.html b/examples/common/web/index-synth.html index 51258f5..7714c55 100644 --- a/examples/common/web/index-synth.html +++ b/examples/common/web/index-synth.html @@ -3,7 +3,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 @@ -51,9 +51,9 @@ var Synth = { if (!this.node) this.node = new AudioWorkletNode(audioCtx, "BWExample", { - numberOfInputs: 0, - numberOfOutputs: 1, - outputChannelCount: [ 1 ], + numberOfInputs: buses.filter(function (b) { return !b.output; }).length, + numberOfOutputs: buses.filter(function (b) { return b.output; }).length, + outputChannelCount: buses.filter(function (b) { return b.output}).map(function (b) { return b.stereo ? 2 : 1 }), processorOptions: { wasmBytes: this.wasmBytes } }); this.node.connect(audioCtx.destination); diff --git a/examples/common/web/memset.c b/examples/common/web/memset.c index 991a99a..7adc910 100644 --- a/examples/common/web/memset.c +++ b/examples/common/web/memset.c @@ -1,7 +1,7 @@ /* * Brickworks * - * Copyright (C) 2021, 2022 Orastron Srl unipersonale + * 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 diff --git a/examples/common/web/wrapper.c b/examples/common/web/wrapper.c index 9fb0b95..f785d1c 100644 --- a/examples/common/web/wrapper.c +++ b/examples/common/web/wrapper.c @@ -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 @@ -54,23 +54,29 @@ wrapper wrapper_new(float sample_rate) { #if NUM_BUSES_IN != 0 int dx = 0; + int jx = 0; for (int i = 0; i < NUM_BUSES_IN; i++) { - ret->x[i] = ret->ins + dx; + ret->x[jx] = ret->ins + dx; dx += 128; + jx++; if (config_buses_in[i].configs & IO_STEREO) { - ret->x[i] = ret->ins + dx; + ret->x[jx] = ret->ins + dx; dx += 128; + jx++; } } #endif #if NUM_BUSES_OUT != 0 int dy = 0; + int jy = 0; for (int i = 0; i < NUM_BUSES_OUT; i++) { - ret->y[i] = ret->outs + dy; + ret->y[jy] = ret->outs + dy; dy += 128; + jy++; if (config_buses_out[i].configs & IO_STEREO) { - ret->y[i] = ret->outs + dy; + ret->y[jy] = ret->outs + dy; dy += 128; + jy++; } } #endif diff --git a/examples/fx_pan/src/bw_example_fx_pan.c b/examples/fx_pan/src/bw_example_fx_pan.c new file mode 100644 index 0000000..d88e8ee --- /dev/null +++ b/examples/fx_pan/src/bw_example_fx_pan.c @@ -0,0 +1,112 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * File author: Stefano D'Angelo + */ + +#include "bw_example_fx_pan.h" + +#include <bw_pan.h> +#include <bw_ppm.h> +#include <bw_math.h> +#ifdef __WASM__ +# include "walloc.h" +#else +# include <stdlib.h> +#endif + +enum { + p_pan, + p_n +}; + +struct _bw_example_fx_pan { + // Sub-components + bw_pan_coeffs pan_coeffs; + bw_ppm_coeffs ppm_coeffs; + bw_ppm_state ppm_l_state; + bw_ppm_state ppm_r_state; + + // Parameters + float params[p_n]; +}; + +bw_example_fx_pan bw_example_fx_pan_new() { + bw_example_fx_pan instance = (bw_example_fx_pan)malloc(sizeof(struct _bw_example_fx_pan)); + if (instance == NULL) + return NULL; + bw_pan_init(&instance->pan_coeffs); + bw_ppm_init(&instance->ppm_coeffs); + return instance; +} + +void bw_example_fx_pan_free(bw_example_fx_pan instance) { + free(instance); +} + +void bw_example_fx_pan_set_sample_rate(bw_example_fx_pan instance, float sample_rate) { + bw_pan_set_sample_rate(&instance->pan_coeffs, sample_rate); + bw_ppm_set_sample_rate(&instance->ppm_coeffs, sample_rate); +} + +void bw_example_fx_pan_reset(bw_example_fx_pan instance) { + bw_pan_reset_coeffs(&instance->pan_coeffs); + bw_ppm_reset_coeffs(&instance->ppm_coeffs); + bw_ppm_reset_state(&instance->ppm_coeffs, &instance->ppm_l_state); + bw_ppm_reset_state(&instance->ppm_coeffs, &instance->ppm_r_state); +} + +void bw_example_fx_pan_process(bw_example_fx_pan instance, const float** x, float** y, int n_samples) { + bw_pan_process(&instance->pan_coeffs, x[0], y[0], y[1], n_samples); + bw_ppm_update_coeffs_ctrl(&instance->ppm_coeffs); + for (int i = 0; i < n_samples; i++) { + bw_ppm_update_coeffs_audio(&instance->ppm_coeffs); + bw_ppm_process1(&instance->ppm_coeffs, &instance->ppm_l_state, y[0][i]); + bw_ppm_process1(&instance->ppm_coeffs, &instance->ppm_r_state, y[1][i]); + } +} + +void bw_example_fx_pan_set_parameter(bw_example_fx_pan instance, int index, float value) { + instance->params[index] = value; + switch (index) { + case p_pan: + bw_pan_set_pan(&instance->pan_coeffs, value + value - 1.f); + break; + } +} + +float bw_example_fx_pan_get_parameter(bw_example_fx_pan instance, int index) { + float r; + switch (index) { + case p_pan: + r = instance->params[p_pan]; + break; + case p_pan + 1: + { + const float v = bw_ppm_get_y_z1(&instance->ppm_l_state); + r = v < -200.f ? 0.f : bw_clipf(0.01666666666666667f * v + 1.f, 0.f, 1.f); + break; + } + case p_pan + 2: + { + const float v = bw_ppm_get_y_z1(&instance->ppm_r_state); + r = v < -200.f ? 0.f : bw_clipf(0.01666666666666667f * v + 1.f, 0.f, 1.f); + break; + } + } + return r; +} diff --git a/examples/fx_pan/src/bw_example_fx_pan.h b/examples/fx_pan/src/bw_example_fx_pan.h new file mode 100644 index 0000000..e4cf3ea --- /dev/null +++ b/examples/fx_pan/src/bw_example_fx_pan.h @@ -0,0 +1,42 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * File author: Stefano D'Angelo + */ + +#ifndef _BW_EXAMPLE_FX_PAN_H +#define _BW_EXAMPLE_FX_PAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _bw_example_fx_pan* bw_example_fx_pan; + +bw_example_fx_pan bw_example_fx_pan_new(); +void bw_example_fx_pan_free(bw_example_fx_pan instance); +void bw_example_fx_pan_set_sample_rate(bw_example_fx_pan instance, float sample_rate); +void bw_example_fx_pan_reset(bw_example_fx_pan instance); +void bw_example_fx_pan_process(bw_example_fx_pan instance, const float** x, float** y, int n_samples); +void bw_example_fx_pan_set_parameter(bw_example_fx_pan instance, int index, float value); +float bw_example_fx_pan_get_parameter(bw_example_fx_pan instance, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/fx_pan/src/config.h b/examples/fx_pan/src/config.h new file mode 100644 index 0000000..4af50cc --- /dev/null +++ b/examples/fx_pan/src/config.h @@ -0,0 +1,90 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * 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_pan" +#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 2 + +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_STEREO } +}; + +#define NUM_PARAMETERS 3 + +static struct config_parameter config_parameters[NUM_PARAMETERS] = { + { "Pan", "Pan", "", 0, 0, 0, 0.5f }, + { "Left level", "L Level", "", 1, 0, 0, 0.f }, + { "Right level", "R Level", "", 1, 0, 0, 0.f } +}; + +// Internal API + +#include "bw_example_fx_pan.h" + +#define P_TYPE bw_example_fx_pan +#define P_NEW bw_example_fx_pan_new +#define P_FREE bw_example_fx_pan_free +#define P_SET_SAMPLE_RATE bw_example_fx_pan_set_sample_rate +#define P_RESET bw_example_fx_pan_reset +#define P_PROCESS bw_example_fx_pan_process +#define P_SET_PARAMETER bw_example_fx_pan_set_parameter +#define P_GET_PARAMETER bw_example_fx_pan_get_parameter + +#endif diff --git a/examples/fx_pan/vst3/Makefile b/examples/fx_pan/vst3/Makefile new file mode 100644 index 0000000..5ba8e1e --- /dev/null +++ b/examples/fx_pan/vst3/Makefile @@ -0,0 +1,6 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) + +NAME := bw_example_fx_pan +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_pan.c + +include ${ROOT_DIR}/../../common/vst3/vst3.mk diff --git a/examples/fx_pan/vst3/config_vst3.h b/examples/fx_pan/vst3/config_vst3.h new file mode 100644 index 0000000..ea3d041 --- /dev/null +++ b/examples/fx_pan/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 <http://www.gnu.org/licenses/>. + * + * File authors: Stefano D'Angelo, Paolo Marrone + */ + +#ifndef _VST3_CONFIG_H +#define _VST3_CONFIG_H + +#define PLUGIN_SUBCATEGORY "Fx|Spatial" + +#define PLUGIN_GUID_1 0x7ad61d9e +#define PLUGIN_GUID_2 0x26b44033 +#define PLUGIN_GUID_3 0xbfae229a +#define PLUGIN_GUID_4 0x3e99719e + +#define CTRL_GUID_1 0x59d57809 +#define CTRL_GUID_2 0x6b3d4822 +#define CTRL_GUID_3 0x89272538 +#define CTRL_GUID_4 0x8e8a352c + +#endif diff --git a/examples/fx_pan/web/Makefile b/examples/fx_pan/web/Makefile new file mode 100644 index 0000000..8e53cab --- /dev/null +++ b/examples/fx_pan/web/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) +SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_pan.c + +include ${ROOT_DIR}/../../common/web/web.mk diff --git a/examples/fx_pan/web/config.js b/examples/fx_pan/web/config.js new file mode 100644 index 0000000..8bd233b --- /dev/null +++ b/examples/fx_pan/web/config.js @@ -0,0 +1,48 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * File author: Stefano D'Angelo + */ + +var buses = [ + { + stereo: false, + output: false + }, + { + stereo: true, + output: true + } +]; + +var parameters = [ + { + name: "Pan", + output: false, + defaultValue: 0.5 + }, + { + name: "Left level", + output: true, + defaultValue: 0.0 + }, + { + name: "Right level", + output: true, + defaultValue: 0.0 + } +]; diff --git a/include/bw_pan.h b/include/bw_pan.h index 3c81ca0..6227dbe 100644 --- a/include/bw_pan.h +++ b/include/bw_pan.h @@ -84,7 +84,7 @@ static inline void bw_pan_update_coeffs_audio(bw_pan_coeffs *BW_RESTRICT coeffs) * * #### bw_pan_process1() * ```>>> */ -static inline float bw_pan_process1(const bw_pan_coeffs *BW_RESTRICT coeffs, float x, float *BW_RESTRICT y_l, float *BW_RESTRICT y_r); +static inline void bw_pan_process1(const bw_pan_coeffs *BW_RESTRICT coeffs, float x, float *BW_RESTRICT y_l, float *BW_RESTRICT y_r); /*! <<<``` * Processes one input sample `x` using `coeffs`, while using and updating * `state`. The left and right output samples are put into `y_l` (left) and @@ -138,7 +138,7 @@ static inline void bw_pan_set_sample_rate(bw_pan_coeffs *BW_RESTRICT coeffs, flo bw_gain_set_sample_rate(&coeffs->r_coeffs, sample_rate); } -static inline void _bw_pan_do_update_coeffs(bw_gain_coeffs *BW_RESTRICT coeffs, char force) { +static inline void _bw_pan_do_update_coeffs(bw_pan_coeffs *BW_RESTRICT coeffs, char force) { if (force || coeffs->pan != coeffs->pan_prev) { const float k = 0.125f * coeffs->pan + 0.125f; bw_gain_set_gain_lin(&coeffs->l_coeffs, bw_cos2pif_3(k)); @@ -164,7 +164,7 @@ static inline void bw_pan_update_coeffs_audio(bw_pan_coeffs *BW_RESTRICT coeffs) bw_gain_update_coeffs_audio(&coeffs->r_coeffs); } -static inline float bw_pan_process1(const bw_pan_coeffs *BW_RESTRICT coeffs, float x, float *BW_RESTRICT y_l, float *BW_RESTRICT y_r) { +static inline void bw_pan_process1(const bw_pan_coeffs *BW_RESTRICT coeffs, float x, float *BW_RESTRICT y_l, float *BW_RESTRICT y_r) { *y_l = bw_gain_process1(&coeffs->l_coeffs, x); *y_r = bw_gain_process1(&coeffs->r_coeffs, x); } @@ -175,13 +175,13 @@ static inline void bw_pan_process(bw_pan_coeffs *BW_RESTRICT coeffs, const float if (y_r != NULL) { for (int i = 0; i < n_samples; i++) { bw_pan_update_coeffs_audio(coeffs); - bw_pan_process1(coeffs, state, x[i], y_l + i, y_r + i); + bw_pan_process1(coeffs, x[i], y_l + i, y_r + i); } } else { for (int i = 0; i < n_samples; i++) { bw_pan_update_coeffs_audio(coeffs); float r; - bw_pan_process1(coeffs, state, x[i], y_l + i, &r); + bw_pan_process1(coeffs, x[i], y_l + i, &r); } } } else { @@ -189,13 +189,13 @@ static inline void bw_pan_process(bw_pan_coeffs *BW_RESTRICT coeffs, const float for (int i = 0; i < n_samples; i++) { bw_pan_update_coeffs_audio(coeffs); float l; - bw_pan_process1(coeffs, state, x[i], &l, y_r + i); + bw_pan_process1(coeffs, x[i], &l, y_r + i); } } else { for (int i = 0; i < n_samples; i++) { bw_pan_update_coeffs_audio(coeffs); float l, r; - bw_pan_process1(coeffs, state, x[i], &l, &r); + bw_pan_process1(coeffs, x[i], &l, &r); } } } diff --git a/include/bw_ppm.h b/include/bw_ppm.h index 4ad1036..59459e2 100644 --- a/include/bw_ppm.h +++ b/include/bw_ppm.h @@ -20,7 +20,7 @@ /*! * module_type {{{ dsp }}} - * version {{{ 0.2.0 }}} + * version {{{ 0.3.0 }}} * requires {{{ bw_config bw_common bw_env_follow bw_math bw_one_pole }}} * description {{{ * Digital peak programme meter with adjustable integration time constant.