From 37415a0b0ee6713d506e7adfe61d81eeaebe9d98 Mon Sep 17 00:00:00 2001
From: Stefano D'Angelo <stefano.dangelo@orastron.com>
Date: Wed, 10 May 2023 11:16:38 +0200
Subject: [PATCH] fixed bw_drive, new example fx_drive

---
 examples/fx_drive/daisy-seed/Makefile         |  7 ++
 .../fx_drive/daisy-seed/config_daisy_seed.h   | 37 ++++++++
 examples/fx_drive/src/bw_example_fx_drive.c   | 68 ++++++++++++++
 examples/fx_drive/src/bw_example_fx_drive.h   | 68 ++++++++++++++
 examples/fx_drive/src/config.h                | 89 +++++++++++++++++++
 examples/fx_drive/vst3/Makefile               |  6 ++
 examples/fx_drive/vst3/config_vst3.h          | 36 ++++++++
 examples/fx_drive/web/Makefile                |  4 +
 examples/fx_drive/web/config.js               | 48 ++++++++++
 include/bw_drive.h                            | 10 +--
 10 files changed, 368 insertions(+), 5 deletions(-)
 create mode 100644 examples/fx_drive/daisy-seed/Makefile
 create mode 100644 examples/fx_drive/daisy-seed/config_daisy_seed.h
 create mode 100644 examples/fx_drive/src/bw_example_fx_drive.c
 create mode 100644 examples/fx_drive/src/bw_example_fx_drive.h
 create mode 100644 examples/fx_drive/src/config.h
 create mode 100644 examples/fx_drive/vst3/Makefile
 create mode 100644 examples/fx_drive/vst3/config_vst3.h
 create mode 100644 examples/fx_drive/web/Makefile
 create mode 100644 examples/fx_drive/web/config.js

diff --git a/examples/fx_drive/daisy-seed/Makefile b/examples/fx_drive/daisy-seed/Makefile
new file mode 100644
index 0000000..03b29ea
--- /dev/null
+++ b/examples/fx_drive/daisy-seed/Makefile
@@ -0,0 +1,7 @@
+ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+
+TARGET = bw_example_fx_drive
+
+C_SOURCES += ${ROOT_DIR}/../src/bw_example_fx_drive.c
+
+include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk
diff --git a/examples/fx_drive/daisy-seed/config_daisy_seed.h b/examples/fx_drive/daisy-seed/config_daisy_seed.h
new file mode 100644
index 0000000..8aa4923
--- /dev/null
+++ b/examples/fx_drive/daisy-seed/config_daisy_seed.h
@@ -0,0 +1,37 @@
+/*
+ * 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_DAISY_SEED_H
+#define _CONFIG_DAISY_SEED_H
+
+struct config_pin {
+	int	param_index;
+	int	pin;
+};
+
+#define NUM_PINS 	3
+
+static struct config_pin config_pins[NUM_PINS] = {
+	{ 0, 15 },
+	{ 1, 16 },
+	{ 2, 17 }
+};
+
+#endif
diff --git a/examples/fx_drive/src/bw_example_fx_drive.c b/examples/fx_drive/src/bw_example_fx_drive.c
new file mode 100644
index 0000000..aefe129
--- /dev/null
+++ b/examples/fx_drive/src/bw_example_fx_drive.c
@@ -0,0 +1,68 @@
+/*
+ * 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_drive.h"
+
+void bw_example_fx_drive_init(bw_example_fx_drive *instance) {
+	bw_drive_init(&instance->drive_coeffs);
+	bw_src_int_init(&instance->src_up_coeffs, 2);
+	bw_src_int_init(&instance->src_down_coeffs, -2);
+}
+
+void bw_example_fx_drive_set_sample_rate(bw_example_fx_drive *instance, float sample_rate) {
+	bw_drive_set_sample_rate(&instance->drive_coeffs, 2.f * sample_rate);
+}
+
+void bw_example_fx_drive_reset(bw_example_fx_drive *instance) {
+	bw_drive_reset_coeffs(&instance->drive_coeffs);
+	bw_drive_reset_state(&instance->drive_coeffs, &instance->drive_state);
+	bw_src_int_reset_state(&instance->src_up_coeffs, &instance->src_up_state, 0.f);
+	bw_src_int_reset_state(&instance->src_down_coeffs, &instance->src_down_state, 0.f);
+}
+
+void bw_example_fx_drive_process(bw_example_fx_drive *instance, const float** x, float** y, int n_samples) {
+	int i = 0;
+	while (i < n_samples) {
+		int n = bw_mini32(n_samples - i, BUF_SIZE >> 1);
+		bw_src_int_process(&instance->src_up_coeffs, &instance->src_up_state, x[0] + i, instance->buf, n);
+		bw_drive_process(&instance->drive_coeffs, &instance->drive_state, instance->buf, instance->buf, n << 1);
+		bw_src_int_process(&instance->src_down_coeffs, &instance->src_down_state, instance->buf, y[0] + i, n << 1);
+		i += n;
+	}
+}
+
+void bw_example_fx_drive_set_parameter(bw_example_fx_drive *instance, int index, float value) {
+	instance->params[index] = value;
+	switch (index) {
+	case p_drive:
+		bw_drive_set_drive(&instance->drive_coeffs, value);
+		break;
+	case p_tone:
+		bw_drive_set_tone(&instance->drive_coeffs, value);
+		break;
+	case p_volume:
+		bw_drive_set_volume(&instance->drive_coeffs, value);
+		break;
+	}
+}
+
+float bw_example_fx_drive_get_parameter(bw_example_fx_drive *instance, int index) {
+	return instance->params[index];
+}
diff --git a/examples/fx_drive/src/bw_example_fx_drive.h b/examples/fx_drive/src/bw_example_fx_drive.h
new file mode 100644
index 0000000..007fcd1
--- /dev/null
+++ b/examples/fx_drive/src/bw_example_fx_drive.h
@@ -0,0 +1,68 @@
+/*
+ * 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_DRIVE_H
+#define _BW_EXAMPLE_FX_DRIVE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bw_drive.h>
+#include <bw_src_int.h>
+
+enum {
+	p_drive,
+	p_tone,
+	p_volume,
+	p_n
+};
+
+#define BUF_SIZE	32
+
+struct _bw_example_fx_drive {
+	// Sub-components
+	bw_drive_coeffs		drive_coeffs;
+	bw_drive_state		drive_state;
+	bw_src_int_coeffs	src_up_coeffs;
+	bw_src_int_state	src_up_state;
+	bw_src_int_coeffs	src_down_coeffs;
+	bw_src_int_state	src_down_state;
+
+	// Parameters
+	float		params[p_n];
+
+	// Buffers
+	float		buf[BUF_SIZE];
+};
+typedef struct _bw_example_fx_drive bw_example_fx_drive;
+
+void bw_example_fx_drive_init(bw_example_fx_drive *instance);
+void bw_example_fx_drive_set_sample_rate(bw_example_fx_drive *instance, float sample_rate);
+void bw_example_fx_drive_reset(bw_example_fx_drive *instance);
+void bw_example_fx_drive_process(bw_example_fx_drive *instance, const float** x, float** y, int n_samples);
+void bw_example_fx_drive_set_parameter(bw_example_fx_drive *instance, int index, float value);
+float bw_example_fx_drive_get_parameter(bw_example_fx_drive *instance, int index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/examples/fx_drive/src/config.h b/examples/fx_drive/src/config.h
new file mode 100644
index 0000000..c25b37c
--- /dev/null
+++ b/examples/fx_drive/src/config.h
@@ -0,0 +1,89 @@
+/*
+ * 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_drive"
+#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_MONO }
+};
+
+static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = {
+	{ "Audio out", 1, 0, 0, IO_MONO }
+};
+
+#define NUM_PARAMETERS		3
+
+static struct config_parameter config_parameters[NUM_PARAMETERS] = {
+	{ "Overdrive", "Overdrive", "", 0, 0, 0, 0.f },
+	{ "Tone", "Tone", "", 0, 0, 0, 0.5f },
+	{ "Volume", "Volume", "", 0, 0, 0, 1.f }
+};
+
+// Internal API
+
+#include "bw_example_fx_drive.h"
+
+#define P_TYPE				bw_example_fx_drive
+#define P_INIT				bw_example_fx_drive_init
+#define P_SET_SAMPLE_RATE		bw_example_fx_drive_set_sample_rate
+#define P_RESET				bw_example_fx_drive_reset
+#define P_PROCESS			bw_example_fx_drive_process
+#define P_SET_PARAMETER			bw_example_fx_drive_set_parameter
+#define P_GET_PARAMETER			bw_example_fx_drive_get_parameter
+
+#endif
diff --git a/examples/fx_drive/vst3/Makefile b/examples/fx_drive/vst3/Makefile
new file mode 100644
index 0000000..e85999a
--- /dev/null
+++ b/examples/fx_drive/vst3/Makefile
@@ -0,0 +1,6 @@
+ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+
+NAME := bw_example_fx_drive
+SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_drive.c
+
+include ${ROOT_DIR}/../../common/vst3/vst3.mk
diff --git a/examples/fx_drive/vst3/config_vst3.h b/examples/fx_drive/vst3/config_vst3.h
new file mode 100644
index 0000000..67bcbb5
--- /dev/null
+++ b/examples/fx_drive/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|Distortion"
+
+#define PLUGIN_GUID_1		0xd1f2d0ec
+#define PLUGIN_GUID_2		0xfea7421c
+#define PLUGIN_GUID_3		0xbbcf7153
+#define PLUGIN_GUID_4		0xaa570d7d
+
+#define CTRL_GUID_1		0x704bb2c1
+#define CTRL_GUID_2		0xc9954416
+#define CTRL_GUID_3		0xa2e3f58c
+#define CTRL_GUID_4		0x6ec4695b
+
+#endif
diff --git a/examples/fx_drive/web/Makefile b/examples/fx_drive/web/Makefile
new file mode 100644
index 0000000..447b4fb
--- /dev/null
+++ b/examples/fx_drive/web/Makefile
@@ -0,0 +1,4 @@
+ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_fx_drive.c
+
+include ${ROOT_DIR}/../../common/web/web.mk
diff --git a/examples/fx_drive/web/config.js b/examples/fx_drive/web/config.js
new file mode 100644
index 0000000..5bd3889
--- /dev/null
+++ b/examples/fx_drive/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:		false,
+		output:		true
+	}
+];
+
+var parameters = [
+	{
+		name:		"Overdrive",
+		output:		false,
+		defaultValue:	0.0
+	},
+	{
+		name:		"Tone",
+		output:		false,
+		defaultValue:	0.5
+	},
+	{
+		name:		"Volume",
+		output:		false,
+		defaultValue:	1.0
+	}
+];
diff --git a/include/bw_drive.h b/include/bw_drive.h
index 2710ead..8868650 100644
--- a/include/bw_drive.h
+++ b/include/bw_drive.h
@@ -162,7 +162,7 @@ struct _bw_drive_coeffs {
 
 struct _bw_drive_state {
 	// Sub-components
-	bw_svf_state	svf_state;
+	bw_svf_state	hp2_state;
 	bw_peak_state	peak_state;
 	bw_satur_state	satur_state;
 	bw_svf_state	lp2_state;
@@ -178,7 +178,7 @@ static inline void bw_drive_init(bw_drive_coeffs *BW_RESTRICT coeffs) {
 	bw_peak_set_cutoff(&coeffs->peak_coeffs, 2e3f);
 	bw_peak_set_bandwidth(&coeffs->peak_coeffs, 10.f);
 	bw_satur_set_gain(&coeffs->satur_coeffs, 1.5f);
-	bw_lp1_set_cutoff(&coeffs->lp1_coeffs, 600.f + (7.5e3f - 600.f) * 0.125f);
+	bw_svf_set_cutoff(&coeffs->lp2_coeffs, 600.f + (7.5e3f - 600.f) * 0.125f);
 }
 
 static inline void bw_drive_set_sample_rate(bw_drive_coeffs *BW_RESTRICT coeffs, float sample_rate) {
@@ -221,8 +221,8 @@ static inline float bw_drive_process1(const bw_drive_coeffs *BW_RESTRICT coeffs,
 	bw_svf_process1(&coeffs->hp2_coeffs, &state->hp2_state, x, &v_lp, &v_bp, &v_hp);
 	float y = bw_peak_process1(&coeffs->peak_coeffs, &state->peak_state, v_hp);
 	y = v_hp + 0.5f * bw_satur_process1_comp(&coeffs->satur_coeffs, &state->satur_state, y);
-	y = bw_svf_process1(&coeffs->lp2_coeffs, &state->lp2_state, y);
-	return bw_gain_process1(&coeffs->gain_coeffs, y);
+	bw_svf_process1(&coeffs->lp2_coeffs, &state->lp2_state, y, &v_lp, &v_bp, &v_hp);
+	return bw_gain_process1(&coeffs->gain_coeffs, v_lp);
 }
 
 static inline void bw_drive_process(bw_drive_coeffs *BW_RESTRICT coeffs, bw_drive_state *BW_RESTRICT state, const float *x, float *y, int n_samples) {
@@ -238,7 +238,7 @@ static inline void bw_drive_set_drive(bw_drive_coeffs *BW_RESTRICT coeffs, float
 }
 
 static inline void bw_drive_set_tone(bw_drive_coeffs *BW_RESTRICT coeffs, float value) {
-	bw_lp1_set_cutoff(&coeffs->lp1_coeffs, 600.f + (7.5e3f - 600.f) * value * value * value);
+	bw_svf_set_cutoff(&coeffs->lp2_coeffs, 600.f + (7.5e3f - 600.f) * value * value * value);
 }
 
 static inline void bw_drive_set_volume(bw_drive_coeffs *BW_RESTRICT coeffs, float value) {