From c6f8cb1e0e68502b48bb9ce3c1c9e8d6c87a49a1 Mon Sep 17 00:00:00 2001 From: Liam Kerr Date: Tue, 4 Aug 2026 03:33:53 +0100 Subject: [PATCH] feat: added mixer component and add wet/dry mix to distortion --- core/Mixer.cpp | 59 +++++++++++++++++++ core/Mixer.hpp | 29 +++++++++ plugins/SquidgeDistortion/Makefile | 2 +- .../SquidgeDistortion/SquidgeDistortion.cpp | 36 ++++++++++- 4 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 core/Mixer.cpp create mode 100644 core/Mixer.hpp diff --git a/core/Mixer.cpp b/core/Mixer.cpp new file mode 100644 index 0000000..f96e0ba --- /dev/null +++ b/core/Mixer.cpp @@ -0,0 +1,59 @@ +#include "Mixer.hpp" +#include + +template +Mixer::Mixer(float init_gain) : normalise_(false) { + for (uint32_t i = 0; i < NumInputs; ++i) { + gains_[i] = init_gain; + } +} + +template +void Mixer::process(const float **inputs, float *out, + uint32_t frames) { + mixChannels(inputs, out, frames); +} + +template +void Mixer::processStereo(const float **inputsL, + const float **inputsR, float *outL, + float *outR, uint32_t frames) { + mixChannels(inputsL, outL, frames); + mixChannels(inputsR, outR, frames); +} + +template +void Mixer::mixChannels(const float **inputs, float *out, + uint32_t frames) { + float scale = normalise_ ? (1.0f / NumInputs) : 1.0f; + for (uint32_t i = 0; i < frames; ++i) { + float sum = 0.0f; + for (uint32_t j = 0; j < NumInputs; ++j) { + sum += inputs[j][i] * (gains_[j] * scale); + } + out[i] = sum; + } +} + +template +void Mixer::setInputGain(uint32_t index, float gain) { + gains_[index] = gain; +} + +template +float Mixer::getInputGain(uint32_t index) const { + return isValidInputIndex(index) ? gains_[index] : 0; +} + +template void Mixer::setNormalise(bool norm) { + normalise_ = norm; +} + +template bool Mixer::getNormalise() const { + return normalise_; +} + +template +bool Mixer::isValidInputIndex(float index) const { + return index >= 0 && index < NumInputs; +} \ No newline at end of file diff --git a/core/Mixer.hpp b/core/Mixer.hpp new file mode 100644 index 0000000..b13208b --- /dev/null +++ b/core/Mixer.hpp @@ -0,0 +1,29 @@ +#ifndef MIXER_HPP_INCLUDED +#define MIXER_HPP_INCLUDED + +#include + +template class Mixer { +public: + Mixer(float init_gain); + + void process(const float **inputs, float *out, uint32_t frames); + void processStereo(const float **inputsL, const float **inputsR, float *outL, + float *outR, uint32_t frames); + + void setInputGain(uint32_t index, float gain); + float getInputGain(uint32_t index) const; + + void setNormalise(bool norm); + bool getNormalise() const; + +private: + void mixChannels(const float **inputs, float *out, uint32_t frames); + bool isValidInputIndex(float index) const; + float gains_[NumInputs]; + bool normalise_; +}; + +#endif // MIXER_HPP_INCLUDED + +template class Mixer<2u>; \ No newline at end of file diff --git a/plugins/SquidgeDistortion/Makefile b/plugins/SquidgeDistortion/Makefile index 6175a5c..9b08a97 100644 --- a/plugins/SquidgeDistortion/Makefile +++ b/plugins/SquidgeDistortion/Makefile @@ -1,7 +1,7 @@ #!/usr/bin/make -f NAME = SquidgeDistortion -FILES_DSP = SquidgeDistortion.cpp ../../core/Gain.cpp ../../core/Clipper.cpp +FILES_DSP = SquidgeDistortion.cpp ../../core/Gain.cpp ../../core/Clipper.cpp ../../core/Mixer.cpp TARGETS = vst3 clap diff --git a/plugins/SquidgeDistortion/SquidgeDistortion.cpp b/plugins/SquidgeDistortion/SquidgeDistortion.cpp index 4d1415f..568a058 100644 --- a/plugins/SquidgeDistortion/SquidgeDistortion.cpp +++ b/plugins/SquidgeDistortion/SquidgeDistortion.cpp @@ -1,20 +1,28 @@ +#include "DistrhoDetails.hpp" #include "DistrhoPlugin.hpp" #include "DistrhoPluginInfo.h" #include "../../core/Clipper.hpp" #include "../../core/Gain.hpp" +#include "../../core/Mixer.hpp" START_NAMESPACE_DISTRHO class SquidgeDistortion : public Plugin { public: + enum MixerChannels { kChannelDry, kChannelWet, KChannelCount }; enum Parameters { kParamGain, kParamClipMode, + kParamMixVolume, kParameterCount // must be last }; - SquidgeDistortion() : Plugin(kParameterCount, 0, 0), gain_(2.0f) {} + SquidgeDistortion() + : Plugin(kParameterCount, 0, 0), gain_(2.0f), mixer_(1.0f) { + mixer_.setInputGain(kChannelDry, 0.0f); + mixer_.setInputGain(kChannelWet, 1.0f); + } protected: const char *getLabel() const override { return "SquidgeDistortion"; } @@ -52,6 +60,14 @@ protected: parameter.enumValues.values = const_cast(sClipModes); break; + case kParamMixVolume: + parameter.name = "Dry/Wet"; + parameter.symbol = "drywetvolume"; + parameter.ranges.min = 0.0f; + parameter.ranges.def = 1.0f; + parameter.ranges.max = 1.0f; + parameter.hints = kParameterIsAutomatable; + break; } } @@ -61,6 +77,8 @@ protected: return gain_.getGain(); case kParamClipMode: return (float)clipper_.getMode(); + case kParamMixVolume: + return mixer_.getInputGain(kChannelWet); } return 0.0f; } @@ -73,18 +91,30 @@ protected: case kParamClipMode: clipper_.setMode((Clipper::ClipperMode)value); break; + case kParamMixVolume: + mixer_.setInputGain(kChannelWet, value); + mixer_.setInputGain(kChannelDry, 1.0f - value); + break; } } void run(const float **inputs, float **outputs, uint32_t frames) override { - gain_.processStereo(inputs[0], inputs[1], outputs[0], outputs[1], frames); - clipper_.processStereo(outputs[0], outputs[1], outputs[0], outputs[1], + gain_.processStereo(inputs[0], inputs[1], wetBufferL_, wetBufferR_, frames); + clipper_.processStereo(wetBufferL_, wetBufferR_, wetBufferL_, wetBufferR_, frames); + + const float *inputsL[2] = {inputs[0], wetBufferL_}; + const float *inputsR[2] = {inputs[1], wetBufferR_}; + + mixer_.processStereo(inputsL, inputsR, outputs[0], outputs[1], frames); } private: Gain gain_; Clipper clipper_; + Mixer<2> mixer_; + float wetBufferL_[4096]; + float wetBufferR_[4096]; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SquidgeDistortion); };