feat: add soft clipping mode

This commit is contained in:
Liam Kerr 2026-08-02 22:58:56 +01:00
parent 556519a750
commit e7ff4fcc18
5 changed files with 45 additions and 13 deletions

View file

@ -27,7 +27,7 @@ clean:
echo "Cleaning $$plugin..."; \ echo "Cleaning $$plugin..."; \
$(MAKE) clean -C plugins/$$plugin || true; \ $(MAKE) clean -C plugins/$$plugin || true; \
done done
rm -rf bin build core/*.o core/*.obj rm -rf bin/* build/* core/*.o core/*.obj
# -------------------------------------------------------------- # --------------------------------------------------------------

View file

@ -1,10 +1,12 @@
#include "Clipper.hpp" #include "Clipper.hpp"
#include <cmath>
Clipper::Clipper(float init_clip) : clip_(init_clip) {} Clipper::Clipper(float init_clip, ClipperMode init_mode)
: clip_(init_clip), mode_(init_mode) {}
void Clipper::process(const float *in, float *out, uint32_t frames) { void Clipper::process(const float *in, float *out, uint32_t frames) {
for (uint32_t i = 0; i < frames; ++i) { for (uint32_t i = 0; i < frames; ++i) {
out[i] = in[i] > clip_ ? clip_ : in[i]; out[i] = clip(in[i]);
} }
} }
void Clipper::processStereo(const float *inLeft, const float *inRight, void Clipper::processStereo(const float *inLeft, const float *inRight,
@ -16,6 +18,9 @@ void Clipper::processStereo(const float *inLeft, const float *inRight,
} }
float Clipper::clip(const float in) { float Clipper::clip(const float in) {
switch (mode_) {
default:
case kClipperModeHard: {
float out = in; float out = in;
if (in > 0) { if (in > 0) {
out = in > clip_ ? clip_ : in; out = in > clip_ ? clip_ : in;
@ -24,3 +29,9 @@ float Clipper::clip(const float in) {
} }
return out; return out;
} }
case kClipperModeSoft: {
float normalized = (in / clip_) * 0.75f;
return std::tanh(normalized) * clip_;
}
}
}

View file

@ -5,7 +5,9 @@
class Clipper { class Clipper {
public: public:
Clipper(float init_clip = 1.0f); enum ClipperMode { kClipperModeSoft, kClipperModeHard, kClipperModeCount };
Clipper(float init_clip = 1.0f, ClipperMode mode = kClipperModeSoft);
void process(const float *in, float *out, uint32_t frames); void process(const float *in, float *out, uint32_t frames);
void processStereo(const float *inLeft, const float *inRight, float *outLeft, void processStereo(const float *inLeft, const float *inRight, float *outLeft,
@ -14,10 +16,13 @@ public:
private: private:
float clip_; float clip_;
float clip(const float in); float clip(const float in);
ClipperMode mode_;
public: public:
void setGain(float c) { clip_ = c; } void setGain(float c) { clip_ = c; }
float getGain() const { return clip_; } float getGain() const { return clip_; }
void setMode(ClipperMode m) { mode_ = m; }
ClipperMode getMode() const { return mode_; }
}; };
#endif // CLIPPER_HPP_INCLUDED #endif // CLIPPER_HPP_INCLUDED

View file

@ -9,7 +9,7 @@
#define DISTRHO_PLUGIN_NUM_INPUTS 2 #define DISTRHO_PLUGIN_NUM_INPUTS 2
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 #define DISTRHO_PLUGIN_NUM_OUTPUTS 2
#define DISTRHO_PLUGIN_NUM_PARAMETERS 1 #define DISTRHO_PLUGIN_NUM_PARAMETERS 2
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0 #define DISTRHO_PLUGIN_WANT_PROGRAMS 0
#define DISTRHO_PLUGIN_WANT_STATE 0 #define DISTRHO_PLUGIN_WANT_STATE 0

View file

@ -11,6 +11,7 @@ class SquidgeDistortion : public Plugin {
public: public:
enum Parameters { enum Parameters {
kParamGain, kParamGain,
kParamClipMode,
kParameterCount // must be last kParameterCount // must be last
}; };
SquidgeDistortion() : Plugin(kParameterCount, 0, 0), gain_(2.0f) {} SquidgeDistortion() : Plugin(kParameterCount, 0, 0), gain_(2.0f) {}
@ -26,7 +27,6 @@ protected:
int64_t getUniqueId() const override { return d_cconst('S', 'Q', 'D', 'T'); } int64_t getUniqueId() const override { return d_cconst('S', 'Q', 'D', 'T'); }
void initParameter(uint32_t index, Parameter &parameter) override { void initParameter(uint32_t index, Parameter &parameter) override {
parameter.unit = "!";
switch (index) { switch (index) {
case kParamGain: case kParamGain:
parameter.name = "Gain"; parameter.name = "Gain";
@ -35,7 +35,18 @@ protected:
parameter.ranges.def = 2.0f; parameter.ranges.def = 2.0f;
parameter.ranges.max = 10.0f; parameter.ranges.max = 10.0f;
parameter.hints = kParameterIsAutomatable; parameter.hints = kParameterIsAutomatable;
break;
case kParamClipMode:
parameter.name = "Clip Mode";
parameter.symbol = "clipmode";
parameter.ranges.min = 0.0f;
parameter.ranges.def = 0.0f;
parameter.ranges.max = Clipper::kClipperModeCount - 1;
parameter.hints = kParameterIsAutomatable | kParameterIsInteger;
parameter.enumValues.count = Clipper::kClipperModeCount;
parameter.enumValues.restrictedMode = true;
parameter.enumValues.values =
new ParameterEnumerationValue[2]{{0.0f, "Soft"}, {1.0f, "Hard"}};
break; break;
} }
} }
@ -44,6 +55,8 @@ protected:
switch (index) { switch (index) {
case kParamGain: case kParamGain:
return gain_.getGain(); return gain_.getGain();
case kParamClipMode:
return (float)clipper_.getMode();
} }
return 0.0f; return 0.0f;
} }
@ -53,6 +66,9 @@ protected:
case kParamGain: case kParamGain:
gain_.setGain(value); gain_.setGain(value);
break; break;
case kParamClipMode:
clipper_.setMode((Clipper::ClipperMode)value);
break;
} }
} }