From 21cea40da41277dc7565e991f3a1a5b3aec323cd Mon Sep 17 00:00:00 2001 From: bsp2 Date: Sun, 9 Sep 2018 18:45:20 +0200 Subject: [PATCH] add module bsp.DownSampler --- plugins/community/repos/bsp/README.md | 14 + plugins/community/repos/bsp/make.objects | 1 + .../community/repos/bsp/res/DownSampler.svg | 495 ++++++++++++++++++ .../community/repos/bsp/src/DownSampler.cpp | 166 ++++++ plugins/community/repos/bsp/src/bsp.cpp | 2 + vst2_bin/plugins/bsp/README.md | 14 + vst2_bin/plugins/bsp/res/DownSampler.svg | 495 ++++++++++++++++++ 7 files changed, 1187 insertions(+) create mode 100644 plugins/community/repos/bsp/res/DownSampler.svg create mode 100644 plugins/community/repos/bsp/src/DownSampler.cpp create mode 100644 vst2_bin/plugins/bsp/res/DownSampler.svg diff --git a/plugins/community/repos/bsp/README.md b/plugins/community/repos/bsp/README.md index deba7a22..5f037b9c 100644 --- a/plugins/community/repos/bsp/README.md +++ b/plugins/community/repos/bsp/README.md @@ -18,6 +18,20 @@ Suggested applications: +# DownSampler + +Records audio into a ringbuffer (~10 seconds) and plays it back at a lower sample rate (/1../8). + +The trigger input resets the record and play heads. + +NOTE: this used to be a sampler trick that was especially popular in 90ies dub techno music (e.g. downsampled chord stabs). + +NOTE: the module makes absolutely no attempt to hide / filter out the aliased frequencies. feel free to pre-process the input with a steep lowpass filter. + +NOTE: here's an example video: https://vimeo.com/288968750 + + + # Obxd_VCF An adaption of Filatov Vadim's excellent Ob-Xd filter. Distributed under terms of the GNU General Public License V3. diff --git a/plugins/community/repos/bsp/make.objects b/plugins/community/repos/bsp/make.objects index 3b791b20..9cae6605 100644 --- a/plugins/community/repos/bsp/make.objects +++ b/plugins/community/repos/bsp/make.objects @@ -1,5 +1,6 @@ ALL_OBJ= \ src/AttenuMixer.o \ + src/DownSampler.o \ src/bsp.o \ src/Obxd_VCF.o \ src/RMS.o \ diff --git a/plugins/community/repos/bsp/res/DownSampler.svg b/plugins/community/repos/bsp/res/DownSampler.svg new file mode 100644 index 00000000..f57fe4de --- /dev/null +++ b/plugins/community/repos/bsp/res/DownSampler.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/community/repos/bsp/src/DownSampler.cpp b/plugins/community/repos/bsp/src/DownSampler.cpp new file mode 100644 index 00000000..fd1153f4 --- /dev/null +++ b/plugins/community/repos/bsp/src/DownSampler.cpp @@ -0,0 +1,166 @@ +/* +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 "dsp/digital.hpp" + +#include "bsp.hpp" + +namespace rack_plugin_bsp { + +struct DownSampler : Module { + enum ParamIds { + RATE_PARAM, + NUM_PARAMS + }; + enum InputIds { + AUDIO_INPUT, + TRIG_INPUT, + RATE_MOD_INPUT, + NUM_INPUTS + }; + enum OutputIds { + AUDIO_OUTPUT, + NUM_OUTPUTS + }; + + static const uint32_t BUFFER_SIZE = (512*1024u); // ~11.8sec @ 44.1kHz + static const uint32_t BUFFER_SIZE_MASK = (BUFFER_SIZE - 1u); + + float *buf; + uint32_t buf_write_idx; + int32_t rate_read_left; + uint32_t buf_read_idx; + SchmittTrigger trigger; + float sample_rate; + + DownSampler() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { + buf_read_idx = ~0u; + rate_read_left = 0; + buf_write_idx = 0u; + buf = new float[BUFFER_SIZE]; + handleSampleRateChanged(); + } + + ~DownSampler() { + delete [] buf; + buf = NULL; + } + + void handleSampleRateChanged(void) { + sample_rate = engineGetSampleRate(); + } + + void onSampleRateChange() override { + Module::onSampleRateChange(); + + handleSampleRateChanged(); + } + + void step() override; +}; + + +void DownSampler::step() { + + if(trigger.process(inputs[TRIG_INPUT].value)) + { + // printf("xxx DownSampler: trig\n"); + buf_read_idx = ~0u; + buf_write_idx = 0u; + rate_read_left = 0; + } + + // Append new input to ring buffer + float inVal = inputs[AUDIO_INPUT].value; + buf[buf_write_idx] = inVal; + buf_write_idx = (buf_write_idx + 1u) & BUFFER_SIZE_MASK; + + if(--rate_read_left < 0) + { + buf_read_idx = (buf_read_idx + 1u) & BUFFER_SIZE_MASK; + + float rateF = params[RATE_PARAM].value; + + if(inputs[RATE_MOD_INPUT].active) + { + rateF += inputs[RATE_MOD_INPUT].value * (7.0f / 5.0f); + } + + rate_read_left = int32_t(rateF); + } + + float outVal = buf[buf_read_idx]; + + outputs[AUDIO_OUTPUT].value = outVal; + +#if 0 + static int xxx = 0; + if(0 == (++xxx & 32767)) + { + printf("xxx readIdx=%u writeIdx=%u readLeft=%d\n", buf_read_idx, buf_write_idx, rate_read_left); + } +#endif +} + + +struct DownSamplerWidget : ModuleWidget { + DownSamplerWidget(DownSampler *module); +}; + +DownSamplerWidget::DownSamplerWidget(DownSampler *module) : ModuleWidget(module) { + setPanel(SVG::load(assetPlugin(plugin, "res/DownSampler.svg"))); + + addChild(Widget::create(Vec(15, 0))); + addChild(Widget::create(Vec(15, 365))); + + float cx; + float cy; + +#define STY 60.0f + cx = 12.0f; + cy = 66.0f; + addInput(Port::create(Vec(11.0f, cy), Port::INPUT, module, DownSampler::AUDIO_INPUT)); + cy += STY; + addInput(Port::create(Vec(11.0f, cy), Port::INPUT, module, DownSampler::TRIG_INPUT)); +#undef STY + +#define STY 32.0f + cx = 12.0f; + cy = 200.0f; + addParam(ParamWidget::create(Vec(cx, cy), module, DownSampler::RATE_PARAM, 0.0f, 7.0f, 1.0f)); + cy += STY; + addInput(Port::create(Vec(11.0f, cy), Port::INPUT, module, DownSampler::RATE_MOD_INPUT)); +#undef STX +#undef STY + + addOutput(Port::create(Vec(11, 325), Port::OUTPUT, module, DownSampler::AUDIO_OUTPUT)); +} + +} // namespace rack_plugin_bsp + +using namespace rack_plugin_bsp; + +RACK_PLUGIN_MODEL_INIT(bsp, DownSampler) { + Model *modelDownSampler = Model::create("bsp", "DownSampler", "DownSampler", SAMPLER_TAG); + return modelDownSampler; +} diff --git a/plugins/community/repos/bsp/src/bsp.cpp b/plugins/community/repos/bsp/src/bsp.cpp index 0a7938ee..9d3e7889 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, AttenuMixer); +RACK_PLUGIN_MODEL_DECLARE(bsp, DownSampler); RACK_PLUGIN_MODEL_DECLARE(bsp, Obxd_VCF); RACK_PLUGIN_MODEL_DECLARE(bsp, RMS); RACK_PLUGIN_MODEL_DECLARE(bsp, Scanner); @@ -13,6 +14,7 @@ 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, AttenuMixer); + RACK_PLUGIN_MODEL_ADD(bsp, DownSampler); RACK_PLUGIN_MODEL_ADD(bsp, Obxd_VCF); RACK_PLUGIN_MODEL_ADD(bsp, RMS); RACK_PLUGIN_MODEL_ADD(bsp, Scanner); diff --git a/vst2_bin/plugins/bsp/README.md b/vst2_bin/plugins/bsp/README.md index deba7a22..5f037b9c 100644 --- a/vst2_bin/plugins/bsp/README.md +++ b/vst2_bin/plugins/bsp/README.md @@ -18,6 +18,20 @@ Suggested applications: +# DownSampler + +Records audio into a ringbuffer (~10 seconds) and plays it back at a lower sample rate (/1../8). + +The trigger input resets the record and play heads. + +NOTE: this used to be a sampler trick that was especially popular in 90ies dub techno music (e.g. downsampled chord stabs). + +NOTE: the module makes absolutely no attempt to hide / filter out the aliased frequencies. feel free to pre-process the input with a steep lowpass filter. + +NOTE: here's an example video: https://vimeo.com/288968750 + + + # Obxd_VCF An adaption of Filatov Vadim's excellent Ob-Xd filter. Distributed under terms of the GNU General Public License V3. diff --git a/vst2_bin/plugins/bsp/res/DownSampler.svg b/vst2_bin/plugins/bsp/res/DownSampler.svg new file mode 100644 index 00000000..f57fe4de --- /dev/null +++ b/vst2_bin/plugins/bsp/res/DownSampler.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +