Browse Source

Rewrite ABC.

tags/v2.1.0
Andrew Belt 3 years ago
parent
commit
a0acea01b4
1 changed files with 48 additions and 97 deletions
  1. +48
    -97
      src/ABC.cpp

+ 48
- 97
src/ABC.cpp View File

@@ -3,7 +3,7 @@
using simd::float_4;

template <typename T>
static T clip4(T x) {
static T clip(T x) {
// Pade approximant of x/(1 + x^12)^(1/12)
const T limit = 1.16691853009184f;
x = clamp(x * 0.1f, -limit, limit);
@@ -54,115 +54,66 @@ struct ABC : Module {
configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level");
}

int processSection(simd::float_4* out, InputIds inputA, InputIds inputB, InputIds inputC, ParamIds levelB, ParamIds levelC) {

float_4 inA[4] = {};
float_4 inB[4] = {};
float_4 inC[4] = {};

int channelsA = inputs[inputA].getChannels();
int channelsB = inputs[inputB].getChannels();
int channelsC = inputs[inputC].getChannels();

// this sets the number of active engines (according to polyphony standard)
// NOTE: A*B + C has the number of active engines set by any one of the three inputs
int activeEngines = std::max(1, channelsA);
activeEngines = std::max(activeEngines, channelsB);
activeEngines = std::max(activeEngines, channelsC);

float mult_B = (2.f / 5.f) * exponentialBipolar80Pade_5_4(params[levelB].getValue());
float mult_C = exponentialBipolar80Pade_5_4(params[levelC].getValue());

if (inputs[inputA].isConnected()) {
for (int c = 0; c < activeEngines; c += 4)
inA[c / 4] = inputs[inputA].getPolyVoltageSimd<float_4>(c);
void processSection(const ProcessArgs& args, int& lastChannels, float_4* lastOut, ParamIds levelB, ParamIds levelC, InputIds inputA, InputIds inputB, InputIds inputC, OutputIds output, LightIds outLight) {
// Compute polyphony channels
int channels = std::max(lastChannels, inputs[inputA].getChannels());
channels = std::max(channels, inputs[inputB].getChannels());
channels = std::max(channels, inputs[inputC].getChannels());
lastChannels = channels;

// Get param levels
float gainB = 2.f * exponentialBipolar80Pade_5_4(params[levelB].getValue());
float gainC = exponentialBipolar80Pade_5_4(params[levelC].getValue());

for (int c = 0; c < channels; c += 4) {
// Get inputs
float_4 inA = inputs[inputA].getPolyVoltageSimd<float_4>(c);
float_4 inB = inputs[inputB].getNormalPolyVoltageSimd<float_4>(5.f, c) * gainB;
float_4 inC = inputs[inputC].getNormalPolyVoltageSimd<float_4>(10.f, c) * gainC;

// Compute and set output
float_4 out = inA * inB / 5.f + inC;
lastOut[c / 4] += out;
if (outputs[output].isConnected()) {
outputs[output].setChannels(channels);
outputs[output].setVoltageSimd(clip(lastOut[c / 4]), c);
}
}

if (inputs[inputB].isConnected()) {
for (int c = 0; c < activeEngines; c += 4)
inB[c / 4] = inputs[inputB].getPolyVoltageSimd<float_4>(c) * mult_B;
// Set lights
if (channels == 1) {
float b = lastOut[0][0];
lights[outLight + 0].setSmoothBrightness(b / 5.f, args.sampleTime);
lights[outLight + 1].setSmoothBrightness(-b / 5.f, args.sampleTime);
lights[outLight + 2].setBrightness(0.f);
}
else {
for (int c = 0; c < activeEngines; c += 4)
inB[c / 4] = 5.f * mult_B;
}

if (inputs[inputC].isConnected()) {
for (int c = 0; c < activeEngines; c += 4)
inC[c / 4] = inputs[inputC].getPolyVoltageSimd<float_4>(c) * mult_C;
// RMS of output
float b = 0.f;
for (int c = 0; c < channels; c++)
b += std::pow(lastOut[c / 4][c % 4], 2);
b = std::sqrt(b);
lights[outLight + 0].setBrightness(0.0f);
lights[outLight + 1].setBrightness(0.0f);
lights[outLight + 2].setBrightness(b);
}
else {
for (int c = 0; c < activeEngines; c += 4)
inC[c / 4] = 10.f * mult_C;
}

for (int c = 0; c < activeEngines; c += 4)
out[c / 4] = clip4(inA[c / 4] * inB[c / 4] + inC[c / 4]);

return activeEngines;
}

void process(const ProcessArgs& args) override {
int channels = 1;
float_4 out[4] = {};

// process upper section
float_4 out1[4] = {};
int activeEngines1 = 1;
if (outputs[OUT1_OUTPUT].isConnected() || outputs[OUT2_OUTPUT].isConnected()) {
activeEngines1 = processSection(out1, A1_INPUT, B1_INPUT, C1_INPUT, B1_LEVEL_PARAM, C1_LEVEL_PARAM);
}

float_4 out2[4] = {};
int activeEngines2 = 1;
// process lower section
if (outputs[OUT2_OUTPUT].isConnected()) {
activeEngines2 = processSection(out2, A2_INPUT, B2_INPUT, C2_INPUT, B2_LEVEL_PARAM, C2_LEVEL_PARAM);
}
// Section A
processSection(args, channels, out, B1_LEVEL_PARAM, C1_LEVEL_PARAM, A1_INPUT, B1_INPUT, C1_INPUT, OUT1_OUTPUT, OUT1_LIGHT);

// Set outputs
// Break summing if output A is patched
if (outputs[OUT1_OUTPUT].isConnected()) {
outputs[OUT1_OUTPUT].setChannels(activeEngines1);
for (int c = 0; c < activeEngines1; c += 4)
outputs[OUT1_OUTPUT].setVoltageSimd(out1[c / 4], c);
channels = 1;
std::memset(out, 0, sizeof(out));
}
else if (outputs[OUT2_OUTPUT].isConnected()) {

for (int c = 0; c < activeEngines1; c += 4)
out2[c / 4] += out1[c / 4];

activeEngines2 = std::max(activeEngines1, activeEngines2);

outputs[OUT2_OUTPUT].setChannels(activeEngines2);
for (int c = 0; c < activeEngines2; c += 4)
outputs[OUT2_OUTPUT].setVoltageSimd(out2[c / 4], c);
}

// Lights

if (activeEngines1 == 1) {
float b = out1[0].s[0];
lights[OUT1_LIGHT + 0].setSmoothBrightness(b / 5.f, args.sampleTime);
lights[OUT1_LIGHT + 1].setSmoothBrightness(-b / 5.f, args.sampleTime);
lights[OUT1_LIGHT + 2].setBrightness(0.f);
}
else {
float b = 10.f;
lights[OUT1_LIGHT + 0].setBrightness(0.0f);
lights[OUT1_LIGHT + 1].setBrightness(0.0f);
lights[OUT1_LIGHT + 2].setBrightness(b);
}

if (activeEngines2 == 1) {
float b = out2[0].s[0];
lights[OUT2_LIGHT + 0].setSmoothBrightness(b / 5.f, args.sampleTime);
lights[OUT2_LIGHT + 1].setSmoothBrightness(-b / 5.f, args.sampleTime);
lights[OUT2_LIGHT + 2].setBrightness(0.f);
}
else {
float b = 10.f;
lights[OUT2_LIGHT + 0].setBrightness(0.0f);
lights[OUT2_LIGHT + 1].setBrightness(0.0f);
lights[OUT2_LIGHT + 2].setBrightness(b);
}
// Section B
processSection(args, channels, out, B2_LEVEL_PARAM, C2_LEVEL_PARAM, A2_INPUT, B2_INPUT, C2_INPUT, OUT2_OUTPUT, OUT2_LIGHT);
}
};



Loading…
Cancel
Save