diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml deleted file mode 100644 index 15ee850..0000000 --- a/.github/workflows/build-plugin.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: Build VCV Rack Plugin -on: [push, pull_request] - -env: - rack-sdk-version: 1.1.6 - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.config.name }} - runs-on: ${{ matrix.config.os }} - strategy: - matrix: - config: - - { - name: Linux, - os: ubuntu-16.04, - prepare-os: sudo apt install -y libglu-dev - } - - { - name: MacOS, - os: macos-latest, - prepare-os: "" - } - - { - name: Windows, - os: windows-latest, - prepare-os: export CC=gcc - } - steps: - - uses: actions/checkout@v2 - with: - submodules: recursive - - name: Get Rack-SDK - run: | - pushd $HOME - curl -o Rack-SDK.zip https://vcvrack.com/downloads/Rack-SDK-${{ env.rack-sdk-version }}.zip - unzip Rack-SDK.zip - - name: Patch plugin.mk, use 7zip on Windows - if: runner.os == 'Windows' - run: | - sed -i 's/zip -q -9 -r/7z a -tzip -mx=9/' $HOME/Rack-SDK/plugin.mk - - name: Modify plugin version - # only modify plugin version if no tag was created - if: "! startsWith(github.ref, 'refs/tags/v')" - run: | - gitrev=`git rev-parse --short HEAD` - pluginversion=`jq -r '.version' plugin.json` - echo "Set plugin version from $pluginversion to $pluginversion-$gitrev" - cat <<< `jq --arg VERSION "$pluginversion-$gitrev" '.version=$VERSION' plugin.json` > plugin.json - - name: Build plugin - run: | - ${{ matrix.config.prepare-os }} - export RACK_DIR=$HOME/Rack-SDK - make -j dep - make -j dist - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - path: dist - name: ${{ matrix.config.name }} - - publish: - name: Publish plugin - # only create a release if a tag was created that is called e.g. v1.2.3 - # see also https://vcvrack.com/manual/Manifest#version - if: startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-16.04 - needs: build - steps: - - uses: actions/checkout@v2 - - uses: FranzDiebold/github-env-vars-action@v1.2.1 - - name: Check if plugin version matches tag - run: | - pluginversion=`jq -r '.version' plugin.json` - if [ "v$pluginversion" != "${{ env.GITHUB_REF_NAME }}" ]; then - echo "Plugin version from plugin.json 'v$pluginversion' doesn't match with tag version '${{ env.GITHUB_REF_NAME }}'" - exit 1 - fi - - name: Create Release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - body: | - ${{ env.GITHUB_REPOSITORY_NAME }} VCV Rack Plugin ${{ env.GITHUB_REF_NAME }} - draft: false - prerelease: false - - uses: actions/download-artifact@v2 - with: - path: _artifacts - - name: Upload release assets - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: _artifacts/**/*.zip - tag: ${{ github.ref }} - file_glob: true diff --git a/src/ABC.cpp b/src/ABC.cpp index c6e4399..f707d51 100644 --- a/src/ABC.cpp +++ b/src/ABC.cpp @@ -56,9 +56,9 @@ struct ABC : Module { int processSection(simd::float_4* out, InputIds inputA, InputIds inputB, InputIds inputC, ParamIds levelB, ParamIds levelC) { - float_4 inA[4] = {0.f}; - float_4 inB[4] = {0.f}; - float_4 inC[4] = {0.f}; + float_4 inA[4] = {}; + float_4 inB[4] = {}; + float_4 inC[4] = {}; int channelsA = inputs[inputA].getChannels(); int channelsB = inputs[inputB].getChannels(); @@ -105,13 +105,13 @@ struct ABC : Module { void process(const ProcessArgs& args) override { // process upper section - float_4 out1[4] = {0.f}; + 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] = {0.f}; + float_4 out2[4] = {}; int activeEngines2 = 1; // process lower section if (outputs[OUT2_OUTPUT].isConnected()) { diff --git a/src/ChoppingKinky.cpp b/src/ChoppingKinky.cpp index 9e3161b..65f9a93 100644 --- a/src/ChoppingKinky.cpp +++ b/src/ChoppingKinky.cpp @@ -39,9 +39,9 @@ struct ChoppingKinky : Module { }; static const int WAVESHAPE_CACHE_SIZE = 256; - float waveshapeA[WAVESHAPE_CACHE_SIZE + 1] = {0.f}; - float waveshapeBPositive[WAVESHAPE_CACHE_SIZE + 1] = {0.f}; - float waveshapeBNegative[WAVESHAPE_CACHE_SIZE + 1] = {0.f}; + float waveshapeA[WAVESHAPE_CACHE_SIZE + 1] = {}; + float waveshapeBPositive[WAVESHAPE_CACHE_SIZE + 1] = {}; + float waveshapeBNegative[WAVESHAPE_CACHE_SIZE + 1] = {}; dsp::SchmittTrigger trigger; bool outputAToChopp = false; @@ -349,7 +349,7 @@ struct ChoppingKinkyWidget : ModuleWidget { } }; for (int i = 0; i < 5; i++) { - ModeItem* modeItem = createMenuItem(std::to_string(int (1 << i)) + "x"); + ModeItem* modeItem = createMenuItem(string::f("%dx", int (1 << i))); modeItem->rightText = CHECKMARK(module->oversamplingIndex == i); modeItem->module = module; modeItem->oversamplingIndex = i; diff --git a/src/EvenVCO.cpp b/src/EvenVCO.cpp index 209d6d7..5010124 100644 --- a/src/EvenVCO.cpp +++ b/src/EvenVCO.cpp @@ -26,14 +26,14 @@ struct EvenVCO : Module { NUM_OUTPUTS }; - float_4 phase[4]; - float_4 tri[4]; + float_4 phase[4] = {}; + float_4 tri[4] = {}; /** The value of the last sync input */ float sync = 0.0; /** The outputs */ /** Whether we are past the pulse width already */ - bool halfPhase[PORT_MAX_CHANNELS]; + bool halfPhase[PORT_MAX_CHANNELS] = {}; dsp::MinBlepGenerator<16, 32> triSquareMinBlep[PORT_MAX_CHANNELS]; dsp::MinBlepGenerator<16, 32> triMinBlep[PORT_MAX_CHANNELS]; @@ -42,20 +42,11 @@ struct EvenVCO : Module { dsp::MinBlepGenerator<16, 32> sawMinBlep[PORT_MAX_CHANNELS]; dsp::MinBlepGenerator<16, 32> squareMinBlep[PORT_MAX_CHANNELS]; - dsp::RCFilter triFilter; - EvenVCO() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); - - for (int i = 0; i < 4; i++) { - phase[i] = 0.f; - tri[i] = 0.f; - } - for (int c = 0; c < PORT_MAX_CHANNELS; c++) - halfPhase[c] = false; } void process(const ProcessArgs& args) override { @@ -70,9 +61,9 @@ struct EvenVCO : Module { float pitch_0 = 1.f + std::round(params[OCTAVE_PARAM].getValue()) + params[TUNE_PARAM].getValue() / 12.f; // Compute frequency, pitch is 1V/oct - float_4 pitch[4]; + float_4 pitch[4] = {}; for (int c = 0; c < channels; c += 4) - pitch[c / 4] = float_4(pitch_0); + pitch[c / 4] = pitch_0; if (inputs[PITCH1_INPUT].isConnected()) { for (int c = 0; c < channels; c += 4) @@ -89,30 +80,26 @@ struct EvenVCO : Module { pitch[c / 4] += inputs[FM_INPUT].getPolyVoltageSimd(c) / 4.f; } - float_4 freq[4]; + float_4 freq[4] = {}; for (int c = 0; c < channels; c += 4) { freq[c / 4] = dsp::FREQ_C4 * simd::pow(2.f, pitch[c / 4]); freq[c / 4] = clamp(freq[c / 4], 0.f, 20000.f); } - // Pulse width - float pw_0 = params[PWM_PARAM].getValue(); - float_4 pw[4]; + // Pulse width + float_4 pw[4] = {}; for (int c = 0; c < channels; c += 4) - pw[c / 4] = float_4(pw_0); + pw[c / 4] = params[PWM_PARAM].getValue(); if (inputs[PWM_INPUT].isConnected()) { 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); - const float_4 m_one_4 = float_4(-1.0f); - const float_4 one_4 = float_4(1.0f); - float_4 deltaPhase[4]; - float_4 oldPhase[4]; + + float_4 deltaPhase[4] = {}; + float_4 oldPhase[4] = {}; for (int c = 0; c < channels; c += 4) { - pw[c / 4] = rescale(clamp(pw[c / 4], m_one_4, one_4), m_one_4, one_4, minPw_4, one_4 - minPw_4); + pw[c / 4] = rescale(clamp(pw[c / 4], -1.0f, 1.0f), -1.0f, 1.0f, 0.05f, 1.0f - 0.05f); // Advance phase deltaPhase[c / 4] = clamp(freq[c / 4] * args.sampleTime, float_4(1e-6f), float_4(0.5f)); @@ -121,7 +108,6 @@ struct EvenVCO : Module { } // the next block can't be done with SIMD instructions: - for (int c = 0; c < channels; c++) { if (oldPhase[c / 4].s[c % 4] < 0.5 && phase[c / 4].s[c % 4] >= 0.5) { @@ -148,19 +134,19 @@ struct EvenVCO : Module { } } - float_4 triSquareMinBlepOut[4]; - float_4 doubleSawMinBlepOut[4]; - float_4 sawMinBlepOut[4]; - float_4 squareMinBlepOut[4]; + float_4 triSquareMinBlepOut[4] = {}; + float_4 doubleSawMinBlepOut[4] = {}; + float_4 sawMinBlepOut[4] = {}; + float_4 squareMinBlepOut[4] = {}; - float_4 triSquare[4]; - float_4 sine[4]; - float_4 doubleSaw[4]; + float_4 triSquare[4] = {}; + float_4 sine[4] = {}; + float_4 doubleSaw[4] = {}; - float_4 even[4]; - float_4 saw[4]; - float_4 square[4]; - float_4 triOut[4]; + float_4 even[4] = {}; + float_4 saw[4] = {}; + float_4 square[4] = {}; + float_4 triOut[4] = {}; for (int c = 0; c < channels; c++) { triSquareMinBlepOut[c / 4].s[c % 4] = triSquareMinBlep[c].process(); @@ -170,7 +156,6 @@ struct EvenVCO : Module { } // Outputs - outputs[TRI_OUTPUT].setChannels(channels); outputs[SINE_OUTPUT].setChannels(channels); outputs[EVEN_OUTPUT].setChannels(channels); @@ -179,7 +164,7 @@ struct EvenVCO : Module { for (int c = 0; c < channels; c += 4) { - triSquare[c / 4] = simd::ifelse((phase[c / 4] < 0.5f * one_4), m_one_4, one_4); + triSquare[c / 4] = simd::ifelse((phase[c / 4] < 0.5f), -1.f, +1.f); triSquare[c / 4] += triSquareMinBlepOut[c / 4]; // Integrate square for triangle @@ -199,7 +184,7 @@ struct EvenVCO : Module { saw[c / 4] += sawMinBlepOut[c / 4]; saw[c / 4] *= 5.f; - square[c / 4] = simd::ifelse((phase[c / 4] < pw[c / 4]), m_one_4, one_4) ; + square[c / 4] = simd::ifelse((phase[c / 4] < pw[c / 4]), -1.f, +1.f); square[c / 4] += squareMinBlepOut[c / 4]; square[c / 4] *= 5.f; diff --git a/src/HexmixVCA.cpp b/src/HexmixVCA.cpp index 26c22b0..43e1fd7 100644 --- a/src/HexmixVCA.cpp +++ b/src/HexmixVCA.cpp @@ -35,21 +35,25 @@ struct HexmixVCA : Module { const static int numRows = 6; dsp::ClockDivider cvDivider; - float outputLevels[numRows] = {1.f}; - float shapes[numRows] = {0.f}; + float outputLevels[numRows] = {}; + float shapes[numRows] = {}; bool finalRowIsMix = true; HexmixVCA() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); for (int i = 0; i < numRows; ++i) { - configParam(SHAPE_PARAM + i, -1.f, 1.f, 0.f, "VCA response"); - configParam(VOL_PARAM + i, 0.f, 1.f, 1.f, "Output level"); + configParam(SHAPE_PARAM + i, -1.f, 1.f, 0.f, string::f("Channel %d VCA response", i)); + configParam(VOL_PARAM + i, 0.f, 1.f, 1.f, string::f("Channel %d output level", i)); } cvDivider.setDivision(16); + + for (int row = 0; row < numRows; ++row) { + outputLevels[row] = 1.f; + } } void process(const ProcessArgs& args) override { - float_4 mix[4] = {0.f}; + float_4 mix[4] = {}; int maxChannels = 1; // only calculate gains/shapes every 16 samples @@ -63,7 +67,7 @@ struct HexmixVCA : Module { for (int row = 0; row < numRows; ++row) { bool finalRow = (row == numRows - 1); int channels = 1; - float_4 in[4] = {0.f}; + float_4 in[4] = {}; bool inputIsConnected = inputs[IN_INPUT + row].isConnected(); if (inputIsConnected) { channels = inputs[row].getChannels(); @@ -73,7 +77,7 @@ struct HexmixVCA : Module { 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]; @@ -81,7 +85,7 @@ struct HexmixVCA : Module { in[c / 4] = inputs[row].getVoltageSimd(c) * gain; } } - + if (!finalRow) { if (outputs[OUT_OUTPUT + row].isConnected()) { // if output is connected, we don't add to mix @@ -185,19 +189,19 @@ struct HexmixVCAWidget : ModuleWidget { addOutput(createOutputCentered(mm2px(Vec(64.222, 108.536)), module, HexmixVCA::OUT_OUTPUT + 5)); } - struct MixMenuItem : MenuItem { - HexmixVCA* module; - void onAction(const event::Action& e) override { - module->finalRowIsMix ^= true; - } - }; - void appendContextMenu(Menu* menu) override { HexmixVCA* module = dynamic_cast(this->module); assert(module); menu->addChild(new MenuSeparator()); + struct MixMenuItem : MenuItem { + HexmixVCA* module; + void onAction(const event::Action& e) override { + module->finalRowIsMix ^= true; + } + }; + MixMenuItem* mixItem = createMenuItem("Final row is mix", CHECKMARK(module->finalRowIsMix)); mixItem->module = module; menu->addChild(mixItem); diff --git a/src/Mixer.cpp b/src/Mixer.cpp index 9f35c02..1322f00 100644 --- a/src/Mixer.cpp +++ b/src/Mixer.cpp @@ -49,31 +49,26 @@ struct Mixer : Module { out_channels = std::max(out_channels, channels3); out_channels = std::max(out_channels, channels4); - float_4 mult1 = float_4(params[CH1_PARAM].getValue()); - float_4 mult2 = float_4(params[CH2_PARAM].getValue()); - float_4 mult3 = float_4(params[CH3_PARAM].getValue()); - float_4 mult4 = float_4(params[CH4_PARAM].getValue()); - float_4 out[4] = {}; if (inputs[IN1_INPUT].isConnected()) { for (int c = 0; c < channels1; c += 4) - out[c / 4] += inputs[IN1_INPUT].getVoltageSimd(c) * mult1; + out[c / 4] += inputs[IN1_INPUT].getVoltageSimd(c) * params[CH1_PARAM].getValue(); } if (inputs[IN2_INPUT].isConnected()) { for (int c = 0; c < channels2; c += 4) - out[c / 4] += inputs[IN2_INPUT].getVoltageSimd(c) * mult2; + out[c / 4] += inputs[IN2_INPUT].getVoltageSimd(c) * params[CH2_PARAM].getValue(); } if (inputs[IN3_INPUT].isConnected()) { for (int c = 0; c < channels3; c += 4) - out[c / 4] += inputs[IN3_INPUT].getVoltageSimd(c) * mult3; + out[c / 4] += inputs[IN3_INPUT].getVoltageSimd(c) * params[CH3_PARAM].getValue(); } if (inputs[IN4_INPUT].isConnected()) { for (int c = 0; c < channels4; c += 4) - out[c / 4] += inputs[IN4_INPUT].getVoltageSimd(c) * mult4; + out[c / 4] += inputs[IN4_INPUT].getVoltageSimd(c) * params[CH4_PARAM].getValue(); } outputs[OUT1_OUTPUT].setChannels(out_channels); diff --git a/src/Percall.cpp b/src/Percall.cpp index e6a1d99..175bd06 100644 --- a/src/Percall.cpp +++ b/src/Percall.cpp @@ -28,9 +28,8 @@ struct Percall : Module { ADEnvelope envs[4]; - float gains[4] = {0.f}; + float gains[4] = {}; - float strength = 1.0f; dsp::SchmittTrigger trigger[4]; dsp::ClockDivider cvDivider; dsp::ClockDivider lightDivider; @@ -43,16 +42,15 @@ struct Percall : Module { Percall() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); for (int i = 0; i < 4; i++) { - configParam(VOL_PARAMS + i, 0.f, 1.f, 1.f, "Ch " + std::to_string(i + 1) + " level", "%", 0, 100); - configParam(DECAY_PARAMS + i, 0.f, 1.f, 0.f, "Ch " + std::to_string(i + 1) + " decay time"); + configParam(VOL_PARAMS + i, 0.f, 1.f, 1.f, string::f("Channel %d level", i + 1), "%", 0, 100); + configParam(DECAY_PARAMS + i, 0.f, 1.f, 0.f, string::f("Channel %d decay time", i + 1)); envs[i].attackTime = attackTime; envs[i].attackShape = 0.5f; envs[i].decayShape = 2.0f; - } - for (int i = 0; i < 2; i++) { - std::string description = "Choke " + std::to_string(2 * i + 1) + " to " + std::to_string(2 * i + 2); - configParam(CHOKE_PARAMS + i, 0.f, 1.f, 0.f, description); + + for (int i = 0; i < 2; i++) { + configParam(CHOKE_PARAMS + i, 0.f, 1.f, 0.f, string::f("Choke %d to %d", 2 * i + 1, 2 * i + 2)); } cvDivider.setDivision(16); @@ -61,9 +59,9 @@ struct Percall : Module { void process(const ProcessArgs& args) override { - strength = 1.0f; + float strength = 1.0f; if (inputs[STRENGTH_INPUT].isConnected()) { - strength = sqrt(clamp(inputs[STRENGTH_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f)); + strength = std::sqrt(clamp(inputs[STRENGTH_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f)); } // only calculate gains/decays every 16 samples @@ -76,7 +74,7 @@ struct Percall : Module { } } - float_4 mix[4] = {0.f}; + float_4 mix[4] = {}; int maxPolyphonyChannels = 1; // Mixer channels diff --git a/src/PulseGenerator_4.hpp b/src/PulseGenerator_4.hpp index d7cf182..526d93b 100644 --- a/src/PulseGenerator_4.hpp +++ b/src/PulseGenerator_4.hpp @@ -4,26 +4,25 @@ /** When triggered, holds a high value for a specified time before going low again */ struct PulseGenerator_4 { - simd::float_4 remaining = simd::float_4::zero(); + simd::float_4 remaining = 0.f; /** Immediately disables the pulse */ void reset() { - remaining = simd::float_4::zero(); + remaining = 0.f; } /** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */ - inline simd::float_4 process(float deltaTime) { + simd::float_4 process(float deltaTime) { - simd::float_4 mask = (remaining > simd::float_4::zero()); + simd::float_4 mask = (remaining > 0.f); - remaining -= ifelse(mask, simd::float_4(deltaTime), simd::float_4::zero()); - return ifelse(mask, simd::float_4::mask(), simd::float_4::zero()); + remaining -= ifelse(mask, simd::float_4(deltaTime), 0.f); + return ifelse(mask, simd::float_4::mask(), 0.f); } /** Begins a trigger with the given `duration`. */ - inline void trigger(simd::float_4 mask, float duration = 1e-3f) { + void trigger(simd::float_4 mask, float duration = 1e-3f) { // Keep the previous pulse if the existing pulse will be held longer than the currently requested one. - simd::float_4 duration_4 = simd::float_4(duration); - remaining = ifelse(mask & (duration_4 > remaining), duration_4, remaining); + remaining = ifelse(mask & (duration > remaining), duration, remaining); } }; diff --git a/src/Rampage.cpp b/src/Rampage.cpp index bf3458f..d4cae4e 100644 --- a/src/Rampage.cpp +++ b/src/Rampage.cpp @@ -75,8 +75,8 @@ struct Rampage : Module { }; - float_4 out[2][4]; - float_4 gate[2][4]; // use simd __m128 logic instead of bool + float_4 out[2][4] = {}; + float_4 gate[2][4] = {}; // use simd __m128 logic instead of bool dsp::TSchmittTrigger trigger_4[2][4]; PulseGenerator_4 endOfCyclePulse[2][4]; @@ -98,15 +98,12 @@ struct Rampage : Module { configParam(FALL_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 fall time"); configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); - - std::memset(out, 0, sizeof(out)); - std::memset(gate, 0, sizeof(gate)); } void process(const ProcessArgs& args) override { - int channels_in[2]; - int channels_trig[2]; - int channels[2]; // the larger of in or trig (per-part) + int channels_in[2] = {}; + int channels_trig[2] = {}; + int channels[2] = {}; // the larger of in or trig (per-part) // determine number of channels: @@ -122,7 +119,7 @@ struct Rampage : Module { outputs[FALLING_A_OUTPUT + part].setChannels(channels[part]); outputs[EOC_A_OUTPUT + part].setChannels(channels[part]); } - + // total number of active polyphony engines, accounting for both halves // (channels[0] / channels[1] are the number of active engines per section) const int channels_max = std::max(channels[0], channels[1]); @@ -134,14 +131,13 @@ struct Rampage : Module { // loop over two parts of Rampage: for (int part = 0; part < 2; part++) { - 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}; + float_4 in[4] = {}; + float_4 in_trig[4] = {}; + float_4 riseCV[4] = {}; + float_4 fallCV[4] = {}; + float_4 cycle[4] = {}; // get parameters: - float shape = params[SHAPE_A_PARAM + part].getValue(); float minTime; switch ((int) params[RANGE_A_PARAM + part].getValue()) { case 0: @@ -155,10 +151,10 @@ struct Rampage : Module { break; } - float_4 param_rise = float_4(params[RISE_A_PARAM + part].getValue() * 10.0f); - float_4 param_fall = float_4(params[FALL_A_PARAM + part].getValue() * 10.0f); - float_4 param_trig = float_4(params[TRIGG_A_PARAM + part].getValue() * 20.0f); - float_4 param_cycle = float_4(params[CYCLE_A_PARAM + part].getValue() * 10.0f); + float_4 param_rise = params[RISE_A_PARAM + part].getValue() * 10.0f; + float_4 param_fall = params[FALL_A_PARAM + part].getValue() * 10.0f; + float_4 param_trig = params[TRIGG_A_PARAM + part].getValue() * 20.0f; + float_4 param_cycle = params[CYCLE_A_PARAM + part].getValue() * 10.0f; for (int c = 0; c < channels[part]; c += 4) { riseCV[c / 4] = param_rise; @@ -168,7 +164,7 @@ struct Rampage : Module { } // read inputs: - if (inputs[IN_A_INPUT + part].isConnected()) { + 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); } @@ -179,7 +175,7 @@ struct Rampage : Module { } if (inputs[EXP_CV_A_INPUT + part].isConnected()) { - float_4 expCV[4]; + float_4 expCV[4] = {}; for (int c = 0; c < channels[part]; c += 4) expCV[c / 4] = inputs[EXP_CV_A_INPUT + part].getPolyVoltageSimd(c); @@ -190,11 +186,11 @@ struct Rampage : Module { } for (int c = 0; c < channels[part]; c += 4) - riseCV[c / 4] += inputs[RISE_CV_A_INPUT + part].getPolyVoltageSimd(c); + 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); + cycle[c / 4] += inputs[CYCLE_A_INPUT + part].getPolyVoltageSimd(c); // start processing: for (int c = 0; c < channels[part]; c += 4) { @@ -207,39 +203,38 @@ struct Rampage : Module { float_4 delta = in[c / 4] - out[part][c / 4]; // rise / fall branching - - float_4 delta_gt_0 = delta > float_4::zero(); - float_4 delta_lt_0 = delta < float_4::zero(); + float_4 delta_gt_0 = delta > 0.f; + float_4 delta_lt_0 = delta < 0.f; float_4 delta_eq_0 = ~(delta_lt_0 | delta_gt_0); - float_4 rateCV = ifelse(delta_gt_0, riseCV[c / 4], float_4::zero()); + float_4 rateCV = ifelse(delta_gt_0, riseCV[c / 4], 0.f); rateCV = ifelse(delta_lt_0, fallCV[c / 4], rateCV); - rateCV = clamp(rateCV, float_4::zero(), float_4(10.0f)); + rateCV = clamp(rateCV, 0.f, 10.0f); float_4 rate = minTime * simd::pow(2.0f, rateCV); + float shape = params[SHAPE_A_PARAM + part].getValue(); out[part][c / 4] += shapeDelta(delta, rate, shape) * args.sampleTime; - float_4 rising = (in[c / 4] - out[part][c / 4]) > float_4(1e-3); - float_4 falling = (in[c / 4] - out[part][c / 4]) < float_4(-1e-3); + float_4 rising = (in[c / 4] - out[part][c / 4]) > 1e-3f; + float_4 falling = (in[c / 4] - out[part][c / 4]) < -1e-3f; float_4 end_of_cycle = simd::andnot(falling, delta_lt_0); endOfCyclePulse[part][c / 4].trigger(end_of_cycle, 1e-3); - gate[part][c / 4] = ifelse(simd::andnot(rising, delta_gt_0), float_4::zero(), gate[part][c / 4]); - gate[part][c / 4] = ifelse(end_of_cycle & (cycle[c / 4] >= float_4(4.0f)), float_4::mask(), gate[part][c / 4]); - gate[part][c / 4] = ifelse(delta_eq_0, float_4::zero(), gate[part][c / 4]); + gate[part][c / 4] = ifelse(simd::andnot(rising, delta_gt_0), 0.f, gate[part][c / 4]); + gate[part][c / 4] = ifelse(end_of_cycle & (cycle[c / 4] >= 4.0f), float_4::mask(), gate[part][c / 4]); + gate[part][c / 4] = ifelse(delta_eq_0, 0.f, gate[part][c / 4]); out[part][c / 4] = ifelse(rising | falling, out[part][c / 4], in[c / 4]); - float_4 out_rising = ifelse(rising, float_4(10.0f), float_4::zero()); - float_4 out_falling = ifelse(falling, float_4(10.0f), float_4::zero()); + float_4 out_rising = ifelse(rising, 10.0f, 0.f); + float_4 out_falling = ifelse(falling, 10.0f, 0.f); float_4 pulse = endOfCyclePulse[part][c / 4].process(args.sampleTime); - float_4 out_EOC = ifelse(pulse, float_4(10.f), float_4::zero()); - - out[part][c / 4].store(outputs[OUT_A_OUTPUT + part].getVoltages(c)); + float_4 out_EOC = ifelse(pulse, 10.f, 0.f); + outputs[OUT_A_OUTPUT + part].setVoltageSimd(out[part][c / 4], 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); @@ -285,14 +280,13 @@ struct Rampage : Module { else if (balance > 0.5) a *= 2.0f * (1.0 - balance); - float_4 comp = ifelse(b > a, float_4(10.0f), float_4::zero()); + float_4 comp = ifelse(b > a, 10.0f, 0.f); float_4 out_min = simd::fmin(a, b); float_4 out_max = simd::fmax(a, b); - comp.store(outputs[COMPARATOR_OUTPUT].getVoltages(c)); - out_min.store(outputs[MIN_OUTPUT].getVoltages(c)); - out_max.store(outputs[MAX_OUTPUT].getVoltages(c)); - + outputs[COMPARATOR_OUTPUT].setVoltageSimd(comp, c); + outputs[MIN_OUTPUT].setVoltageSimd(out_min, c); + outputs[MAX_OUTPUT].setVoltageSimd(out_max, c); } // Lights if (channels_max == 1) { diff --git a/src/SlewLimiter.cpp b/src/SlewLimiter.cpp index 3b7745c..a7fc8bf 100644 --- a/src/SlewLimiter.cpp +++ b/src/SlewLimiter.cpp @@ -20,22 +20,20 @@ struct SlewLimiter : Module { NUM_OUTPUTS }; - float_4 out[4]; + float_4 out[4] = {}; SlewLimiter() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); configParam(SHAPE_PARAM, 0.0, 1.0, 0.0, "Shape"); configParam(RISE_PARAM, 0.0, 1.0, 0.0, "Rise time"); configParam(FALL_PARAM, 0.0, 1.0, 0.0, "Fall time"); - - memset(out, 0, sizeof(out)); } void process(const ProcessArgs& args) override { - float_4 in[4] = {0.f}; - float_4 riseCV[4] = {0.f}; - float_4 fallCV[4] = {0.f}; + float_4 in[4] = {}; + float_4 riseCV[4] = {}; + float_4 fallCV[4] = {}; // this is the number of active polyphony engines, defined by the input int numPolyphonyEngines = inputs[IN_INPUT].getChannels(); @@ -46,9 +44,8 @@ struct SlewLimiter : Module { // Amount of extra slew per voltage difference const float shapeScale = 1 / 10.f; - const float_4 shape = float_4(params[SHAPE_PARAM].getValue()); - const float_4 param_rise = float_4(params[RISE_PARAM].getValue() * 10.f); - const float_4 param_fall = float_4(params[FALL_PARAM].getValue() * 10.f); + const float_4 param_rise = params[RISE_PARAM].getValue() * 10.f; + const float_4 param_fall = params[FALL_PARAM].getValue() * 10.f; outputs[OUT_OUTPUT].setChannels(numPolyphonyEngines); @@ -66,21 +63,22 @@ struct SlewLimiter : Module { fallCV[c / 4] += param_fall; float_4 delta = in[c / 4] - out[c / 4]; - float_4 delta_gt_0 = delta > float_4::zero(); - float_4 delta_lt_0 = delta < float_4::zero(); + float_4 delta_gt_0 = delta > 0.f; + float_4 delta_lt_0 = delta < 0.f; - float_4 rateCV; - rateCV = ifelse(delta_gt_0, riseCV[c / 4], float_4::zero()); + float_4 rateCV = {}; + rateCV = ifelse(delta_gt_0, riseCV[c / 4], 0.f); rateCV = ifelse(delta_lt_0, fallCV[c / 4], rateCV) * 0.1f; float_4 pm_one = simd::sgn(delta); float_4 slew = slewMax * simd::pow(float_4(slewMin / slewMax), rateCV); + const float shape = params[SHAPE_PARAM].getValue(); out[c / 4] += slew * simd::crossfade(pm_one, shapeScale * delta, shape) * args.sampleTime; out[c / 4] = ifelse(delta_gt_0 & (out[c / 4] > in[c / 4]), in[c / 4], out[c / 4]); out[c / 4] = ifelse(delta_lt_0 & (out[c / 4] < in[c / 4]), in[c / 4], out[c / 4]); - out[c / 4].store(outputs[OUT_OUTPUT].getVoltages(c)); + outputs[OUT_OUTPUT].setVoltageSimd(out[c / 4], c); } } }; diff --git a/src/SpringReverb.cpp b/src/SpringReverb.cpp index 62f1ded..cf4bfed 100644 --- a/src/SpringReverb.cpp +++ b/src/SpringReverb.cpp @@ -34,15 +34,18 @@ struct SpringReverb : Module { NUM_LIGHTS }; - dsp::RealTimeConvolver *convolver = NULL; + dsp::RealTimeConvolver* convolver = NULL; dsp::SampleRateConverter<1> inputSrc; dsp::SampleRateConverter<1> outputSrc; dsp::DoubleRingBuffer, 16 * BLOCK_SIZE> inputBuffer; dsp::DoubleRingBuffer, 16 * BLOCK_SIZE> outputBuffer; dsp::RCFilter dryFilter; - dsp::PeakFilter vuFilter; - dsp::PeakFilter lightFilter; + + dsp::VuMeter2 vuFilter; + dsp::VuMeter2 lightFilter; + dsp::ClockDivider lightRefreshClock; + SpringReverb() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -53,16 +56,21 @@ struct SpringReverb : Module { convolver = new dsp::RealTimeConvolver(BLOCK_SIZE); - const float *kernel = (const float *) BINARY_START(src_SpringReverbIR_pcm); + const float* kernel = (const float*) BINARY_START(src_SpringReverbIR_pcm); size_t kernelLen = BINARY_SIZE(src_SpringReverbIR_pcm) / sizeof(float); convolver->setKernel(kernel, kernelLen); + + vuFilter.mode = dsp::VuMeter2::PEAK; + lightFilter.mode = dsp::VuMeter2::PEAK; + + lightRefreshClock.setDivision(32); } ~SpringReverb() { delete convolver; } - void process(const ProcessArgs &args) override { + void process(const ProcessArgs& args) override { float in1 = inputs[IN1_INPUT].getVoltageSum(); float in2 = inputs[IN2_INPUT].getVoltageSum(); const float levelScale = 0.030; @@ -92,7 +100,7 @@ struct SpringReverb : Module { inputSrc.setRates(args.sampleRate, 48000); int inLen = inputBuffer.size(); int outLen = BLOCK_SIZE; - inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1> *) input, &outLen); + inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1>*) input, &outLen); inputBuffer.startIncr(inLen); } @@ -104,7 +112,7 @@ struct SpringReverb : Module { outputSrc.setRates(48000, args.sampleRate); int inLen = BLOCK_SIZE; int outLen = outputBuffer.capacity(); - outputSrc.process((dsp::Frame<1> *) output, &inLen, outputBuffer.endData(), &outLen); + outputSrc.process((dsp::Frame<1>*) output, &inLen, outputBuffer.endData(), &outLen); outputBuffer.endIncr(outLen); } } @@ -112,6 +120,7 @@ struct SpringReverb : Module { // Set output if (outputBuffer.empty()) return; + float wet = outputBuffer.shift().samples[0]; float balance = clamp(params[WET_PARAM].getValue() + inputs[MIX_CV_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); float mix = crossfade(in1, wet, balance); @@ -119,24 +128,28 @@ struct SpringReverb : Module { outputs[WET_OUTPUT].setVoltage(clamp(wet, -10.0f, 10.0f)); outputs[MIX_OUTPUT].setVoltage(clamp(mix, -10.0f, 10.0f)); - // Set lights - float lightRate = 5.0 * args.sampleTime; - vuFilter.setLambda(1.f - lightRate); - float vuValue = vuFilter.process(1.f, std::fabs(wet)); - lightFilter.setLambda(1.f - lightRate); - float lightValue = lightFilter.process(1.f, std::fabs(dry * 50.0)); - - for (int i = 0; i < 7; i++) { - float light = std::pow(1.413, i) * vuValue / 10.0 - 1.0; - lights[VU1_LIGHTS + i].value = clamp(light, 0.0f, 1.0f); + // process VU lights + vuFilter.process(args.sampleTime, wet); + // process peak light + lightFilter.process(args.sampleTime, dry * 50.0); + + if (lightRefreshClock.process()) { + + float brightnessIntervals[8] = {14.f, 14.f, 12.f, 9.f, 6.f, 0.f, -6.f, -12.f}; + + for (int i = 0; i < 7; i++) { + float brightness = vuFilter.getBrightness(brightnessIntervals[i + 1], brightnessIntervals[i]); + lights[VU1_LIGHTS + i].setBrightness(brightness); + } + + lights[PEAK_LIGHT].value = lightFilter.v; } - lights[PEAK_LIGHT].value = lightValue; } }; struct SpringReverbWidget : ModuleWidget { - SpringReverbWidget(SpringReverb *module) { + SpringReverbWidget(SpringReverb* module) { setModule(module); setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/SpringReverb.svg"))); @@ -173,4 +186,4 @@ struct SpringReverbWidget : ModuleWidget { }; -Model *modelSpringReverb = createModel("SpringReverb"); +Model* modelSpringReverb = createModel("SpringReverb");