diff --git a/plugins/community/repos/bsp/LICENSE_bsp.txt b/plugins/community/repos/bsp/LICENSE_bsp.txt
new file mode 100644
index 00000000..4236b0b6
--- /dev/null
+++ b/plugins/community/repos/bsp/LICENSE_bsp.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2018 bsp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/plugins/community/repos/bsp/README.md b/plugins/community/repos/bsp/README.md
new file mode 100644
index 00000000..683f637e
--- /dev/null
+++ b/plugins/community/repos/bsp/README.md
@@ -0,0 +1,44 @@
+
+# Obxd_VCF
+
+An adaption of Filatov Vadim's excellent Ob-Xd filter. Distributed under terms of the GNU General Public License V3.
+
+
+# Scanner
+
+A mixer that can seamlessly blend up to 16 input channels.
+
+"pos" sets the center position
+
+"pmod" sets the position modulation amount
+
+"shape" selects the input window (when multiple inputs are mixed together). It goes from narrow sine to wide sine, to triangle, then to various pulse shapes.
+
+"width" selects the number of neighbouring inputs (around the center position).
+
+The post section is activated by pluggin a cable into the post output.
+It's basically an experiment where I wanted to hear how the shape window sounds when applied to audio data.
+I left it in since it turned out to be useful for synthesizing cymbal and hihat sounds (among other things).
+The knob selects the window shape (same as the main shape parameter), and the switch toggles a window offset
+(this used to be a bug in earlier versions but it sounded nice with some sounds).
+
+NOTE: try modulating the position with the post output (feedback).
+
+
+# Sway
+
+A kind of slew-filtered noise generator, mainly designed for randomizing control voltages.
+
+The "time" knobs select the minimum and maximum time (up to 60sec).
+
+The "amp" knobs select the minimum and maximum amplification (-1..1).
+
+The "s+o" knobs are used to apply a final scaling/amplification (-5..5) and offset (-5..5) to the output signal.
+
+NOTE: when the min/max time is set to very small values, the module can be used to generate audio-rate noise.
+
+
+# Known Issues
+
+The graphics, especially the texts, look really bad. I currently have no idea to fix that.
+It seems to be an issue with Inkscape, the nanosvg/nanovg SVG loader/renderer, my lack of experience with Inkscape, or all of the above.
diff --git a/plugins/community/repos/bsp/make.objects b/plugins/community/repos/bsp/make.objects
index 69005d64..d5600927 100644
--- a/plugins/community/repos/bsp/make.objects
+++ b/plugins/community/repos/bsp/make.objects
@@ -1,4 +1,5 @@
ALL_OBJ= \
src/bsp.o \
src/Obxd_VCF.o \
+ src/Scanner.o \
src/Sway.o
diff --git a/plugins/community/repos/bsp/res/Scanner.svg b/plugins/community/repos/bsp/res/Scanner.svg
new file mode 100644
index 00000000..9cf767c5
--- /dev/null
+++ b/plugins/community/repos/bsp/res/Scanner.svg
@@ -0,0 +1,504 @@
+
+
+
+
diff --git a/plugins/community/repos/bsp/src/Scanner.cpp b/plugins/community/repos/bsp/src/Scanner.cpp
new file mode 100644
index 00000000..53f752a5
--- /dev/null
+++ b/plugins/community/repos/bsp/src/Scanner.cpp
@@ -0,0 +1,391 @@
+/*
+Copyright (c) 2018 bsp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include
+#include // memset
+
+#include "bsp.hpp"
+
+namespace rack_plugin_bsp {
+
+struct Scanner : Module {
+
+ enum ParamIds {
+ POSITION_PARAM,
+ MOD_POSITION_AMOUNT_PARAM,
+ SHAPE_PARAM, // sin..tri..square
+ WIDTH_PARAM,
+ TABLE_TYPE_PARAM,
+ OUT_WINDOW_SHAPE_PARAM,
+ OUT_WINDOW_OFFSET_SWITCH_PARAM,
+ NUM_PARAMS
+ };
+
+ enum InputIds {
+ MIX_1_INPUT,
+ MIX_2_INPUT,
+ MIX_3_INPUT,
+ MIX_4_INPUT,
+ MIX_5_INPUT,
+ MIX_6_INPUT,
+ MIX_7_INPUT,
+ MIX_8_INPUT,
+ MIX_9_INPUT,
+ MIX_10_INPUT,
+ MIX_11_INPUT,
+ MIX_12_INPUT,
+ MIX_13_INPUT,
+ MIX_14_INPUT,
+ MIX_15_INPUT,
+ MIX_16_INPUT,
+ MOD_POSITION_INPUT,
+ NUM_INPUTS
+ };
+
+ enum OutputIds {
+ MIX_OUTPUT,
+ WIN_OUTPUT,
+ NUM_OUTPUTS
+ };
+
+ enum LightIds {
+ MIX_1_LIGHT,
+ MIX_2_LIGHT,
+ MIX_3_LIGHT,
+ MIX_4_LIGHT,
+ MIX_5_LIGHT,
+ MIX_6_LIGHT,
+ MIX_7_LIGHT,
+ MIX_8_LIGHT,
+ MIX_9_LIGHT,
+ MIX_10_LIGHT,
+ MIX_11_LIGHT,
+ MIX_12_LIGHT,
+ MIX_13_LIGHT,
+ MIX_14_LIGHT,
+ MIX_15_LIGHT,
+ MIX_16_LIGHT,
+ NUM_LIGHTS
+ };
+
+#define MIX_LUT_SIZE (4096)
+ // (note) the table is actually symmetric (center = LUT_SIZE/2)
+ float mix_lut[MIX_LUT_SIZE + 1];
+
+ float last_mix_shape;
+ float last_out_shape;
+
+ static const uint32_t OUT_BUFFER_SIZE = 32u;
+ static const uint32_t OUT_BUFFER_MASK = (OUT_BUFFER_SIZE - 1u);
+ float out_lut[OUT_BUFFER_SIZE + 1];
+ float out_buffer[OUT_BUFFER_SIZE];
+ // (note) the table is actually symmetric (center = LUT_SIZE/2)
+ uint32_t out_buffer_idx;
+
+ Scanner() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ last_mix_shape = -999;
+ last_out_shape = -999;
+ memset((void*)out_buffer, 0, sizeof(out_buffer));
+ out_buffer_idx = 0u;
+ }
+
+ void calcLUT (float *_lut, const uint32_t _lutSize, const float _shape);
+ void calcMixLUT (void);
+ void calcOutLUT (void);
+
+ void step() override;
+};
+
+void Scanner::calcLUT(float *_lut, const uint32_t _lutSize, const float _shape) {
+
+ // printf("xxx Scanner::calcMixLUT: shape=%f\n", _shape);
+
+ float x = 0.0f;
+ float stepX = (1.0f / _lutSize);
+
+ for(uint32_t i = 0u ; i < _lutSize; i++)
+ {
+ float cy = 0.0f;
+
+ float triY = x*2;
+ if(triY > 1.0f)
+ triY = (2.0f - triY);
+
+ float expY = sinf(x*3.14159265359f/*PI*/);
+ expY = powf(expY, powf(1.0f - _shape, 9.0f)*64 + 1.0f);
+
+ float rectY = triY;
+ // rectY = (triY < 0.5) ? 0.0f : 1.0f;
+ rectY = powf(triY * 2.0f, powf((_shape - 0.75f)*4, 20) * 400.0f + 1.0f);
+ if(rectY > 1.0f)
+ rectY = 1.0f;
+
+ if(_shape < 0.5f)
+ {
+ cy = expY;
+ }
+ else if( (_shape >= 0.5f) && (_shape < 0.75f))
+ {
+ float t = (_shape -0.5f) * 4.0f;
+ cy = expY + (triY - expY) * t;
+ }
+ else if(_shape >= 0.75f)
+ {
+ float t = (_shape - 0.75f) * 4.0f;
+ cy = triY + (rectY - triY) * t;
+ }
+
+ // printf("xxx mix_lut[%d] = %f triY=%f\n", i, cy, triY);
+
+ _lut[i] = cy;
+
+ x += stepX;
+ }
+
+ _lut[_lutSize] = _lut[0];
+}
+
+void Scanner::calcMixLUT(void) {
+ calcLUT(mix_lut, MIX_LUT_SIZE, last_mix_shape);
+}
+
+void Scanner::calcOutLUT(void) {
+ calcLUT(out_lut, OUT_BUFFER_SIZE, last_out_shape);
+
+ float sum = 0.0f;
+ for(uint32_t i = 0u; i < OUT_BUFFER_SIZE; i++)
+ sum += out_lut[i];
+ float scl = 1.0f / sum;
+ for(uint32_t i = 0u; i < OUT_BUFFER_SIZE; i++)
+ out_lut[i] *= scl;
+}
+
+
+
+void Scanner::step() {
+
+ if(params[SHAPE_PARAM].value != last_mix_shape)
+ {
+ last_mix_shape = params[SHAPE_PARAM].value;
+ calcMixLUT();
+ }
+
+ int numInputs = 0;
+ int inputIdx[16];
+ float outWeights[16];
+ for(int i = 0; i < 16; i++)
+ {
+ if(inputs[MIX_1_INPUT + i].active)
+ {
+ inputIdx[numInputs] = i;
+ outWeights[numInputs] = 0.0f;
+ numInputs++;
+ }
+ else
+ {
+ lights[MIX_1_LIGHT + i].setBrightnessSmooth(0.0f);
+ }
+ }
+
+ float mixOut = 0.0f;
+
+ static int xxx = 0;
+
+ float width = 1.0f + (1.0f - params[WIDTH_PARAM].value) * 3.0f;
+
+ if(numInputs > 0)
+ {
+ float pos = -params[POSITION_PARAM].value + 0.5f - (inputs[MOD_POSITION_INPUT].value * (1.0f/5.0f))*params[MOD_POSITION_AMOUNT_PARAM].value;
+ float posStep = 1.0f / numInputs;
+ float xStep = float(MIX_LUT_SIZE) / numInputs;
+ float outWSum = 0.0f;
+
+ for(int i = 0; i < numInputs; i++)
+ {
+ if(pos < 0.0f)
+ pos += 1.0f;
+ else if(pos >= 1.0f)
+ pos -= 1.0f;
+
+ float w;
+
+ float posF = ((pos - 0.5f) * width);
+
+ if((posF > -0.5f) && (posF < 0.5f))
+ {
+ posF += 0.5f;
+ posF *= MIX_LUT_SIZE;
+ int posI = int(posF);
+ float posFrac = posF - posI;
+ w = mix_lut[posI] + (mix_lut[posI + 1] - mix_lut[posI]) * posFrac;
+ }
+ else
+ {
+ w = 0.0f;
+ }
+
+#if 0
+ if(0 == (xxx & 32767))
+ {
+ printf("xxx i=%d pos=%f w=%f posStep=%f\n", i, pos, w, posStep);
+ }
+#endif
+
+ outWeights[i] = w;
+ outWSum += w;
+
+ pos += posStep;
+ }
+
+ float outWScale = (outWSum > 0.0f) ? (1.0f / outWSum) : 0.0f;
+
+ for(int i = 0; i < numInputs; i++)
+ {
+ int portIdx = inputIdx[i];
+
+ lights[MIX_1_LIGHT + portIdx].setBrightnessSmooth(outWeights[i]);
+
+ mixOut += inputs[MIX_1_INPUT + portIdx].value * outWeights[i] * outWScale;
+ }
+
+ }
+
+ float winOut = 0.0f;
+
+ if(outputs[WIN_OUTPUT].active)
+ {
+ if(params[OUT_WINDOW_SHAPE_PARAM].value != last_out_shape)
+ {
+ last_out_shape = params[OUT_WINDOW_SHAPE_PARAM].value;
+ calcOutLUT();
+ }
+
+ out_buffer[out_buffer_idx] = mixOut;
+
+ uint32_t j;
+
+ bool bOffsetSw = (params[Scanner::OUT_WINDOW_OFFSET_SWITCH_PARAM].value >= 0.5f);
+
+ if(bOffsetSw)
+ {
+ // (note) this used to be a bug in the first implementation but it turned out
+ // that this produces some nice hihat / cymbal sounds so I left it
+ // in as a switchable parameter
+ j = (out_buffer_idx - (OUT_BUFFER_SIZE>>1)) & OUT_BUFFER_MASK;
+
+ for(uint32_t i = 0u; i < OUT_BUFFER_SIZE; i++)
+ {
+ winOut += out_buffer[j] * out_lut[i];
+
+ j = (j + 1u) & OUT_BUFFER_MASK;
+ }
+ }
+ else
+ {
+ j = out_buffer_idx;
+
+ for(uint32_t i = 0u; i < OUT_BUFFER_SIZE; i++)
+ {
+ j = (j - 1u) & OUT_BUFFER_MASK;
+
+ winOut += out_buffer[j] * out_lut[i];
+ }
+ }
+
+ out_buffer_idx = (out_buffer_idx + 1u) & OUT_BUFFER_MASK;
+ }
+
+
+#if 1
+ if(0 == (++xxx & 32767))
+ {
+ // printf("xxx numInputs=%d\n", numInputs);
+ // printf("xxx mix_lut[2048]=%f\n", mix_lut[MIX_LUT_SIZE/2]);
+ // printf("xxx outWeights=[%f; %f; %f; %f]\n", outWeights[0], outWeights[1], outWeights[2], outWeights[3]);
+
+ }
+#endif
+
+ outputs[MIX_OUTPUT].value = mixOut;
+ outputs[WIN_OUTPUT].value = winOut;
+}
+
+
+struct ScannerWidget : ModuleWidget {
+ ScannerWidget(Scanner *module);
+};
+
+ScannerWidget::ScannerWidget(Scanner *module) : ModuleWidget(module) {
+ setPanel(SVG::load(assetPlugin(plugin, "res/Scanner.svg")));
+
+ addChild(Widget::create(Vec(RACK_GRID_WIDTH, 0)));
+ addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
+ addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+ addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ // Audio input ports
+ {
+ float cy = 20.0f;
+ int k = 0;
+ for(int y = 0; y < 4; y++)
+ {
+ float cx = 3.6f;
+ for(int x = 0; x < 4; x++)
+ {
+ addInput(Port::create(mm2px(Vec(cx, cy)), Port::INPUT, module, Scanner::MIX_1_INPUT + k));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(cx+3.1f, cy-3.5f)), module, Scanner::MIX_1_LIGHT + k));
+ cx += 12.0f;
+ k++;
+ }
+ cy += 15.0f;
+ }
+ }
+
+#define STX 35
+#define STY 40
+ float cx = 9.0f;
+ float cy = 248.0f;
+ addParam(ParamWidget::create(Vec(cx, cy), module, Scanner::POSITION_PARAM, -1.0f, 1.0f, 0.0f));
+ cx += STX;
+ addParam(ParamWidget::create(Vec(cx, cy), module, Scanner::MOD_POSITION_AMOUNT_PARAM, -1.0f, 1.0f, 0.0f));
+ addInput(Port::create(Vec(cx+2.3f, cy + 37.0f), Port::INPUT, module, Scanner::MOD_POSITION_INPUT));
+ cx += STX;
+ addParam(ParamWidget::create(Vec(cx, cy), module, Scanner::SHAPE_PARAM, 0.0f, 1.0f, 0.0f));
+ cx += STX;
+ addParam(ParamWidget::create(Vec(cx, cy), module, Scanner::WIDTH_PARAM, 0.0f, 1.0f, 1.0f));
+
+ addParam(ParamWidget::create(Vec(27, box.size.y - 60), module, Scanner::OUT_WINDOW_SHAPE_PARAM, 0.0f, 1.0f, 0.34f));
+
+ addParam(ParamWidget::create(Vec(9, box.size.y-58), module, Scanner::OUT_WINDOW_OFFSET_SWITCH_PARAM, 0.0f, 1.0f, 0.0f));
+
+ addOutput(Port::create(Vec(box.size.x - 40, 320), Port::OUTPUT, module, Scanner::MIX_OUTPUT));
+ addOutput(Port::create(Vec(box.size.x - 90, 320), Port::OUTPUT, module, Scanner::WIN_OUTPUT));
+}
+
+} // namespace rack_plugin_bsp
+
+using namespace rack_plugin_bsp;
+
+RACK_PLUGIN_MODEL_INIT(bsp, Scanner) {
+ Model *modelScanner = Model::create("bsp", "Scanner", "Scanner", MIXER_TAG);
+ return modelScanner;
+}
diff --git a/plugins/community/repos/bsp/src/Sway.cpp b/plugins/community/repos/bsp/src/Sway.cpp
index 76cf013f..ad5e289d 100644
--- a/plugins/community/repos/bsp/src/Sway.cpp
+++ b/plugins/community/repos/bsp/src/Sway.cpp
@@ -1,3 +1,24 @@
+/*
+Copyright (c) 2018 bsp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
#include
diff --git a/plugins/community/repos/bsp/src/bsp.cpp b/plugins/community/repos/bsp/src/bsp.cpp
index 5aef6ade..22ad8f37 100644
--- a/plugins/community/repos/bsp/src/bsp.cpp
+++ b/plugins/community/repos/bsp/src/bsp.cpp
@@ -1,6 +1,7 @@
#include "bsp.hpp"
RACK_PLUGIN_MODEL_DECLARE(bsp, Obxd_VCF);
+RACK_PLUGIN_MODEL_DECLARE(bsp, Scanner);
RACK_PLUGIN_MODEL_DECLARE(bsp, Sway);
RACK_PLUGIN_INIT(bsp) {
@@ -9,5 +10,6 @@ RACK_PLUGIN_INIT(bsp) {
RACK_PLUGIN_INIT_WEBSITE("https://github.com/bsp2/VeeSeeVSTRack/tree/v0.6/plugins/community/repos/bsp");
RACK_PLUGIN_MODEL_ADD(bsp, Obxd_VCF);
+ RACK_PLUGIN_MODEL_ADD(bsp, Scanner);
RACK_PLUGIN_MODEL_ADD(bsp, Sway);
}
diff --git a/vst2_bin/plugins/bsp/LICENSE_bsp.txt b/vst2_bin/plugins/bsp/LICENSE_bsp.txt
new file mode 100644
index 00000000..4236b0b6
--- /dev/null
+++ b/vst2_bin/plugins/bsp/LICENSE_bsp.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2018 bsp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vst2_bin/plugins/bsp/README.md b/vst2_bin/plugins/bsp/README.md
new file mode 100644
index 00000000..683f637e
--- /dev/null
+++ b/vst2_bin/plugins/bsp/README.md
@@ -0,0 +1,44 @@
+
+# Obxd_VCF
+
+An adaption of Filatov Vadim's excellent Ob-Xd filter. Distributed under terms of the GNU General Public License V3.
+
+
+# Scanner
+
+A mixer that can seamlessly blend up to 16 input channels.
+
+"pos" sets the center position
+
+"pmod" sets the position modulation amount
+
+"shape" selects the input window (when multiple inputs are mixed together). It goes from narrow sine to wide sine, to triangle, then to various pulse shapes.
+
+"width" selects the number of neighbouring inputs (around the center position).
+
+The post section is activated by pluggin a cable into the post output.
+It's basically an experiment where I wanted to hear how the shape window sounds when applied to audio data.
+I left it in since it turned out to be useful for synthesizing cymbal and hihat sounds (among other things).
+The knob selects the window shape (same as the main shape parameter), and the switch toggles a window offset
+(this used to be a bug in earlier versions but it sounded nice with some sounds).
+
+NOTE: try modulating the position with the post output (feedback).
+
+
+# Sway
+
+A kind of slew-filtered noise generator, mainly designed for randomizing control voltages.
+
+The "time" knobs select the minimum and maximum time (up to 60sec).
+
+The "amp" knobs select the minimum and maximum amplification (-1..1).
+
+The "s+o" knobs are used to apply a final scaling/amplification (-5..5) and offset (-5..5) to the output signal.
+
+NOTE: when the min/max time is set to very small values, the module can be used to generate audio-rate noise.
+
+
+# Known Issues
+
+The graphics, especially the texts, look really bad. I currently have no idea to fix that.
+It seems to be an issue with Inkscape, the nanosvg/nanovg SVG loader/renderer, my lack of experience with Inkscape, or all of the above.
diff --git a/vst2_bin/plugins/bsp/res/Scanner.svg b/vst2_bin/plugins/bsp/res/Scanner.svg
new file mode 100644
index 00000000..af9696db
--- /dev/null
+++ b/vst2_bin/plugins/bsp/res/Scanner.svg
@@ -0,0 +1,504 @@
+
+
+
+