diff --git a/plugins/community/repos/LindenbergResearch/CMakeLists.txt b/plugins/community/repos/LindenbergResearch/CMakeLists.txt index 839cd6e8..c80ee4a5 100644 --- a/plugins/community/repos/LindenbergResearch/CMakeLists.txt +++ b/plugins/community/repos/LindenbergResearch/CMakeLists.txt @@ -14,13 +14,34 @@ set(SOURCE_FILES src/VCO.cpp src/dsp/DSPMath.cpp src/dsp/DSPMath.hpp - src/Release.h src/dsp/Oscillator.cpp src/dsp/Oscillator.hpp src/dsp/DSPSystem.hpp src/dsp/LadderFilter.hpp src/dsp/LadderFilter.cpp - src/dsp/MS20zdf.hpp src/dsp/MS20zdf.cpp src/MS20Filter.cpp src/LRComponents.cpp src/LRComponents.hpp) + src/dsp/MS20zdf.hpp + src/dsp/MS20zdf.cpp + src/MS20Filter.cpp + src/LRComponents.hpp + src/dsp/WaveShaper.cpp + src/dsp/WaveShaper.hpp + src/dsp/Lockhart.cpp + src/dsp/Lockhart.hpp + src/Westcoast.cpp + src/dsp/HQTrig.hpp + src/dsp/Serge.cpp + src/dsp/Serge.hpp + src/dsp/Horner.h + src/dsp/LambertW.h + src/dsp/LambertW.cpp + src/widgets/LRKnob.cpp + src/widgets/LRShadow.cpp + src/widgets/LRCVIndicator.cpp + src/widgets/LRCVIndicator.cpp + src/widgets/LRLCDWidget.cpp + src/widgets/LRLight.cpp + src/widgets/LRPanel.cpp + src/widgets/LRSVGRotator.cpp src/dsp/Saturator.cpp src/dsp/Saturator.hpp src/dsp/Hardclip.cpp src/dsp/Hardclip.hpp src/dsp/RShaper.cpp src/dsp/RShaper.hpp) include_directories(.) include_directories(src) @@ -30,4 +51,4 @@ include_directories(../../include) include_directories(../../include/dsp) include_directories(../../dep/include) -add_executable(LRT ${SOURCE_FILES} src/dsp/DSPMath.cpp src/dsp/DSPMath.hpp src/Release.h) \ No newline at end of file +add_executable(LRT ${SOURCE_FILES} src/dsp/DSPMath.cpp src/dsp/DSPMath.hpp) \ No newline at end of file diff --git a/plugins/community/repos/LindenbergResearch/Makefile b/plugins/community/repos/LindenbergResearch/Makefile index 6ccd8700..9da15d09 100644 --- a/plugins/community/repos/LindenbergResearch/Makefile +++ b/plugins/community/repos/LindenbergResearch/Makefile @@ -1,9 +1,7 @@ SLUG = LindenbergResearch -VERSION = 0.6.0 - -SOURCES += $(wildcard src/*.cpp src/dsp/*.cpp) - +VERSION = 0.6.2_beta-3 +SOURCES += $(wildcard src/*.cpp src/dsp/*.cpp src/widgets/*.cpp) DISTRIBUTABLES += $(wildcard LICENSE*) res - RACK_DIR ?= ../.. -include $(RACK_DIR)/plugin.mk + +include $(RACK_DIR)/plugin.mk \ No newline at end of file diff --git a/plugins/community/repos/LindenbergResearch/make.objects b/plugins/community/repos/LindenbergResearch/make.objects index 02167d19..0665333f 100644 --- a/plugins/community/repos/LindenbergResearch/make.objects +++ b/plugins/community/repos/LindenbergResearch/make.objects @@ -1,10 +1,12 @@ ALL_OBJ= \ src/dsp/DSPMath.o \ + src/dsp/Hardclip.o \ src/dsp/LadderFilter.o \ src/dsp/LambertW.o \ src/dsp/Lockhart.o \ src/dsp/MS20zdf.o \ src/dsp/Oscillator.o \ + src/dsp/RShaper.o \ src/dsp/Saturator.o \ src/dsp/Serge.o \ src/dsp/WaveShaper.o \ diff --git a/plugins/community/repos/LindenbergResearch/res/Westcoast.afdesign b/plugins/community/repos/LindenbergResearch/res/Westcoast.afdesign index 9b3512c8..a9a84102 100644 Binary files a/plugins/community/repos/LindenbergResearch/res/Westcoast.afdesign and b/plugins/community/repos/LindenbergResearch/res/Westcoast.afdesign differ diff --git a/plugins/community/repos/LindenbergResearch/res/Westcoast.svg b/plugins/community/repos/LindenbergResearch/res/Westcoast.svg index 652da07b..794da0eb 100644 --- a/plugins/community/repos/LindenbergResearch/res/Westcoast.svg +++ b/plugins/community/repos/LindenbergResearch/res/Westcoast.svg @@ -151,26 +151,26 @@ - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + - + @@ -180,7 +180,7 @@ - + @@ -189,17 +189,17 @@ - - - - - - - - - + + + + + + + + + - + @@ -210,7 +210,7 @@ - + diff --git a/plugins/community/repos/LindenbergResearch/res/WestcoastAged.afdesign b/plugins/community/repos/LindenbergResearch/res/WestcoastAged.afdesign index 8f03ea9e..f31a5a30 100644 Binary files a/plugins/community/repos/LindenbergResearch/res/WestcoastAged.afdesign and b/plugins/community/repos/LindenbergResearch/res/WestcoastAged.afdesign differ diff --git a/plugins/community/repos/LindenbergResearch/res/WestcoastAged.svg b/plugins/community/repos/LindenbergResearch/res/WestcoastAged.svg index 75fd24e8..46f2225a 100644 --- a/plugins/community/repos/LindenbergResearch/res/WestcoastAged.svg +++ b/plugins/community/repos/LindenbergResearch/res/WestcoastAged.svg @@ -176,26 +176,26 @@ - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + - + @@ -205,7 +205,7 @@ - + @@ -214,17 +214,17 @@ - - - - - - - - - + + + + + + + + + - + @@ -235,7 +235,7 @@ - + diff --git a/plugins/community/repos/LindenbergResearch/src/Westcoast.cpp b/plugins/community/repos/LindenbergResearch/src/Westcoast.cpp index 154a9484..ca8f44c7 100644 --- a/plugins/community/repos/LindenbergResearch/src/Westcoast.cpp +++ b/plugins/community/repos/LindenbergResearch/src/Westcoast.cpp @@ -1,3 +1,5 @@ +#include "dsp/Hardclip.hpp" +#include "dsp/RShaper.hpp" #include "dsp/Serge.hpp" #include "dsp/Lockhart.hpp" #include "dsp/Saturator.hpp" @@ -14,8 +16,8 @@ struct Westcoast : LRModule { LOCKHART, OVERDRIVE, SATURATE, - POLYNOM, - SOFTCLIP, + RESHAPER, + VALERIE, HARDCLIP }; @@ -49,11 +51,15 @@ struct Westcoast : LRModule { hs = new dsp::LockhartWavefolder(engineGetSampleRate()); sg = new dsp::SergeWavefolder(engineGetSampleRate()); saturator = new dsp::Saturator(engineGetSampleRate()); + hardclip = new dsp::Hardclip(engineGetSampleRate()); + reshaper = new dsp::ReShaper(engineGetSampleRate()); } dsp::LockhartWavefolder *hs; dsp::SergeWavefolder *sg; dsp::Saturator *saturator; + dsp::Hardclip *hardclip; + dsp::ReShaper *reshaper; LRAlternateBigKnob *gainBtn = NULL; LRAlternateMiddleKnob *biasBtn = NULL; @@ -98,7 +104,7 @@ void Westcoast::step() { biasBtn->setIndicatorActive(inputs[CV_BIAS_INPUT].active); gainBtn->setIndicatorValue((params[GAIN_PARAM].value + gaincv) / 20); - biasBtn->setIndicatorValue((params[BIAS_PARAM].value + (biascv + 3)) / 6); + biasBtn->setIndicatorValue((params[BIAS_PARAM].value + (biascv + 6)) / 12); } float out; @@ -133,6 +139,24 @@ void Westcoast::step() { out = (float) saturator->getOut(); break; + case HARDCLIP: // Hardclip + hardclip->setGain(gain); + hardclip->setBias(bias); + hardclip->setIn(inputs[SHAPER_INPUT].value); + + hardclip->process(); + out = (float) hardclip->getOut(); + break; + + case RESHAPER: // ReShaper + reshaper->setGain(gain); + reshaper->setBias(bias); + reshaper->setIn(inputs[SHAPER_INPUT].value); + + reshaper->process(); + out = (float) reshaper->getOut(); + break; + default: // invalid state, should not happen out = 0; break; diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/HQTrig.hpp b/plugins/community/repos/LindenbergResearch/src/dsp/HQTrig.hpp index 2cb99271..58099ac6 100644 --- a/plugins/community/repos/LindenbergResearch/src/dsp/HQTrig.hpp +++ b/plugins/community/repos/LindenbergResearch/src/dsp/HQTrig.hpp @@ -1,6 +1,8 @@ #pragma once #include "DSPEffect.hpp" +#include "DSPMath.hpp" + namespace dsp { @@ -94,4 +96,95 @@ namespace dsp { }; + struct HQClip : DSPEffect { + + /* oversampling channel */ + static const int STD_CHANNEL = 0; + + int factor; + double in, out, xn1, fn1; + Resampler<1> *rs; + + + HQClip(float sr, int factor, int quality = 4) : DSPEffect(sr) { + HQClip::factor = factor; + + rs = new Resampler<1>(factor, factor * quality); + } + + + /** + * @brief Returns the actual sample-rate which is used by oversampled computation + * @return + */ + float getOversampledRate() { + return sr * rs->getFactor(); + } + + + void init() override { + DSPEffect::init(); + } + + + void invalidate() override { + DSPEffect::invalidate(); + } + + + /** + * @brief Compute next value + * @param x + * @return + */ + double next(double x) { + in = x; + process(); + + return out; + } + + + /** + * @brief Generate an anti-aliased clipping + * @param x + * @return + */ + inline double computeAA(double x) { + double xa = x + 1; + double xb = x - 1; + double fn = ((xa * xa) * sign(xa) - (xb * xb) * sign(xb) - 2) / 4.; + double xn, out; + + if (abs(x - xn1) < 10e-10) { + xn = (x + xn1) / 2.; + out = (abs(xn + 1) - abs(xn - 1)) / 2.; + } else { + out = (fn - fn1) / (x - xn1); + } + + fn1 = fn; + xn1 = x; + + return out; + } + + + /** + * @brief Compute tanh + */ + inline void process() override { + rs->doUpsample(STD_CHANNEL, in); + + for (int i = 0; i < rs->getFactor(); i++) { + double x = rs->getUpsampled(STD_CHANNEL)[i]; + rs->data[STD_CHANNEL][i] = computeAA(x); + } + + out = rs->getDownsampled(STD_CHANNEL); + } + + }; + + } \ No newline at end of file diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.cpp b/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.cpp new file mode 100644 index 00000000..b2ab8c93 --- /dev/null +++ b/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.cpp @@ -0,0 +1,43 @@ +#include "Hardclip.hpp" + +using namespace dsp; + + +Hardclip::Hardclip(float sr) : WaveShaper(sr) { + init(); + noise = new Noise; + hqclip = new HQClip(sr, 4); +} + + +void Hardclip::init() { + WaveShaper::rs = new Resampler<1>(1); +} + + +void Hardclip::process() { + WaveShaper::process(); +} + + +void Hardclip::invalidate() {} + + +double Hardclip::compute(double x) { + double out; + double in = clampd(x, -SHAPER_MAX_VOLTS, SHAPER_MAX_VOLTS); + + in *= clampd(gain, 0., 20.); // add gain + in += clampd(bias * 2, -SHAPER_MAX_BIAS, SHAPER_MAX_BIAS); // add bias + + in *= HARDCLIP_GAIN; + + in = hqclip->next(in); + + in *= 1 / HARDCLIP_GAIN * 0.3; + if (blockDC) in = dc->filter(in); + + out = in + noise->nextFloat(HARDCLIP_NOISE); + + return out; +} diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.hpp b/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.hpp new file mode 100644 index 00000000..4ddb3e0d --- /dev/null +++ b/plugins/community/repos/LindenbergResearch/src/dsp/Hardclip.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "WaveShaper.hpp" + +#define HARDCLIP_NOISE 0.0017234327 +#define HARDCLIP_GAIN 0.05 + +namespace dsp { + + struct Hardclip : WaveShaper { + + Noise *noise; + HQClip *hqclip; + + + public: + + explicit Hardclip(float sr); + + void init() override; + void invalidate() override; + void process() override; + double compute(double x) override; + + }; + +} \ No newline at end of file diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/Lockhart.cpp b/plugins/community/repos/LindenbergResearch/src/dsp/Lockhart.cpp index 7aabad11..4f03c349 100644 --- a/plugins/community/repos/LindenbergResearch/src/dsp/Lockhart.cpp +++ b/plugins/community/repos/LindenbergResearch/src/dsp/Lockhart.cpp @@ -61,8 +61,8 @@ double LockhartWavefolder::compute(double x) { double out; double in = clampd(x, -SHAPER_MAX_VOLTS, SHAPER_MAX_VOLTS); - in *= clampd(gain, 0., 20.); // add gainBtn - in += clampd(bias*2, -12., 12.); // add biasBtn + in *= clampd(gain, 0., 20.); // add gain + in += clampd(bias * 2, -SHAPER_MAX_BIAS, SHAPER_MAX_BIAS); // add bias in *= 0.05; diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.cpp b/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.cpp new file mode 100644 index 00000000..01f4aed8 --- /dev/null +++ b/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.cpp @@ -0,0 +1,42 @@ +#include "RShaper.hpp" + +using namespace dsp; + + +ReShaper::ReShaper(float sr) : WaveShaper(sr) { + init(); + noise = new Noise; +} + + +void ReShaper::init() { + WaveShaper::rs = new Resampler<1>(8, 16); +} + + +void ReShaper::process() { + WaveShaper::process(); +} + + +void ReShaper::invalidate() {} + + +double ReShaper::compute(double x) { + double out; + double a = gain * 2.5; + double in = clampd(x, -SHAPER_MAX_VOLTS, SHAPER_MAX_VOLTS); + + in += clampd(bias * 0.5, -SHAPER_MAX_BIAS / 4., SHAPER_MAX_BIAS / .4); // add bias + + in *= RSHAPER_GAIN; + + in = in * (fabs(in) + a) / (in * in + (a - 1) * fabs(in) + 1); + + in *= 1 / RSHAPER_GAIN * 0.5; + if (blockDC) in = dc->filter(in); + + out = in + noise->nextFloat(RSHAPER_NOISE); + + return out; +} diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.hpp b/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.hpp new file mode 100644 index 00000000..1587bb2c --- /dev/null +++ b/plugins/community/repos/LindenbergResearch/src/dsp/RShaper.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "WaveShaper.hpp" + +#define RSHAPER_NOISE 0.0017234327 +#define RSHAPER_GAIN 0.1 + +namespace dsp { + + struct ReShaper : WaveShaper { + + Noise *noise; + + + public: + + explicit ReShaper(float sr); + + void init() override; + void invalidate() override; + void process() override; + double compute(double x) override; + + }; + +} \ No newline at end of file diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/Saturator.cpp b/plugins/community/repos/LindenbergResearch/src/dsp/Saturator.cpp index a6659b5b..c845ce3a 100644 --- a/plugins/community/repos/LindenbergResearch/src/dsp/Saturator.cpp +++ b/plugins/community/repos/LindenbergResearch/src/dsp/Saturator.cpp @@ -27,8 +27,8 @@ double Saturator::compute(double x) { double out; double in = clampd(x, -SHAPER_MAX_VOLTS, SHAPER_MAX_VOLTS); - in *= clampd(gain, 0., 20.); // add gainBtn - in += clampd(bias * 2, -12., 12.); // add biasBtn + in *= clampd(gain, 0., 20.); // add gain + in += clampd(bias * 2, -SHAPER_MAX_BIAS, SHAPER_MAX_BIAS); // add bias in *= SATURATOR_GAIN; diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/Serge.cpp b/plugins/community/repos/LindenbergResearch/src/dsp/Serge.cpp index 1d60b031..da2c83c3 100644 --- a/plugins/community/repos/LindenbergResearch/src/dsp/Serge.cpp +++ b/plugins/community/repos/LindenbergResearch/src/dsp/Serge.cpp @@ -59,8 +59,8 @@ double SergeWavefolder::compute(double x) { double out; double in = clampd(x, -SHAPER_MAX_VOLTS, SHAPER_MAX_VOLTS); - in *= clampd(gain, 0., 20.); // add gainBtn - in += clampd(bias * 2, -12., 12.); // add biasBtn + in *= clampd(gain, 0., 20.); // add gain + in += clampd(bias * 2, -SHAPER_MAX_BIAS, SHAPER_MAX_BIAS); // add bias in *= 0.07; diff --git a/plugins/community/repos/LindenbergResearch/src/dsp/WaveShaper.hpp b/plugins/community/repos/LindenbergResearch/src/dsp/WaveShaper.hpp index 20a02148..f0833d55 100644 --- a/plugins/community/repos/LindenbergResearch/src/dsp/WaveShaper.hpp +++ b/plugins/community/repos/LindenbergResearch/src/dsp/WaveShaper.hpp @@ -16,7 +16,7 @@ namespace dsp { struct WaveShaper : DSPEffect { /* oversampling channel */ static const int STD_CHANNEL = 0; - static constexpr double MAX_BIAS_LEVEL = 5.0; // +/- 5V + static constexpr double SHAPER_MAX_BIAS = 12.0; // +/- 5V protected: Resampler<1> *rs; diff --git a/vst2_bin/plugins/LindenbergResearch/res/Westcoast.svg b/vst2_bin/plugins/LindenbergResearch/res/Westcoast.svg index 652da07b..794da0eb 100644 --- a/vst2_bin/plugins/LindenbergResearch/res/Westcoast.svg +++ b/vst2_bin/plugins/LindenbergResearch/res/Westcoast.svg @@ -151,26 +151,26 @@ - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + - + @@ -180,7 +180,7 @@ - + @@ -189,17 +189,17 @@ - - - - - - - - - + + + + + + + + + - + @@ -210,7 +210,7 @@ - + diff --git a/vst2_bin/plugins/LindenbergResearch/res/WestcoastAged.svg b/vst2_bin/plugins/LindenbergResearch/res/WestcoastAged.svg index 75fd24e8..46f2225a 100644 --- a/vst2_bin/plugins/LindenbergResearch/res/WestcoastAged.svg +++ b/vst2_bin/plugins/LindenbergResearch/res/WestcoastAged.svg @@ -176,26 +176,26 @@ - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + - + @@ -205,7 +205,7 @@ - + @@ -214,17 +214,17 @@ - - - - - - - - - + + + + + + + + + - + @@ -235,7 +235,7 @@ - +