From c22e022e6adfdb210f2f414bcd000c385c49352c Mon Sep 17 00:00:00 2001 From: hemmer <915048+hemmer@users.noreply.github.com> Date: Fri, 2 Jul 2021 17:28:08 +0100 Subject: [PATCH] Remove lots of boilerplate by using set/getPolyVoltageSimd instead * try to convert to idomatic Rack code * tightened up Percall/Hexmix polyphony logic --- src/ABC.cpp | 38 +++------------- src/DualAtenuverter.cpp | 4 +- src/EvenVCO.cpp | 58 ++++++------------------ src/HexmixVCA.cpp | 23 ++++++---- src/Mixer.cpp | 4 +- src/Percall.cpp | 24 ++++++---- src/Rampage.cpp | 98 +++++++++-------------------------------- src/SlewLimiter.cpp | 14 +----- 8 files changed, 77 insertions(+), 186 deletions(-) diff --git a/src/ABC.cpp b/src/ABC.cpp index 9e2387d..4092883 100644 --- a/src/ABC.cpp +++ b/src/ABC.cpp @@ -76,29 +76,13 @@ struct ABC : Module { float mult_C = exponentialBipolar80Pade_5_4(params[levelC].getValue()); if (inputs[inputA].isConnected()) { - // if monophonic, broadcast to number of active engines - if (channelsA == 1) { - for (int c = 0; c < activeEngines; c += 4) - inA[c / 4] = float_4(inputs[inputA].getVoltage()); - } - else { - for (int c = 0; c < channelsA; c += 4) - inA[c / 4] = inputs[inputA].getVoltageSimd(c); - } + for (int c = 0; c < activeEngines; c += 4) + inA[c / 4] = inputs[inputA].getPolyVoltageSimd(c); } if (inputs[inputB].isConnected()) { - // if monophonic, broadcast to number of active engines - if (channelsB == 1) { - for (int c = 0; c < activeEngines; c += 4) - inB[c / 4] = float_4(inputs[inputB].getVoltage()); - } - else { - for (int c = 0; c < channelsB; c += 4) - inB[c / 4] = inputs[inputB].getVoltageSimd(c); - } for (int c = 0; c < activeEngines; c += 4) - inB[c / 4] *= mult_B; + inB[c / 4] = inputs[inputB].getPolyVoltageSimd(c) * mult_B; } else { for (int c = 0; c < activeEngines; c += 4) @@ -106,18 +90,8 @@ struct ABC : Module { } if (inputs[inputC].isConnected()) { - // if monophonic, broadcast to number of active engines - if (channelsC == 1) { - for (int c = 0; c < activeEngines; c += 4) - inC[c / 4] = float_4(inputs[inputC].getVoltage()); - } - else { - for (int c = 0; c < channelsC; c += 4) - inC[c / 4] = inputs[inputC].getVoltageSimd(c); - } - for (int c = 0; c < activeEngines; c += 4) - inC[c / 4] *= mult_C; + inC[c / 4] = inputs[inputC].getPolyVoltageSimd(c) * mult_C; } else { for (int c = 0; c < activeEngines; c += 4) @@ -150,7 +124,7 @@ struct ABC : Module { if (outputs[OUT1_OUTPUT].isConnected()) { outputs[OUT1_OUTPUT].setChannels(activeEngines1); for (int c = 0; c < activeEngines1; c += 4) - out1[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); + outputs[OUT1_OUTPUT].setVoltageSimd(out1[c / 4], c); } else if (outputs[OUT2_OUTPUT].isConnected()) { @@ -161,7 +135,7 @@ struct ABC : Module { outputs[OUT2_OUTPUT].setChannels(activeEngines2); for (int c = 0; c < activeEngines2; c += 4) - out2[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); + outputs[OUT2_OUTPUT].setVoltageSimd(out2[c / 4], c); } // Lights diff --git a/src/DualAtenuverter.cpp b/src/DualAtenuverter.cpp index b32fbb4..7c8816f 100644 --- a/src/DualAtenuverter.cpp +++ b/src/DualAtenuverter.cpp @@ -61,10 +61,10 @@ struct DualAtenuverter : Module { outputs[OUT2_OUTPUT].setChannels(channels2); for (int c = 0; c < channels1; c += 4) { - out1[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); + outputs[OUT1_OUTPUT].setVoltageSimd(out1[c / 4], c); } for (int c = 0; c < channels2; c += 4) { - out2[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); + outputs[OUT2_OUTPUT].setVoltageSimd(out2[c / 4], c); } float light1 = outputs[OUT1_OUTPUT].getVoltageSum() / channels1; diff --git a/src/EvenVCO.cpp b/src/EvenVCO.cpp index ec708b3..181736c 100644 --- a/src/EvenVCO.cpp +++ b/src/EvenVCO.cpp @@ -63,8 +63,6 @@ struct EvenVCO : Module { int channels_pitch1 = inputs[PITCH1_INPUT].getChannels(); int channels_pitch2 = inputs[PITCH2_INPUT].getChannels(); - int channels_fm = inputs[FM_INPUT].getChannels(); - int channels_pwm = inputs[PWM_INPUT].getChannels(); int channels = 1; channels = std::max(channels, channels_pitch1); @@ -78,39 +76,18 @@ struct EvenVCO : Module { pitch[c / 4] = float_4(pitch_0); if (inputs[PITCH1_INPUT].isConnected()) { - // if pitch_1 monophonic, broadcast - if (channels_pitch1 == 1) { - for (int c = 0; c < channels; c += 4) - pitch[c / 4] += float_4(inputs[PITCH1_INPUT].getVoltage()); - } - else { - for (int c = 0; c < std::min(channels, channels_pitch1); c += 4) - pitch[c / 4] += inputs[PITCH1_INPUT].getVoltageSimd(c); - } + for (int c = 0; c < channels; c += 4) + pitch[c / 4] += inputs[PITCH1_INPUT].getPolyVoltageSimd(c); } if (inputs[PITCH2_INPUT].isConnected()) { - // if pitch_2 monophonic, broadcast - if (channels_pitch2 == 1) { - for (int c = 0; c < channels; c += 4) - pitch[c / 4] += float_4(inputs[PITCH2_INPUT].getVoltage()); - } - else { - for (int c = 0; c < std::min(channels, channels_pitch2); c += 4) - pitch[c / 4] += inputs[PITCH2_INPUT].getVoltageSimd(c); - } + for (int c = 0; c < channels; c += 4) + pitch[c / 4] += inputs[PITCH2_INPUT].getPolyVoltageSimd(c); } - if (inputs[FM_INPUT].isConnected()) { - // if FM is monophonic, broadcast - if (channels_fm == 1) { - for (int c = 0; c < channels; c += 4) - pitch[c / 4] += float_4(inputs[FM_INPUT].getVoltage() / 4.f); - } - else { - for (int c = 0; c < std::min(channels, channels_fm); c += 4) - pitch[c / 4] += inputs[FM_INPUT].getVoltageSimd(c) / 4.f; - } + if (inputs[FM_INPUT].isConnected()) { + for (int c = 0; c < channels; c += 4) + pitch[c / 4] += inputs[FM_INPUT].getPolyVoltageSimd(c) / 4.f; } float_4 freq[4]; @@ -126,14 +103,8 @@ struct EvenVCO : Module { pw[c / 4] = float_4(pw_0); if (inputs[PWM_INPUT].isConnected()) { - if (channels_pwm == 1) { - for (int c = 0; c < channels; c += 4) - pw[c / 4] += float_4(inputs[PWM_INPUT].getVoltage() / 5.f); - } - else { - for (int c = 0; c < std::min(channels, channels_pwm); c += 4) - pw[c / 4] += inputs[PWM_INPUT].getVoltageSimd(c) / 5.f; - } + for (int c = 0; c < channels; c += 4) + pw[c / 4] += inputs[PWM_INPUT].getPolyVoltageSimd(c) / 5.f; } const float_4 minPw_4 = float_4(0.05f); @@ -234,12 +205,11 @@ struct EvenVCO : Module { square[c / 4] *= 5.f; // Set outputs - - triOut[c / 4].store(outputs[TRI_OUTPUT].getVoltages(c)); - sine[c / 4].store(outputs[SINE_OUTPUT].getVoltages(c)); - even[c / 4].store(outputs[EVEN_OUTPUT].getVoltages(c)); - saw[c / 4].store(outputs[SAW_OUTPUT].getVoltages(c)); - square[c / 4].store(outputs[SQUARE_OUTPUT].getVoltages(c)); + outputs[TRI_OUTPUT].setVoltageSimd(triOut[c / 4], c); + outputs[SINE_OUTPUT].setVoltageSimd(sine[c / 4], c); + outputs[EVEN_OUTPUT].setVoltageSimd(even[c / 4], c); + outputs[SAW_OUTPUT].setVoltageSimd(saw[c / 4], c); + outputs[SQUARE_OUTPUT].setVoltageSimd(square[c / 4], c); } } }; diff --git a/src/HexmixVCA.cpp b/src/HexmixVCA.cpp index 350be50..8ea5059 100644 --- a/src/HexmixVCA.cpp +++ b/src/HexmixVCA.cpp @@ -1,6 +1,7 @@ #include "plugin.hpp" #include "Common.hpp" +using simd::float_4; static float gainFunction(float x, float shape) { float lin = x; @@ -49,7 +50,7 @@ struct HexmixVCA : Module { } void process(const ProcessArgs& args) override { - simd::float_4 mix[4] = {}; + float_4 mix[4] = {0.f}; int maxChannels = 1; // only calculate gains/shapes every 16 samples @@ -61,29 +62,33 @@ struct HexmixVCA : Module { } for (int row = 0; row < numRows; ++row) { - + bool finalRow = (row == numRows - 1); int channels = 1; - simd::float_4 in[4] = {}; + float_4 in[4] = {0.f}; bool inputIsConnected = inputs[IN_INPUT + row].isConnected(); if (inputIsConnected) { channels = inputs[row].getChannels(); - maxChannels = std::max(maxChannels, channels); + // if we're in "mixer" mode, an input only counts towards the main output polyphony count if it's + // not taken out of the mix (i.e. patched in). the final row should count towards polyphony calc. + if (finalRowIsMix && (finalRow || !outputs[OUT_OUTPUT + row].isConnected())) { + maxChannels = std::max(maxChannels, channels); + } + float cvGain = clamp(inputs[CV_INPUT + row].getNormalVoltage(10.f) / 10.f, 0.f, 1.f); float gain = gainFunction(cvGain, shapes[row]) * outputLevels[row]; for (int c = 0; c < channels; c += 4) { - in[c / 4] = simd::float_4::load(inputs[row].getVoltages(c)) * gain; + in[c / 4] = inputs[row].getVoltageSimd(c) * gain; } } - bool finalRow = (row == numRows - 1); if (!finalRow) { if (outputs[OUT_OUTPUT + row].isConnected()) { // if output is connected, we don't add to mix outputs[OUT_OUTPUT + row].setChannels(channels); for (int c = 0; c < channels; c += 4) { - in[c / 4].store(outputs[OUT_OUTPUT + row].getVoltages(c)); + outputs[OUT_OUTPUT + row].setVoltageSimd(in[c / 4], c); } } else if (finalRowIsMix) { @@ -105,14 +110,14 @@ struct HexmixVCA : Module { } for (int c = 0; c < maxChannels; c += 4) { - mix[c / 4].store(outputs[OUT_OUTPUT + row].getVoltages(c)); + outputs[OUT_OUTPUT + row].setVoltageSimd(mix[c / 4], c); } } else { // same as other rows outputs[OUT_OUTPUT + row].setChannels(channels); for (int c = 0; c < channels; c += 4) { - in[c / 4].store(outputs[OUT_OUTPUT + row].getVoltages(c)); + outputs[OUT_OUTPUT + row].setVoltageSimd(in[c / 4], c); } } } diff --git a/src/Mixer.cpp b/src/Mixer.cpp index f8e96ff..ae3d956 100644 --- a/src/Mixer.cpp +++ b/src/Mixer.cpp @@ -83,9 +83,9 @@ struct Mixer : Module { outputs[OUT2_OUTPUT].setChannels(out_channels); for (int c = 0; c < out_channels; c += 4) { - out[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); + outputs[OUT1_OUTPUT].setVoltageSimd(out[c / 4], c); out[c / 4] *= -1.f; - out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); + outputs[OUT2_OUTPUT].setVoltageSimd(out[c / 4], c); } if (out_channels == 1) { diff --git a/src/Percall.cpp b/src/Percall.cpp index 4e2b629..083213e 100644 --- a/src/Percall.cpp +++ b/src/Percall.cpp @@ -1,6 +1,7 @@ #include "plugin.hpp" #include "Common.hpp" +using simd::float_4; struct Percall : Module { enum ParamIds { @@ -28,7 +29,7 @@ struct Percall : Module { ADEnvelope envs[4]; - float gains[4] = {}; + float gains[4] = {0.f}; float strength = 1.0f; dsp::SchmittTrigger trigger[4]; @@ -76,7 +77,7 @@ struct Percall : Module { } } - simd::float_4 mix[4] = {}; + float_4 mix[4] = {0.f}; int maxPolyphonyChannels = 1; // Mixer channels @@ -95,19 +96,24 @@ struct Percall : Module { envs[i].process(args.sampleTime); int polyphonyChannels = 1; - simd::float_4 in[4] = {}; + float_4 in[4] = {}; bool inputIsConnected = inputs[CH_INPUTS + i].isConnected(); bool inputIsNormed = !inputIsConnected && (i % 2) && inputs[CH_INPUTS + i - 1].isConnected(); if ((inputIsConnected || inputIsNormed)) { - int channel_to_read_from = inputIsNormed ? CH_INPUTS + i - 1 : CH_INPUTS + i; - polyphonyChannels = inputs[channel_to_read_from].getChannels(); - maxPolyphonyChannels = std::max(maxPolyphonyChannels, polyphonyChannels); + int channelToReadFrom = inputIsNormed ? CH_INPUTS + i - 1 : CH_INPUTS + i; + polyphonyChannels = inputs[channelToReadFrom].getChannels(); + + // an input only counts towards the main output polyphony count if it's not taken out of the mix + // (i.e. an output is patched in). the final input should always count towards polyphony count. + if (i == CH_INPUTS_LAST || !outputs[CH_OUTPUTS + i].isConnected()) { + maxPolyphonyChannels = std::max(maxPolyphonyChannels, polyphonyChannels); + } // only process input audio if envelope is active if (envs[i].stage != ADEnvelope::STAGE_OFF) { float gain = gains[i] * envs[i].env; for (int c = 0; c < polyphonyChannels; c += 4) { - in[c / 4] = simd::float_4::load(inputs[channel_to_read_from].getVoltages(c)) * gain; + in[c / 4] = inputs[channelToReadFrom].getVoltageSimd(c) * gain; } } } @@ -117,7 +123,7 @@ struct Percall : Module { if (outputs[CH_OUTPUTS + i].isConnected()) { outputs[CH_OUTPUTS + i].setChannels(polyphonyChannels); for (int c = 0; c < polyphonyChannels; c += 4) { - in[c / 4].store(outputs[CH_OUTPUTS + i].getVoltages(c)); + outputs[CH_OUTPUTS + i].setVoltageSimd(in[c / 4], c); } } else { @@ -138,7 +144,7 @@ struct Percall : Module { } for (int c = 0; c < maxPolyphonyChannels; c += 4) { - mix[c / 4].store(outputs[CH_OUTPUTS + i].getVoltages(c)); + outputs[CH_OUTPUTS + i].setVoltageSimd(mix[c / 4], c); } } diff --git a/src/Rampage.cpp b/src/Rampage.cpp index c4061c2..5ca4dd5 100644 --- a/src/Rampage.cpp +++ b/src/Rampage.cpp @@ -135,11 +135,11 @@ struct Rampage : Module { // loop over two parts of Rampage: for (int part = 0; part < 2; part++) { - float_4 in[4]; - float_4 in_trig[4]; - float_4 riseCV[4]; - float_4 fallCV[4]; - float_4 cycle[4]; + float_4 in[4] = {0.f}; + float_4 in_trig[4] = {0.f}; + float_4 riseCV[4] = {0.f}; + float_4 fallCV[4] = {0.f}; + float_4 cycle[4] = {0.f}; // get parameters: float shape = params[SHAPE_A_PARAM + part].getValue(); @@ -169,47 +169,20 @@ struct Rampage : Module { } // read inputs: - if (inputs[IN_A_INPUT + part].isConnected()) { - // if IN__INPUT is monophonic, broadcast to the active number of engines (channels[part]) - if (inputs[IN_A_INPUT + part].getChannels() == 1) { - for (int c = 0; c < channels[part]; c += 4) - in[c / 4] = float_4(inputs[IN_A_INPUT + part].getVoltage()); - } - else { - for (int c = 0; c < channels[part]; c += 4) - in[c / 4] = inputs[IN_A_INPUT + part].getVoltageSimd(c); - } - } - else { - std::memset(in, 0, sizeof(in)); + if (inputs[IN_A_INPUT + part].isConnected()) { + for (int c = 0; c < channels[part]; c += 4) + in[c / 4] = inputs[IN_A_INPUT + part].getPolyVoltageSimd(c); } if (inputs[TRIGG_A_INPUT + part].isConnected()) { - // if TRIGG__INPUT is monophonic, broadcast to the active number of engines (channels[part]) - if (inputs[TRIGG_A_INPUT + part].getChannels() == 1) { - for (int c = 0; c < channels[part]; c += 4) - in_trig[c / 4] += float_4(inputs[TRIGG_A_INPUT + part].getVoltage()); - } - else { - for (int c = 0; c < channels[part]; c += 4) - in_trig[c / 4] += inputs[TRIGG_A_INPUT + part].getVoltageSimd(c); - } + for (int c = 0; c < channels[part]; c += 4) + in_trig[c / 4] += inputs[TRIGG_A_INPUT + part].getPolyVoltageSimd(c); } if (inputs[EXP_CV_A_INPUT + part].isConnected()) { - float_4 expCV[4]; - int expCVChannels = inputs[EXP_CV_A_INPUT + part].getChannels(); - // if EXP_CV__INPUT is monophonic, broadcast to the active number of engines (channels[part]) - if (expCVChannels == 1) { - for (int c = 0; c < channels[part]; c += 4) - expCV[c / 4] = float_4(inputs[EXP_CV_A_INPUT + part].getVoltage()); - } - else { - // otherwise read in the polyphonic expCV data, either to the number of active engines (channels[part]) - // or the number of channels of expCV, whichever is smaller - for (int c = 0; c < std::min(channels[part], expCVChannels); c += 4) - expCV[c / 4] = inputs[EXP_CV_A_INPUT + part].getVoltageSimd(c); - } + float_4 expCV[4]; + for (int c = 0; c < channels[part]; c += 4) + expCV[c / 4] = inputs[EXP_CV_A_INPUT + part].getPolyVoltageSimd(c); for (int c = 0; c < channels[part]; c += 4) { riseCV[c / 4] -= expCV[c / 4]; @@ -217,44 +190,17 @@ struct Rampage : Module { } } - const int riseCVChannels = inputs[RISE_CV_A_INPUT + part].getChannels(); - // if EXP_CV__INPUT is monophonic, broadcast to the active number of engines (channels[part]) - if (riseCVChannels == 1) { - for (int c = 0; c < channels[part]; c += 4) - riseCV[c / 4] += float_4(inputs[RISE_CV_A_INPUT + part].getVoltage()); - } - else { - // otherwise read in the polyphonic rise CV data, either to the number of active engines (channels[part]) - // or the number of channels of expCV, whichever is smaller - for (int c = 0; c < std::min(channels[part], riseCVChannels); c += 4) - riseCV[c / 4] += inputs[RISE_CV_A_INPUT + part].getVoltageSimd(c); - } - - const int fallCVChannels = inputs[FALL_CV_A_INPUT + part].getChannels(); - if (fallCVChannels == 1) { - for (int c = 0; c < channels[part]; c += 4) - fallCV[c / 4] += float_4(inputs[FALL_CV_A_INPUT + part].getVoltage()); - } - else { - for (int c = 0; c < std::min(channels[part], fallCVChannels); c += 4) - fallCV[c / 4] += inputs[FALL_CV_A_INPUT + part].getVoltageSimd(c); - } - - const int cycleChannels = inputs[CYCLE_A_INPUT + part].getChannels(); - if (cycleChannels == 1) { - for (int c = 0; c < channels[part]; c += 4) - cycle[c / 4] += float_4(inputs[CYCLE_A_INPUT + part].getVoltage()); - } - else { - for (int c = 0; c < std::min(channels[part], cycleChannels); c += 4) - cycle[c / 4] += inputs[CYCLE_A_INPUT + part].getVoltageSimd(c); - } + for (int c = 0; c < channels[part]; c += 4) + riseCV[c / 4] += inputs[RISE_CV_A_INPUT + part].getPolyVoltageSimd(c); + for (int c = 0; c < channels[part]; c += 4) + fallCV[c / 4] += inputs[FALL_CV_A_INPUT + part].getPolyVoltageSimd(c); + for (int c = 0; c < channels[part]; c += 4) + cycle[c / 4] += inputs[CYCLE_A_INPUT + part].getPolyVoltageSimd(c); // start processing: for (int c = 0; c < channels[part]; c += 4) { // process SchmittTriggers - float_4 trig_mask = trigger_4[part][c / 4].process(in_trig[c / 4] / 2.0); gate[part][c / 4] = ifelse(trig_mask, float_4::mask(), gate[part][c / 4]); in[c / 4] = ifelse(gate[part][c / 4], float_4(10.0f), in[c / 4]); @@ -295,9 +241,9 @@ struct Rampage : Module { out[part][c / 4].store(outputs[OUT_A_OUTPUT + part].getVoltages(c)); - out_rising.store(outputs[RISING_A_OUTPUT + part].getVoltages(c)); - out_falling.store(outputs[FALLING_A_OUTPUT + part].getVoltages(c)); - out_EOC.store(outputs[EOC_A_OUTPUT + part].getVoltages(c)); + outputs[RISING_A_OUTPUT + part].setVoltageSimd(out_rising, c); + outputs[FALLING_A_OUTPUT + part].setVoltageSimd(out_falling, c); + outputs[EOC_A_OUTPUT + part].setVoltageSimd(out_EOC, c); } // for(int c, ...) diff --git a/src/SlewLimiter.cpp b/src/SlewLimiter.cpp index c47677b..3cfe57b 100644 --- a/src/SlewLimiter.cpp +++ b/src/SlewLimiter.cpp @@ -57,20 +57,10 @@ struct SlewLimiter : Module { in[c / 4] = inputs[IN_INPUT].getVoltageSimd(c); if (inputs[RISE_INPUT].isConnected()) { - if (inputs[RISE_INPUT].getChannels() == 1) { - riseCV[c / 4] = float_4(inputs[RISE_INPUT].getVoltage()); - } - else { - riseCV[c / 4] = inputs[RISE_INPUT].getVoltageSimd(c); - } + riseCV[c / 4] = inputs[RISE_INPUT].getPolyVoltageSimd(c); } if (inputs[FALL_INPUT].isConnected()) { - if (inputs[FALL_INPUT].getChannels() == 1) { - fallCV[c / 4] = float_4(inputs[FALL_INPUT].getVoltage()); - } - else { - fallCV[c / 4] = inputs[FALL_INPUT].getVoltageSimd(c); - } + fallCV[c / 4] = inputs[FALL_INPUT].getPolyVoltageSimd(c); } riseCV[c / 4] += param_rise;