2024-07-27 22:53:03 +00:00
|
|
|
/*
|
|
|
|
BarrVerb reverb plugin
|
|
|
|
|
|
|
|
Copyright 2024 Gordon JC Pearce <gordonjcp@gjcp.net>
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "barrverb.hpp"
|
2024-07-29 20:56:06 +00:00
|
|
|
#include "rom.h"
|
2024-07-27 22:53:03 +00:00
|
|
|
|
|
|
|
START_NAMESPACE_DISTRHO
|
|
|
|
|
2024-08-22 22:05:08 +00:00
|
|
|
BarrVerb::BarrVerb() : Plugin(kParameterCount, 64, 0) { // one parameter, 64 programs, no states
|
2024-07-28 00:40:15 +00:00
|
|
|
lowpass = new float[getBufferSize()];
|
2024-07-29 20:56:06 +00:00
|
|
|
ram = new int16_t[16384];
|
2024-07-28 00:40:15 +00:00
|
|
|
|
2024-08-24 19:53:16 +00:00
|
|
|
bzero(lowpass, sizeof(float) * getBufferSize());
|
|
|
|
bzero(ram, sizeof(int16_t) * 16384);
|
2024-08-21 20:23:40 +00:00
|
|
|
|
2024-08-24 19:53:16 +00:00
|
|
|
/*
|
2024-07-28 00:40:15 +00:00
|
|
|
// calculate SVF params
|
2024-07-29 20:56:06 +00:00
|
|
|
// hardcoded values for now
|
|
|
|
float fc = 5019;
|
|
|
|
float F = fc / 48000; // assume 48kHz
|
|
|
|
float w = 2 * tan(3.14159 * F);
|
|
|
|
float a = w / 0.7845; // 1dB Chebyshev, 2-pole
|
|
|
|
float b = w * w;
|
|
|
|
|
|
|
|
// "corrected" SVF params, per Fons Adriaensen
|
|
|
|
c1_1 = (a + b) / (1 + a / 2 + b / 4);
|
|
|
|
c2_1 = b / (a + b);
|
|
|
|
d0_1 = c1_1 * c2_1 / 4;
|
|
|
|
|
|
|
|
fc = 9433;
|
|
|
|
F = fc / 48000; // assume 48kHz
|
|
|
|
w = 2 * tan(3.14159 * F);
|
|
|
|
a = w / 3.5594; // 1dB Chebyshev, 2-pole
|
|
|
|
b = w * w;
|
|
|
|
|
|
|
|
c1_2 = (a + b) / (1 + a / 2 + b / 4);
|
|
|
|
c2_2 = b / (a + b);
|
|
|
|
d0_2 = c1_2 * c2_2 / 4;*/
|
|
|
|
// calculate SVF params
|
2024-07-28 00:40:15 +00:00
|
|
|
// hardcoded values for now
|
|
|
|
|
|
|
|
float fc = 10000;
|
|
|
|
float F = fc / 48000; // assume 48kHz
|
|
|
|
float w = 2 * tan(3.14159 * F);
|
2024-07-28 21:00:07 +00:00
|
|
|
float a = w / 0.5412; // Butterworth 4-pole first stage
|
2024-07-28 00:40:15 +00:00
|
|
|
float b = w * w;
|
|
|
|
|
|
|
|
// "corrected" SVF params, per Fons Adriaensen
|
|
|
|
c1_1 = (a + b) / (1 + a / 2 + b / 4);
|
|
|
|
c2_1 = b / (a + b);
|
|
|
|
d0_1 = c1_1 * c2_1 / 4;
|
|
|
|
|
|
|
|
fc = 10000;
|
|
|
|
F = fc / 48000; // assume 48kHz
|
|
|
|
w = 2 * tan(3.14159 * F);
|
2024-07-28 21:00:07 +00:00
|
|
|
a = w / 1.3065; // Butterworth 4-pole second stage
|
2024-07-28 00:40:15 +00:00
|
|
|
b = w * w;
|
|
|
|
|
|
|
|
c1_2 = (a + b) / (1 + a / 2 + b / 4);
|
|
|
|
c2_2 = b / (a + b);
|
|
|
|
d0_2 = c1_2 * c2_2 / 4;
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initialisation functions
|
|
|
|
|
2024-08-22 22:05:08 +00:00
|
|
|
void BarrVerb::initParameter(uint32_t index, Parameter ¶meter) {
|
|
|
|
if (index == paramProgram) {
|
|
|
|
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
|
|
|
|
parameter.name = "Program";
|
|
|
|
parameter.symbol = "program";
|
|
|
|
parameter.ranges.def = 20.0f;
|
|
|
|
parameter.ranges.min = 1.0f;
|
|
|
|
parameter.ranges.max = 64.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BarrVerb::setParameterValue(uint32_t index, float value) {
|
|
|
|
if (index == paramProgram) {
|
|
|
|
program = value;
|
|
|
|
prog_offset = (((int)value-1) & 0x3f) << 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float BarrVerb::getParameterValue(uint32_t index) const {
|
|
|
|
if (index == paramProgram) {
|
|
|
|
return program;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-07-27 22:53:03 +00:00
|
|
|
void BarrVerb::initAudioPort(bool input, uint32_t index, AudioPort &port) {
|
2024-07-28 00:40:15 +00:00
|
|
|
port.groupId = kPortGroupStereo;
|
|
|
|
Plugin::initAudioPort(input, index, port);
|
2024-08-29 21:12:52 +00:00
|
|
|
|
|
|
|
if (input && index == 0) port.name="Left In";
|
|
|
|
if (input && index == 1) port.name="Right In";
|
|
|
|
if (!input && index == 0) port.name="Left Out";
|
|
|
|
if (!input && index == 1) port.name="Right Out";
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BarrVerb::initProgramName(uint32_t index, String &programName) {
|
2024-07-30 18:03:05 +00:00
|
|
|
|
2024-07-30 18:35:38 +00:00
|
|
|
programName = prog_name[index & 0x3f].c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BarrVerb::loadProgram(uint32_t index) {
|
|
|
|
prog_offset = (index & 0x3f) << 7;
|
2024-08-22 22:05:08 +00:00
|
|
|
program = index + 1;
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Processing functions
|
|
|
|
|
|
|
|
void BarrVerb::activate() {
|
2024-07-28 00:40:15 +00:00
|
|
|
// calculate filter coefficients
|
|
|
|
printf("called activate()\n");
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BarrVerb::deactivate() {
|
2024-07-28 00:40:15 +00:00
|
|
|
// zero out the outputs, maybe
|
|
|
|
printf("called deactivate()\n");
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BarrVerb::run(const float **inputs, float **outputs, uint32_t frames) {
|
2024-07-28 00:40:15 +00:00
|
|
|
// actual effects here
|
|
|
|
|
2024-07-29 20:56:06 +00:00
|
|
|
float x;
|
|
|
|
uint16_t opcode;
|
2024-07-28 00:40:15 +00:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < frames; i++) {
|
|
|
|
// smash to mono
|
|
|
|
lowpass[i] = (inputs[0][i] + inputs[1][i]) / 2;
|
|
|
|
|
|
|
|
// 10kHz lowpass filter, 2x oversampling
|
|
|
|
x = lowpass[i] - in_z1 - in_z2;
|
|
|
|
in_z2 += c2_1 * in_z1;
|
|
|
|
in_z1 += c1_1 * x;
|
|
|
|
|
|
|
|
x = (d0_1 * x + in_z2) - in_z12 - in_z22;
|
|
|
|
in_z22 += c2_2 * in_z12;
|
|
|
|
in_z12 += c1_2 * x;
|
|
|
|
lowpass[i] = d0_2 * x + in_z22;
|
2024-07-29 21:09:09 +00:00
|
|
|
}
|
2024-07-28 00:40:15 +00:00
|
|
|
|
2024-07-29 21:09:09 +00:00
|
|
|
// now run the DSP
|
|
|
|
for (uint32_t i=0; i < frames; i+=2) {
|
2024-07-29 20:56:06 +00:00
|
|
|
// run the actual DSP engine for each sample
|
|
|
|
for (uint8_t step = 0; step < 128; step++) {
|
2024-07-30 18:35:38 +00:00
|
|
|
opcode = rom[prog_offset + step];
|
2024-07-29 20:56:06 +00:00
|
|
|
switch (opcode & 0xc000) {
|
|
|
|
case 0x0000:
|
|
|
|
ai = ram[ptr];
|
|
|
|
li = acc + (ai >> 1);
|
|
|
|
break;
|
|
|
|
case 0x4000:
|
|
|
|
ai = ram[ptr];
|
|
|
|
li = (ai >> 1);
|
|
|
|
break;
|
|
|
|
case 0x8000:
|
|
|
|
ai = acc;
|
|
|
|
ram[ptr] = ai;
|
|
|
|
li = acc + (ai >> 1);
|
|
|
|
break;
|
|
|
|
case 0xc000:
|
|
|
|
ai = acc;
|
|
|
|
ram[ptr] = -ai;
|
|
|
|
li = -(ai >> 1);
|
|
|
|
break;
|
|
|
|
}
|
2024-08-21 20:23:40 +00:00
|
|
|
|
|
|
|
// clamp
|
|
|
|
if (ai > 2047) ai=2047;
|
|
|
|
if (ai < -2047) ai=-2047;
|
|
|
|
|
|
|
|
|
2024-07-29 20:56:06 +00:00
|
|
|
if (step == 0x00) {
|
|
|
|
// load RAM from ADC
|
2024-08-21 20:23:40 +00:00
|
|
|
ram[ptr] = (int)(lowpass[i] * 2048);
|
2024-07-29 20:56:06 +00:00
|
|
|
} else if (step == 0x60) {
|
|
|
|
// output right channel
|
2024-08-21 20:23:40 +00:00
|
|
|
//ai=0;
|
|
|
|
outputs[1][i] = (float)ai / 2048;
|
|
|
|
outputs[1][i+1] = (float)ai / 2048;
|
2024-07-29 21:09:09 +00:00
|
|
|
|
2024-07-29 20:56:06 +00:00
|
|
|
} else if (step == 0x70) {
|
|
|
|
// output left channel
|
2024-08-21 20:23:40 +00:00
|
|
|
//ai=0;
|
|
|
|
outputs[0][i] = (float)ai / 2048;
|
|
|
|
outputs[0][i+1] = (float)ai / 2048;
|
2024-07-29 20:56:06 +00:00
|
|
|
} else {
|
|
|
|
// everything else
|
|
|
|
// ADC and DAC operations don't affect the accumulator
|
|
|
|
// every other step ends with the accumulator latched from the Latch Input reg
|
|
|
|
acc = li;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 16kW of RAM
|
|
|
|
ptr += opcode & 0x3fff;
|
|
|
|
ptr &= 0x3fff;
|
|
|
|
}
|
2024-07-28 00:40:15 +00:00
|
|
|
}
|
2024-07-27 22:53:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// create the plugin
|
2024-07-28 00:40:15 +00:00
|
|
|
Plugin *createPlugin() { return new BarrVerb(); }
|
2024-07-29 21:09:09 +00:00
|
|
|
|
2024-07-27 22:53:03 +00:00
|
|
|
END_NAMESPACE_DISTRHO
|