diff --git a/TODO b/TODO
index 53d409c..ab401e3 100644
--- a/TODO
+++ b/TODO
@@ -64,6 +64,7 @@ code:
* src post filt?
* bw_env_gen process_multi gate const?
* c++ get coeffs/state? or public?
+* bw_buf invert src dest order?
build system:
* make makefiles handle paths with spaces etc
diff --git a/examples/synthpp_poly/daisy-seed/Makefile b/examples/synthpp_poly/daisy-seed/Makefile
new file mode 100644
index 0000000..072afa0
--- /dev/null
+++ b/examples/synthpp_poly/daisy-seed/Makefile
@@ -0,0 +1,9 @@
+ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+
+TARGET = bw_example_synthpp_poly
+
+CPP_SOURCES_EXTRA = ${ROOT_DIR}/../src/bw_example_synthpp_poly.cpp
+
+SYNTH := yes
+
+include ${ROOT_DIR}/../../common/daisy-seed/daisy-seed.mk
diff --git a/examples/synthpp_poly/daisy-seed/config_daisy_seed.h b/examples/synthpp_poly/daisy-seed/config_daisy_seed.h
new file mode 100644
index 0000000..d363122
--- /dev/null
+++ b/examples/synthpp_poly/daisy-seed/config_daisy_seed.h
@@ -0,0 +1,72 @@
+/*
+ * 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_cc {
+ int param_index;
+ unsigned char cc;
+};
+
+#define NUM_CCS 38
+
+static struct config_cc config_ccs[NUM_CCS] = {
+ { 0, 7 }, // Volume
+ { 1, 3 }, // Master tune
+ { 2, 5 }, // Portamento
+ { 3, 9 }, // Modulation mix
+ { 4, 14 }, // VCO1 modulation
+ { 5, 15 }, // VCO1 coarse
+ { 6, 20 }, // VCO1 fine
+ { 7, 21 }, // VCO1 waveform
+ { 8, 22 }, // VCO1 pulse width/slope
+ { 9, 23 }, // VCO1 level
+ { 10, 24 }, // VCO2 modulation
+ { 11, 25 }, // VCO2 coarse
+ { 12, 26 }, // VCO2 fine
+ { 13, 27 }, // VCO2 waveform
+ { 14, 28 }, // VCO2 pulse width/slope
+ { 15, 29 }, // VCO2 level
+ { 16, 30 }, // VCO3 keyboard control
+ { 17, 31 }, // VCO3 coarse
+ { 18, 85 }, // VCO3 fine
+ { 19, 86 }, // VCO3 waveform
+ { 20, 87 }, // VCO3 puslse width/slope
+ { 21, 89 }, // VCO3 level
+ { 22, 90 }, // Noise color
+ { 23, 102 }, // Noise level
+ { 24, 103 }, // VCF modulation
+ { 25, 104 }, // VCF keyboard control
+ { 26, 74 }, // VCF cutoff
+ { 27, 71 }, // VCF Q
+ { 28, 105 }, // VCF contour
+ { 29, 106 }, // VCF attack
+ { 30, 107 }, // VCF decay
+ { 31, 108 }, // VCF sustain
+ { 32, 109 }, // VCF release
+ { 33, 73 }, // VCA attack
+ { 34, 110 }, // VCA decay
+ { 35, 111 }, // VCA sustain
+ { 36, 72 }, // VCA release
+ { 37, 112 } // A440
+};
+
+#endif
diff --git a/examples/synthpp_poly/src/.bw_example_synthpp_poly.cpp.swp b/examples/synthpp_poly/src/.bw_example_synthpp_poly.cpp.swp
new file mode 100644
index 0000000..c00a4af
Binary files /dev/null and b/examples/synthpp_poly/src/.bw_example_synthpp_poly.cpp.swp differ
diff --git a/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp b/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp
new file mode 100644
index 0000000..ae289e1
--- /dev/null
+++ b/examples/synthpp_poly/src/bw_example_synthpp_poly.cpp
@@ -0,0 +1,398 @@
+/*
+ * 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_synthpp_poly.h"
+
+#include
+#include
+#include
+
+void bw_example_synthpp_poly_init(bw_example_synthpp_poly *instance) {
+ instance->vco1OscSaw.setAntialiasing(true);
+ instance->vco1OscPulse.setAntialiasing(true);
+ instance->vco1OscTri.setAntialiasing(true);
+ instance->vco2OscSaw.setAntialiasing(true);
+ instance->vco2OscPulse.setAntialiasing(true);
+ instance->vco2OscTri.setAntialiasing(true);
+ instance->vco3OscSaw.setAntialiasing(true);
+ instance->vco3OscPulse.setAntialiasing(true);
+ instance->vco3OscTri.setAntialiasing(true);
+ instance->a440PhaseGen.setFrequency(440.f);
+
+ instance->rand_state = 0xbaddecaf600dfeed;
+
+ for (int i = 0; i < N_VOICES; i++) {
+ instance->voices[i].instance = instance;
+ instance->voices[i].index = i;
+ }
+}
+
+void bw_example_synthpp_poly_set_sample_rate(bw_example_synthpp_poly *instance, float sample_rate) {
+ instance->vco1OscPulse.setSampleRate(sample_rate);
+ instance->vco1OscTri.setSampleRate(sample_rate);
+ instance->vco1Gain.setSampleRate(sample_rate);
+ instance->vco2OscPulse.setSampleRate(sample_rate);
+ instance->vco2OscTri.setSampleRate(sample_rate);
+ instance->vco2Gain.setSampleRate(sample_rate);
+ instance->vco3OscPulse.setSampleRate(sample_rate);
+ instance->vco3OscTri.setSampleRate(sample_rate);
+ instance->vco3Gain.setSampleRate(sample_rate);
+ instance->noiseGen.setSampleRate(sample_rate);
+ instance->pinkFilt.setSampleRate(sample_rate);
+ instance->noiseGain.setSampleRate(sample_rate);
+ instance->vcfEnvGen.setSampleRate(sample_rate);
+ instance->vcaEnvGen.setSampleRate(sample_rate);
+ instance->a440PhaseGen.setSampleRate(sample_rate);
+ instance->gain.setSampleRate(sample_rate);
+ instance->ppm.setSampleRate(sample_rate);
+
+ for (int i = 0; i < N_VOICES; i++) {
+ instance->voices[i].vco1PhaseGen.setSampleRate(sample_rate);
+ instance->voices[i].vco2PhaseGen.setSampleRate(sample_rate);
+ instance->voices[i].vco3PhaseGen.setSampleRate(sample_rate);
+ instance->voices[i].vcf.setSampleRate(sample_rate);
+ }
+}
+
+void bw_example_synthpp_poly_reset(bw_example_synthpp_poly *instance) {
+ const float v = instance->params[p_vcf_cutoff];
+ const float cutoff = 20.f + (20e3f - 20.f) * v * v * v;
+ for (int i = 0; i < N_VOICES; i++)
+ instance->voices[i].vcf.setCutoff(bw_clipf(cutoff, 20.f, 20e3f));
+
+ instance->noteQueue = NoteQueue();
+ instance->vco1OscPulse.reset();
+ instance->vco1OscTri.reset();
+ instance->vco1Gain.reset();
+ instance->vco2OscPulse.reset();
+ instance->vco2OscTri.reset();
+ instance->vco2Gain.reset();
+ instance->vco3OscPulse.reset();
+ instance->vco3OscTri.reset();
+ instance->vco3Gain.reset();
+ instance->oscFilt.reset();
+ instance->pinkFilt.reset();
+ instance->noiseGain.reset();
+ instance->vcfEnvGen.reset();
+ instance->vcaEnvGen.reset();
+ instance->a440PhaseGen.reset();
+ instance->gain.reset();
+ instance->ppm.reset();
+ for (int i = 0; i < N_VOICES; i++) {
+ instance->voices[i].vco1PhaseGen.reset();
+ instance->voices[i].vco2PhaseGen.reset();
+ instance->voices[i].vco3PhaseGen.reset();
+ instance->voices[i].vcf.reset();
+
+ instance->voices[i].gate = 0;
+ }
+
+ instance->pitch_bend = 0.f;
+ instance->mod_wheel = 0.f;
+}
+
+static void note_on(void *BW_RESTRICT voice, unsigned char note, float velocity) {
+ (void)velocity;
+ bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
+ v->note = note;
+ v->gate = 1;
+}
+
+static void note_off(void *BW_RESTRICT voice, float velocity) {
+ (void)velocity;
+ bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
+ v->gate = 0;
+}
+
+static unsigned char get_note(void *BW_RESTRICT voice) {
+ bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
+ return v->note;
+}
+
+static char is_free(void *BW_RESTRICT voice) {
+ bw_example_synthpp_poly_voice *v = (bw_example_synthpp_poly_voice *)voice;
+ bw_env_gen_phase phase = v->instance->vcaEnvGen.getPhase(v->index);
+ return !v->gate && phase == bw_env_gen_phase_off;
+}
+
+#include
+void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const float** x, float** y, int n_samples) {
+ // FIXME: control-rate modulations are asynchronous here...
+ // it's all good as long as hosts gives us buffers whose length is a multiple of 32,
+ // otherwise it's probably still ok but a bit "swingy"
+
+ (void)x;
+
+ static bw_voice_alloc_opts alloc_opts = { bw_voice_alloc_mode_low, note_on, note_off, get_note, is_free };
+ void *voices[N_VOICES];
+ for (int i = 0; i < N_VOICES; i++)
+ voices[i] = (void *)(instance->voices + i);
+ bw_voice_alloc(&alloc_opts, &instance->noteQueue.queue, voices, N_VOICES);
+ bw_note_queue_clear(&instance->noteQueue.queue);
+
+ const float df1 =
+ 6.f * instance->params[p_vco1_coarse] - 3.f
+ + 2.f * instance->pitch_bend - 1.f
+ + 8.333333333333333e-2f * (2.f * (instance->params[p_master_tune] + instance->params[p_vco1_fine]) - 71.f);
+ const float df2 =
+ 6.f * instance->params[p_vco2_coarse] - 3.f
+ + 2.f * instance->pitch_bend - 1.f
+ + 8.333333333333333e-2f * (2.f * (instance->params[p_master_tune] + instance->params[p_vco2_fine]) - 71.f);
+ const float df3 =
+ 6.f * instance->params[p_vco3_coarse] - 3.f
+ + 2.f * instance->pitch_bend - 1.f
+ + 8.333333333333333e-2f * (2.f * (instance->params[p_master_tune] + instance->params[p_vco3_fine]) - 71.f);
+ for (int i = 0; i < N_VOICES; i++) {
+ int n3 = instance->params[p_vco3_kbd] >= 0.5f ? instance->voices[i].note : 0;
+ instance->voices[i].vco1PhaseGen.setFrequency(440.f * bw_pow2f_3(df1 + 8.333333333333333e-2f * instance->voices[i].note));
+ instance->voices[i].vco2PhaseGen.setFrequency(440.f * bw_pow2f_3(df2 + 8.333333333333333e-2f * instance->voices[i].note));
+ instance->voices[i].vco3PhaseGen.setFrequency(440.f * bw_pow2f_3(df3 + 8.333333333333333e-2f * n3));
+ }
+
+ const float vcf_mod_k = 0.3f * instance->params[p_vcf_mod];
+
+ std::array b0, b1, b2, b3, b4, na;
+ std::array cb0, cb1, cb2, cb3, cb4;
+ std::array gates;
+ for (int j = 0; j < N_VOICES; j++) {
+ b0.data()[j] = instance->voices[j].buf[0];
+ b1.data()[j] = instance->voices[j].buf[1];
+ b2.data()[j] = instance->voices[j].buf[2];
+ b3.data()[j] = instance->voices[j].buf[3];
+ b4.data()[j] = instance->voices[j].buf[4];
+ na.data()[j] = nullptr;
+ cb0.data()[j] = instance->voices[j].buf[0];
+ cb1.data()[j] = instance->voices[j].buf[1];
+ cb2.data()[j] = instance->voices[j].buf[2];
+ cb3.data()[j] = instance->voices[j].buf[3];
+ cb4.data()[j] = instance->voices[j].buf[4];
+ gates.data()[j] = instance->voices[j].gate;
+ }
+
+ for (int i = 0; i < n_samples; i += BUFFER_SIZE) {
+ float *out = y[0] + i;
+ int n = bw_minf(n_samples - i, BUFFER_SIZE);
+
+ for (int j = 0; j < N_VOICES; j++)
+ instance->voices[j].vco3PhaseGen.process({nullptr}, {b0.data()[j]}, {b1.data()[j]}, n);
+ if (instance->params[p_vco3_waveform] >= (1.f / 4.f + 1.f / 2.f)) {
+ instance->vco3OscTri.process(cb0, cb1, b0, n);
+ instance->vco3OscPulse.reset();
+ } else if (instance->params[p_vco3_waveform] >= (1.f / 4.f)) {
+ instance->vco3OscPulse.process(cb0, cb1, b0, n);
+ instance->vco3OscTri.reset();
+ } else {
+ instance->vco3OscSaw.process(cb0, cb1, b0, n);
+ instance->vco3OscPulse.reset();
+ instance->vco3OscTri.reset();
+ }
+
+ instance->noiseGen.process(b1, n);
+ if (instance->params[p_noise_color] >= 0.5f)
+ instance->pinkFilt.process(cb1, b1, n);
+ else
+ instance->pinkFilt.reset(); // FIXME: calling this here is sloppy coding
+ for (int j = 0; j < N_VOICES; j++)
+ bw_buf_scale(b1.data()[j], b1.data()[j], 5.f, n);
+
+ float vcf_mod[N_VOICES];
+ for (int j = 0; j < N_VOICES; j++) {
+ for (int k = 0; k < n; k++)
+ b2.data()[j][k] = instance->mod_wheel * (b0.data()[j][k] + instance->params[p_mod_mix] * (b1.data()[j][k] - b0.data()[j][k]));
+ vcf_mod[j] = vcf_mod_k * b2.data()[j][0];
+ }
+
+ for (int j = 0; j < N_VOICES; j++) {
+ bw_buf_scale(b3.data()[j], b2.data()[j], instance->params[p_vco1_mod], n);
+ instance->voices[j].vco1PhaseGen.process({b3.data()[j]}, {b3.data()[j]}, {b4.data()[j]}, n);
+ }
+ if (instance->params[p_vco1_waveform] >= (1.f / 4.f + 1.f / 2.f)) {
+ instance->vco1OscTri.process(cb3, cb4, b3, n);
+ instance->vco1OscPulse.reset();
+ } else if (instance->params[p_vco1_waveform] >= (1.f / 4.f)) {
+ instance->vco1OscPulse.process(cb3, cb4, b3, n);
+ instance->vco1OscTri.reset();
+ } else {
+ instance->vco1OscSaw.process(cb3, cb4, b3, n);
+ instance->vco1OscPulse.reset();
+ instance->vco1OscTri.reset();
+ }
+
+ for (int j = 0; j < N_VOICES; j++) {
+ bw_buf_scale(b2.data()[j], b2.data()[j], instance->params[p_vco2_mod], n);
+ instance->voices[j].vco2PhaseGen.process({b2.data()[j]}, {b2.data()[j]}, {b4.data()[j]}, n);
+ }
+ if (instance->params[p_vco2_waveform] >= (1.f / 4.f + 1.f / 2.f)) {
+ instance->vco2OscTri.process(cb2, cb4, b2, n);
+ instance->vco2OscPulse.reset();
+ } else if (instance->params[p_vco2_waveform] >= (1.f / 4.f)) {
+ instance->vco2OscPulse.process(cb2, cb4, b2, n);
+ instance->vco2OscTri.reset();
+ } else {
+ instance->vco2OscSaw.process(cb2, cb4, b2, n);
+ instance->vco2OscPulse.reset();
+ instance->vco2OscTri.reset();
+ }
+
+ instance->vco1Gain.process(cb3, b3, n);
+ instance->vco2Gain.process(cb2, b2, n);
+ instance->vco3Gain.process(cb0, b0, n);
+ instance->noiseGain.process(cb1, b1, n);
+ for (int j = 0; j < N_VOICES; j++) {
+ bw_buf_mix(b0.data()[j], b0.data()[j], b2.data()[j], n);
+ bw_buf_mix(b0.data()[j], b0.data()[j], b3.data()[j], n);
+ }
+
+ instance->oscFilt.process(cb0, b0, n);
+
+ const float k = instance->params[p_noise_color] >= 0.5f
+ ? 6.f * instance->noiseGen.getScalingK() * instance->pinkFilt.getScalingK()
+ : 0.1f * instance->noiseGen.getScalingK();
+ for (int j = 0; j < N_VOICES; j++) {
+ bw_buf_scale(b1.data()[j], b1.data()[j], k, n);
+ bw_buf_mix(b0.data()[j], b0.data()[j], b1.data()[j], n);
+ }
+
+ instance->vcfEnvGen.process(gates, na, n);
+ for (int j = 0; j < N_VOICES; j++) {
+ float v = instance->params[p_vcf_cutoff] + instance->params[p_vcf_contour] * instance->vcfEnvGen.getYZ1(j) + vcf_mod[j];
+ float cutoff = 20.f + (20e3f - 20.f) * v * v * v;
+ if (instance->params[p_vcf_kbd_ctrl] >= (1.f / 6.f + 2.f / 3.f))
+ cutoff *= bw_pow2f_3(8.333333333333333e-2f * (instance->voices[j].note - 60));
+ else if (instance->params[p_vcf_kbd_ctrl] >= (1.f / 6.f + 1.f / 3.f))
+ cutoff *= bw_pow2f_3((0.793700525984100f * 8.333333333333333e-2f) * (instance->voices[j].note - 60));
+ else if (instance->params[p_vcf_kbd_ctrl] >= (1.f / 6.f + 2.f / 3.f))
+ cutoff *= bw_pow2f_3((0.629960524947437f * 8.333333333333333e-2f) * (instance->voices[j].note - 60));
+ // otherwise no kbd control
+ instance->voices[j].vcf.setCutoff(bw_clipf(cutoff, 20.f, 20e3f));
+ instance->voices[j].vcf.process({b0.data()[j]}, {b0.data()[j]}, {nullptr}, {nullptr}, n);
+ }
+
+ instance->vcaEnvGen.process(gates, b1, n);
+ for (int j = 0; j < N_VOICES; j++)
+ bw_buf_mul(b0.data()[j], b0.data()[j], b1.data()[j], n);
+
+ bw_buf_fill(out, 0.f, n);
+ for (int j = 0; j < N_VOICES; j++)
+ bw_buf_mix(out, out, b0.data()[j], n);
+
+ instance->a440PhaseGen.process({nullptr}, {instance->buf}, {nullptr}, n);
+ oscSinProcess<1>({instance->buf}, {instance->buf}, n);
+ if (instance->params[p_a440] >= 0.5f)
+ bw_buf_mix(out, out, instance->buf, n);
+
+ instance->gain.process({out}, {out}, n);
+ instance->ppm.process({out}, {nullptr}, n);
+ }
+}
+
+void bw_example_synthpp_poly_set_parameter(bw_example_synthpp_poly *instance, int index, float value) {
+ instance->params[index] = value;
+ switch (index) {
+ case p_volume:
+ instance->gain.setGainLin(value * value * value);
+ break;
+ case p_portamento:
+ for (int i = 0; i < N_VOICES; i++) {
+ instance->voices[i].vco1PhaseGen.setPortamentoTau(value);
+ instance->voices[i].vco2PhaseGen.setPortamentoTau(value);
+ instance->voices[i].vco3PhaseGen.setPortamentoTau(value);
+ }
+ break;
+ case p_vco1_pw_slope:
+ instance->vco1OscPulse.setPulseWidth(value);
+ instance->vco1OscTri.setSlope(bw_clipf(value, 0.001f, 0.999f));
+ break;
+ case p_vco1_level:
+ instance->vco1Gain.setGainLin(value * value * value);
+ break;
+ case p_vco2_pw_slope:
+ instance->vco2OscPulse.setPulseWidth(value);
+ instance->vco2OscTri.setSlope(bw_clipf(value, 0.001f, 0.999f));
+ break;
+ case p_vco2_level:
+ instance->vco2Gain.setGainLin(value * value * value);
+ break;
+ case p_vco3_pw_slope:
+ instance->vco3OscPulse.setPulseWidth(value);
+ instance->vco3OscTri.setSlope(bw_clipf(value, 0.001f, 0.999f));
+ break;
+ case p_vco3_level:
+ instance->vco3Gain.setGainLin(value * value * value);
+ break;
+ case p_noise_level:
+ instance->noiseGain.setGainLin(value * value * value);
+ break;
+ case p_vcf_Q:
+ {
+ const float v = 0.5f + 9.5f * value;
+ for (int i = 0; i < N_VOICES; i++)
+ instance->voices[i].vcf.setQ(v);
+ break;
+ }
+ case p_vcf_attack:
+ instance->vcfEnvGen.setAttack(value);
+ break;
+ case p_vcf_decay:
+ instance->vcfEnvGen.setDecay(value);
+ break;
+ case p_vcf_sustain:
+ instance->vcfEnvGen.setSustain(value);
+ break;
+ case p_vcf_release:
+ instance->vcfEnvGen.setRelease(value);
+ break;
+ case p_vca_attack:
+ instance->vcaEnvGen.setAttack(value);
+ break;
+ case p_vca_decay:
+ instance->vcaEnvGen.setDecay(value);
+ break;
+ case p_vca_sustain:
+ instance->vcaEnvGen.setSustain(value);
+ break;
+ case p_vca_release:
+ instance->vcaEnvGen.setRelease(value);
+ break;
+ }
+}
+
+float bw_example_synthpp_poly_get_parameter(bw_example_synthpp_poly *instance, int index) {
+ if (index < p_n)
+ return instance->params[index];
+ const float v = instance->ppm.getYZ1(0);
+ return v < -200.f ? 0.f : bw_clipf(0.01666666666666666f * v + 1.f, 0.f, 1.f);
+}
+
+void bw_example_synthpp_poly_note_on(bw_example_synthpp_poly *instance, char note, char velocity) {
+ instance->noteQueue.add(note, velocity != 0, velocity, false);
+}
+
+void bw_example_synthpp_poly_note_off(bw_example_synthpp_poly *instance, char note) {
+ instance->noteQueue.add(note, false, 0, false);
+}
+
+void bw_example_synthpp_poly_pitch_bend(bw_example_synthpp_poly *instance, int value) {
+ instance->pitch_bend = (value - 0x2000) / (float)0x4000;
+}
+
+void bw_example_synthpp_poly_mod_wheel(bw_example_synthpp_poly *instance, char value) {
+ instance->mod_wheel = (float)value / 0x80;
+}
diff --git a/examples/synthpp_poly/src/bw_example_synthpp_poly.h b/examples/synthpp_poly/src/bw_example_synthpp_poly.h
new file mode 100644
index 0000000..efe5cfa
--- /dev/null
+++ b/examples/synthpp_poly/src/bw_example_synthpp_poly.h
@@ -0,0 +1,160 @@
+/*
+ * 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_SYNTHPP_MONO_H
+#define _BW_EXAMPLE_SYNTHPP_MONO_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace Brickworks;
+
+extern "C" {
+
+enum {
+ p_volume,
+ p_master_tune,
+ p_portamento,
+ p_mod_mix,
+ p_vco1_mod,
+ p_vco1_coarse,
+ p_vco1_fine,
+ p_vco1_waveform,
+ p_vco1_pw_slope,
+ p_vco1_level,
+ p_vco2_mod,
+ p_vco2_coarse,
+ p_vco2_fine,
+ p_vco2_waveform,
+ p_vco2_pw_slope,
+ p_vco2_level,
+ p_vco3_kbd,
+ p_vco3_coarse,
+ p_vco3_fine,
+ p_vco3_waveform,
+ p_vco3_pw_slope,
+ p_vco3_level,
+ p_noise_color,
+ p_noise_level,
+ p_vcf_mod,
+ p_vcf_kbd_ctrl,
+ p_vcf_cutoff,
+ p_vcf_Q,
+ p_vcf_contour,
+ p_vcf_attack,
+ p_vcf_decay,
+ p_vcf_sustain,
+ p_vcf_release,
+ p_vca_attack,
+ p_vca_decay,
+ p_vca_sustain,
+ p_vca_release,
+ p_a440,
+ p_n
+};
+
+#define BUFFER_SIZE 32
+#define N_VOICES 8
+
+struct _bw_example_synthpp_poly;
+typedef struct _bw_example_synthpp_poly bw_example_synthpp_poly;
+
+struct _bw_example_synthpp_poly_voice {
+ PhaseGen<1> vco1PhaseGen;
+ PhaseGen<1> vco2PhaseGen;
+ PhaseGen<1> vco3PhaseGen;
+ SVF<1> vcf;
+
+ unsigned char note;
+ char gate;
+
+ float buf[5][BUFFER_SIZE];
+
+ bw_example_synthpp_poly *instance;
+ int index;
+};
+typedef struct _bw_example_synthpp_poly_voice bw_example_synthpp_poly_voice;
+
+struct _bw_example_synthpp_poly {
+ // Sub-components
+ NoteQueue noteQueue;
+ OscSaw vco1OscSaw;
+ OscPulse vco1OscPulse;
+ OscTri vco1OscTri;
+ Gain vco1Gain;
+ OscSaw vco2OscSaw;
+ OscPulse vco2OscPulse;
+ OscTri vco2OscTri;
+ Gain vco2Gain;
+ OscSaw vco3OscSaw;
+ OscPulse vco3OscPulse;
+ OscTri vco3OscTri;
+ Gain vco3Gain;
+ OscFilt oscFilt;
+ NoiseGen noiseGen;
+ PinkFilt pinkFilt;
+ Gain noiseGain;
+ EnvGen vcfEnvGen;
+ EnvGen vcaEnvGen;
+ PhaseGen<1> a440PhaseGen;
+ Gain<1> gain;
+ PPM<1> ppm;
+
+ bw_example_synthpp_poly_voice voices[N_VOICES];
+
+ // Parameters
+ float params[p_n];
+
+ // States
+ uint64_t rand_state;
+ float pitch_bend;
+ float mod_wheel;
+
+ // Buffers
+ float buf[BUFFER_SIZE];
+
+ _bw_example_synthpp_poly() : noiseGen(&rand_state) {}
+};
+
+void bw_example_synthpp_poly_init(bw_example_synthpp_poly *instance);
+void bw_example_synthpp_poly_set_sample_rate(bw_example_synthpp_poly *instance, float sample_rate);
+void bw_example_synthpp_poly_reset(bw_example_synthpp_poly *instance);
+void bw_example_synthpp_poly_process(bw_example_synthpp_poly *instance, const float** x, float** y, int n_samples);
+void bw_example_synthpp_poly_set_parameter(bw_example_synthpp_poly *instance, int index, float value);
+float bw_example_synthpp_poly_get_parameter(bw_example_synthpp_poly *instance, int index);
+void bw_example_synthpp_poly_note_on(bw_example_synthpp_poly *instance, char note, char velocity);
+void bw_example_synthpp_poly_note_off(bw_example_synthpp_poly *instance, char note);
+void bw_example_synthpp_poly_pitch_bend(bw_example_synthpp_poly *instance, int value);
+void bw_example_synthpp_poly_mod_wheel(bw_example_synthpp_poly *instance, char value);
+
+}
+
+#endif
diff --git a/examples/synthpp_poly/src/config.h b/examples/synthpp_poly/src/config.h
new file mode 100644
index 0000000..9d36319
--- /dev/null
+++ b/examples/synthpp_poly/src/config.h
@@ -0,0 +1,125 @@
+/*
+ * 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_synthpp_poly"
+#define PLUGIN_VERSION "0.5.0"
+
+#define NUM_BUSES_IN 0
+#define NUM_BUSES_OUT 1
+#define NUM_CHANNELS_IN 0
+#define NUM_CHANNELS_OUT 1
+
+static struct config_io_bus config_buses_out[NUM_BUSES_OUT] = {
+ { "Audio out", 1, 0, 0, IO_MONO }
+};
+
+#define NUM_PARAMETERS 39
+
+static struct config_parameter config_parameters[NUM_PARAMETERS] = {
+ { "Volume", "Volume", "", 0, 0, 0, 0.5f },
+ { "Master tune", "Master tune", "st", 0, 0, 0, 0.5f },
+ { "Portamento", "Portamento", "s", 0, 0, 0, 0.f },
+ { "Modulation mix", "Mod mix", "%", 0, 0, 0, 0.f },
+ { "VCO1 modulation", "VCO1 mod", "%", 0, 0, 0, 0.f },
+ { "VCO1 coarse", "VCO1 coarse", "", 0, 0, 6, 0.5f },
+ { "VCO1 fine", "VCO1 fine", "st", 0, 0, 0, 0.5f },
+ { "VCO1 waveform", "VCO1 wave", "", 0, 0, 2, 0.f },
+ { "VCO1 pulse width/slope", "VCO1 pw/slope", "%", 0, 0, 0, 0.5f },
+ { "VCO1 level", "VCO1 level", "%", 0, 0, 0, 1.f },
+ { "VCO2 modulation", "VCO2 mod", "%", 0, 0, 0, 0.f },
+ { "VCO2 coarse", "VCO2 coarse", "", 0, 0, 6, 0.5f },
+ { "VCO2 fine", "VCO2 fine", "st", 0, 0, 0, 0.5f },
+ { "VCO2 waveform", "VCO2 wave", "", 0, 0, 2, 0.f },
+ { "VCO2 pulse width/slope", "VCO2 pw/slope", "%", 0, 0, 0, 0.5f },
+ { "VCO2 level", "VCO2 level", "%", 0, 0, 0, 0.f },
+ { "VCO3 kyboard control", "VCO3 kbd ctrl", "", 0, 0, 1, 1.f },
+ { "VCO3 coarse", "VCO3 coarse", "", 0, 0, 6, 0.5f },
+ { "VCO3 fine", "VCO3 fine", "st", 0, 0, 0, 0.5f },
+ { "VCO3 waveform", "VCO3 wave", "", 0, 0, 2, 0.f },
+ { "VCO3 pulse width/slope", "VCO3 pw/slope", "%", 0, 0, 0, 0.5f },
+ { "VCO3 level", "VCO3 level", "%", 0, 0, 0, 0.f },
+ { "Noise color", "Noise color", "", 0, 0, 1, 0.f },
+ { "Noise level", "Noise level", "%", 0, 0, 0, 0.f },
+ { "VCF modulation", "VCF mod", "%", 0, 0, 0, 0.f },
+ { "VCF keyboard control", "VCF kbd ctrl", "", 0, 0, 3, 0.f },
+ { "VCF cutoff", "VCF cutoff", "Hz", 0, 0, 0, 1.f },
+ { "VCF Q", "VCF Q", "", 0, 0, 0, 0.f },
+ { "VCF contour", "VCF contour", "%", 0, 0, 0, 0.f },
+ { "VCF attack", "VCF attack", "s", 0, 0, 0, 0.f },
+ { "VCF decay", "VCF decay", "s", 0, 0, 0, 0.f },
+ { "VCF sustain", "VCF sustain", "%", 0, 0, 0, 1.f },
+ { "VCF release", "VCF release", "s", 0, 0, 0, 0.f },
+ { "VCA attack", "VCA attack", "s", 0, 0, 0, 0.f },
+ { "VCA decay", "VCA decay", "s", 0, 0, 0, 0.f },
+ { "VCA sustain", "VCA sustain", "%", 0, 0, 0, 1.f },
+ { "VCA release", "VCA release", "s", 0, 0, 0, 0.f },
+ { "A440", "A440", "", 0, 0, 1, 0.f },
+ { "Level", "Level", "", 1, 0, 0, 0.f }
+};
+
+// Internal API
+
+#include "bw_example_synthpp_poly.h"
+
+#define P_TYPE bw_example_synthpp_poly
+#define P_INIT bw_example_synthpp_poly_init
+#define P_SET_SAMPLE_RATE bw_example_synthpp_poly_set_sample_rate
+#define P_RESET bw_example_synthpp_poly_reset
+#define P_PROCESS bw_example_synthpp_poly_process
+#define P_SET_PARAMETER bw_example_synthpp_poly_set_parameter
+#define P_GET_PARAMETER bw_example_synthpp_poly_get_parameter
+#define P_NOTE_ON bw_example_synthpp_poly_note_on
+#define P_NOTE_OFF bw_example_synthpp_poly_note_off
+#define P_PITCH_BEND bw_example_synthpp_poly_pitch_bend
+#define P_MOD_WHEEL bw_example_synthpp_poly_mod_wheel
+
+#endif
diff --git a/examples/synthpp_poly/vst3/Makefile b/examples/synthpp_poly/vst3/Makefile
new file mode 100644
index 0000000..b7ec214
--- /dev/null
+++ b/examples/synthpp_poly/vst3/Makefile
@@ -0,0 +1,6 @@
+ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+
+NAME := bw_example_synthpp_poly
+SOURCES = ${SOURCES_COMMON} ${ROOT_DIR}/../src/bw_example_synthpp_poly.cpp
+
+include ${ROOT_DIR}/../../common/vst3/vst3.mk
diff --git a/examples/synthpp_poly/vst3/config_vst3.h b/examples/synthpp_poly/vst3/config_vst3.h
new file mode 100644
index 0000000..8e8de04
--- /dev/null
+++ b/examples/synthpp_poly/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 "Instrument|Synth"
+
+#define PLUGIN_GUID_1 0x7f75d73b
+#define PLUGIN_GUID_2 0xf5aa4d9d
+#define PLUGIN_GUID_3 0xba2b1d54
+#define PLUGIN_GUID_4 0x83d45cfe
+
+#define CTRL_GUID_1 0x183b9664
+#define CTRL_GUID_2 0xaca74eaf
+#define CTRL_GUID_3 0xad09b16b
+#define CTRL_GUID_4 0x5d702155
+
+#endif
diff --git a/include/bwpp_ap1.h b/include/bwpp_ap1.h
index 88c13c0..4e39112 100644
--- a/include/bwpp_ap1.h
+++ b/include/bwpp_ap1.h
@@ -46,26 +46,26 @@ namespace Brickworks {
};
template
- AP1::AP1() {
+ inline AP1::AP1() {
bw_ap1_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void AP1::setSampleRate(float sampleRate) {
+ inline void AP1::setSampleRate(float sampleRate) {
bw_ap1_set_sample_rate(&coeffs, sampleRate);
}
template
- void AP1::reset(float x0) {
+ inline void AP1::reset(float x0) {
bw_ap1_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_ap1_reset_state(&coeffs, states + i, x0);
}
template
- void AP1::process(
+ inline void AP1::process(
std::array x,
std::array y,
int nSamples) {
@@ -73,7 +73,7 @@ namespace Brickworks {
}
template
- void AP1::setCutoff(float value) {
+ inline void AP1::setCutoff(float value) {
bw_ap1_set_cutoff(&coeffs, value);
}
}
diff --git a/include/bwpp_ap2.h b/include/bwpp_ap2.h
index 8f71603..5ec670f 100644
--- a/include/bwpp_ap2.h
+++ b/include/bwpp_ap2.h
@@ -47,26 +47,26 @@ namespace Brickworks {
};
template
- AP2::AP2() {
+ inline AP2::AP2() {
bw_ap2_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void AP2::setSampleRate(float sampleRate) {
+ inline void AP2::setSampleRate(float sampleRate) {
bw_ap2_set_sample_rate(&coeffs, sampleRate);
}
template
- void AP2::reset(float x0) {
+ inline void AP2::reset(float x0) {
bw_ap2_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_ap2_reset_state(&coeffs, states + i, x0);
}
template
- void AP2::process(
+ inline void AP2::process(
std::array x,
std::array y,
int nSamples) {
@@ -74,12 +74,12 @@ namespace Brickworks {
}
template
- void AP2::setCutoff(float value) {
+ inline void AP2::setCutoff(float value) {
bw_ap2_set_cutoff(&coeffs, value);
}
template
- void AP2::setQ(float value) {
+ inline void AP2::setQ(float value) {
bw_ap2_set_Q(&coeffs, value);
}
}
diff --git a/include/bwpp_balance.h b/include/bwpp_balance.h
index b056655..e488755 100644
--- a/include/bwpp_balance.h
+++ b/include/bwpp_balance.h
@@ -46,22 +46,22 @@ namespace Brickworks {
};
template
- Balance::Balance() {
+ inline Balance::Balance() {
bw_balance_init(&coeffs);
}
template
- void Balance::setSampleRate(float sampleRate) {
+ inline void Balance::setSampleRate(float sampleRate) {
bw_balance_set_sample_rate(&coeffs, sampleRate);
}
template
- void Balance::reset() {
+ inline void Balance::reset() {
bw_balance_reset_coeffs(&coeffs);
}
template
- void Balance::process(
+ inline void Balance::process(
std::array x_l,
std::array x_r,
std::array y_l,
@@ -71,7 +71,7 @@ namespace Brickworks {
}
template
- void Balance::setBalance(float value) {
+ inline void Balance::setBalance(float value) {
bw_balance_set_balance(&coeffs, value);
}
}
diff --git a/include/bwpp_bd_reduce.h b/include/bwpp_bd_reduce.h
index 85f7764..41f0ae4 100644
--- a/include/bwpp_bd_reduce.h
+++ b/include/bwpp_bd_reduce.h
@@ -43,17 +43,17 @@ namespace Brickworks {
};
template
- BDReduce::BDReduce() {
+ inline BDReduce::BDReduce() {
bw_bd_reduce_init(&coeffs);
}
template
- void BDReduce::reset() {
+ inline void BDReduce::reset() {
bw_bd_reduce_reset_coeffs(&coeffs);
}
template
- void BDReduce::process(
+ inline void BDReduce::process(
std::array x,
std::array y,
int nSamples) {
@@ -61,7 +61,7 @@ namespace Brickworks {
}
template
- void BDReduce::setBitDepth(char value) {
+ inline void BDReduce::setBitDepth(char value) {
bw_bd_reduce_set_bit_depth(&coeffs, value);
}
}
diff --git a/include/bwpp_clip.h b/include/bwpp_clip.h
index 8380262..aa83e4a 100644
--- a/include/bwpp_clip.h
+++ b/include/bwpp_clip.h
@@ -48,26 +48,26 @@ namespace Brickworks {
};
template
- Clip::Clip() {
+ inline Clip::Clip() {
bw_clip_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void Clip::setSampleRate(float sampleRate) {
+ inline void Clip::setSampleRate(float sampleRate) {
bw_clip_set_sample_rate(&coeffs, sampleRate);
}
template
- void Clip::reset() {
+ inline void Clip::reset() {
bw_clip_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_clip_reset_state(&coeffs, states + i);
}
template
- void Clip::process(
+ inline void Clip::process(
std::array x,
std::array y,
int nSamples) {
@@ -75,17 +75,17 @@ namespace Brickworks {
}
template
- void Clip::setBias(float value) {
+ inline void Clip::setBias(float value) {
bw_clip_set_bias(&coeffs, value);
}
template
- void Clip::setGain(float value) {
+ inline void Clip::setGain(float value) {
bw_clip_set_gain(&coeffs, value);
}
template
- void Clip::setGainCompensation(bool value) {
+ inline void Clip::setGainCompensation(bool value) {
bw_clip_set_gain_compensation(&coeffs, value);
}
}
diff --git a/include/bwpp_comp.h b/include/bwpp_comp.h
index d12b780..a0e9e4d 100644
--- a/include/bwpp_comp.h
+++ b/include/bwpp_comp.h
@@ -53,26 +53,26 @@ namespace Brickworks {
};
template
- Comp::Comp() {
+ inline Comp::Comp() {
bw_comp_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void Comp::setSampleRate(float sampleRate) {
+ inline void Comp::setSampleRate(float sampleRate) {
bw_comp_set_sample_rate(&coeffs, sampleRate);
}
template
- void Comp::reset() {
+ inline void Comp::reset() {
bw_comp_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_comp_reset_state(&coeffs, states + i);
}
template
- void Comp::process(
+ inline void Comp::process(
std::array x,
std::array xSC,
std::array y,
@@ -81,37 +81,37 @@ namespace Brickworks {
}
template
- void Comp::setTreshLin(float value) {
+ inline void Comp::setTreshLin(float value) {
bw_comp_set_thresh_lin(&coeffs, value);
}
template
- void Comp::setTreshDBFS(float value) {
+ inline void Comp::setTreshDBFS(float value) {
bw_comp_set_thresh_dBFS(&coeffs, value);
}
template
- void Comp::setRatio(float value) {
+ inline void Comp::setRatio(float value) {
bw_comp_set_ratio(&coeffs, value);
}
template
- void Comp::setAttackTau(float value) {
+ inline void Comp::setAttackTau(float value) {
bw_comp_set_attack_tau(&coeffs, value);
}
template
- void Comp::setReleaseTau(float value) {
+ inline void Comp::setReleaseTau(float value) {
bw_comp_set_release_tau(&coeffs, value);
}
template
- void Comp::setGainLin(float value) {
+ inline void Comp::setGainLin(float value) {
bw_comp_set_gain_lin(&coeffs, value);
}
template
- void Comp::setGainDB(float value) {
+ inline void Comp::setGainDB(float value) {
bw_comp_set_gain_dB(&coeffs, value);
}
}
diff --git a/include/bwpp_dist.h b/include/bwpp_dist.h
index 4cbe75a..80f78dd 100644
--- a/include/bwpp_dist.h
+++ b/include/bwpp_dist.h
@@ -48,26 +48,26 @@ namespace Brickworks {
};
template
- Dist::Dist() {
+ inline Dist::Dist() {
bw_dist_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void Dist::setSampleRate(float sampleRate) {
+ inline void Dist::setSampleRate(float sampleRate) {
bw_dist_set_sample_rate(&coeffs, sampleRate);
}
template
- void Dist::reset() {
+ inline void Dist::reset() {
bw_dist_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_dist_reset_state(&coeffs, states + i);
}
template
- void Dist::process(
+ inline void Dist::process(
std::array x,
std::array y,
int nSamples) {
@@ -75,17 +75,17 @@ namespace Brickworks {
}
template
- void Dist::setDistortion(float value) {
+ inline void Dist::setDistortion(float value) {
bw_dist_set_distortion(&coeffs, value);
}
template
- void Dist::setTone(float value) {
+ inline void Dist::setTone(float value) {
bw_dist_set_tone(&coeffs, value);
}
template
- void Dist::setVolume(float value) {
+ inline void Dist::setVolume(float value) {
bw_dist_set_volume(&coeffs, value);
}
}
diff --git a/include/bwpp_drive.h b/include/bwpp_drive.h
index 2d799ce..ab73fef 100644
--- a/include/bwpp_drive.h
+++ b/include/bwpp_drive.h
@@ -48,26 +48,26 @@ namespace Brickworks {
};
template
- Drive::Drive() {
+ inline Drive::Drive() {
bw_drive_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void Drive::setSampleRate(float sampleRate) {
+ inline void Drive::setSampleRate(float sampleRate) {
bw_drive_set_sample_rate(&coeffs, sampleRate);
}
template
- void Drive::reset() {
+ inline void Drive::reset() {
bw_drive_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_drive_reset_state(&coeffs, states + i);
}
template
- void Drive::process(
+ inline void Drive::process(
std::array x,
std::array y,
int nSamples) {
@@ -75,17 +75,17 @@ namespace Brickworks {
}
template
- void Drive::setDrive(float value) {
+ inline void Drive::setDrive(float value) {
bw_drive_set_drive(&coeffs, value);
}
template
- void Drive::setTone(float value) {
+ inline void Drive::setTone(float value) {
bw_drive_set_tone(&coeffs, value);
}
template
- void Drive::setVolume(float value) {
+ inline void Drive::setVolume(float value) {
bw_drive_set_volume(&coeffs, value);
}
}
diff --git a/include/bwpp_drywet.h b/include/bwpp_drywet.h
index 6367ea6..5bb98ea 100644
--- a/include/bwpp_drywet.h
+++ b/include/bwpp_drywet.h
@@ -46,22 +46,22 @@ namespace Brickworks {
};
template
- DryWet::DryWet() {
+ inline DryWet::DryWet() {
bw_drywet_init(&coeffs);
}
template
- void DryWet::setSampleRate(float sampleRate) {
+ inline void DryWet::setSampleRate(float sampleRate) {
bw_drywet_set_sample_rate(&coeffs, sampleRate);
}
template
- void DryWet::reset() {
+ inline void DryWet::reset() {
bw_drywet_reset_coeffs(&coeffs);
}
template
- void DryWet::process(
+ inline void DryWet::process(
std::array x_dry,
std::array x_wet,
std::array y,
@@ -70,12 +70,12 @@ namespace Brickworks {
}
template
- void DryWet::setWet(float value) {
+ inline void DryWet::setWet(float value) {
bw_drywet_set_wet(&coeffs, value);
}
template
- void DryWet::setSmoothTau(float value) {
+ inline void DryWet::setSmoothTau(float value) {
bw_drywet_set_smooth_tau(&coeffs, value);
}
}
diff --git a/include/bwpp_env_follow.h b/include/bwpp_env_follow.h
index 4657099..2cc3017 100644
--- a/include/bwpp_env_follow.h
+++ b/include/bwpp_env_follow.h
@@ -49,26 +49,26 @@ namespace Brickworks {
};
template
- EnvFollow::EnvFollow() {
+ inline EnvFollow::EnvFollow() {
bw_env_follow_init(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
statesP[i] = states + i;
}
template
- void EnvFollow::setSampleRate(float sampleRate) {
+ inline void EnvFollow::setSampleRate(float sampleRate) {
bw_env_follow_set_sample_rate(&coeffs, sampleRate);
}
template
- void EnvFollow::reset() {
+ inline void EnvFollow::reset() {
bw_env_follow_reset_coeffs(&coeffs);
for (BW_SIZE_T i = 0; i < N_CHANNELS; i++)
bw_env_follow_reset_state(&coeffs, states + i);
}
template
- void EnvFollow::process(
+ inline void EnvFollow::process(
std::array x,
std::array y,
int nSamples) {
@@ -76,17 +76,17 @@ namespace Brickworks {
}
template
- void EnvFollow::setAttackTau(float value) {
+ inline void EnvFollow::setAttackTau(float value) {
bw_env_follow_set_attack_tau(&coeffs, value);
}
template
- void EnvFollow::setReleaseTau(float value) {
+ inline void EnvFollow::setReleaseTau(float value) {
bw_env_follow_set_release_tau(&coeffs, value);
}
template
- float EnvFollow