#include "DistrhoDetails.hpp" #include "DistrhoPlugin.hpp" #include "DistrhoPluginInfo.h" #include #include "../../core/Clipper.hpp" #include "../../core/Filter.hpp" #include "../../core/Gain.hpp" #include "../../core/Mixer.hpp" START_NAMESPACE_DISTRHO const int BUFFER_SIZE = 16384; struct AudioBuffers { float clippedL[BUFFER_SIZE]; float clippedR[BUFFER_SIZE]; float lpL[BUFFER_SIZE]; float lpR[BUFFER_SIZE]; }; class SquidgeDistortion : public Plugin { public: enum MixerChannels { kChannelDry, kChannelWet, kChannelCount }; enum Parameters { kParamGain, kParamClipMode, kParamFilter, kParamFilterFeedback, kParamMixVolume, kParameterCount // must be last }; SquidgeDistortion() : Plugin(kParameterCount, 0, 0), gain_(2.0f), mixer_(1.0f), filter_(440) { mixer_.setInputGain(kChannelDry, 0.0f); mixer_.setInputGain(kChannelWet, 1.0f); } protected: const char *getLabel() const override { return "SquidgeDistortion"; } const char *getDescription() const override { return "Simple distortion plugin."; } const char *getMaker() const override { return "SquidgeSoft"; } const char *getLicense() const override { return "GPL3"; } uint32_t getVersion() const override { return d_version(0, 1, 0); } int64_t getUniqueId() const override { return d_cconst('S', 'Q', 'D', 'T'); } void initParameter(uint32_t index, Parameter ¶meter) override { switch (index) { case kParamGain: parameter.name = "Gain"; parameter.symbol = "gain"; parameter.ranges.min = 1.0f; parameter.ranges.def = 2.0f; parameter.ranges.max = 10.0f; 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; static const ParameterEnumerationValue sClipModes[Clipper::kClipperModeCount] = { {0.0f, "Soft"}, {1.0f, "Hard"}, {2.0f, "Fold"}}; parameter.enumValues.values = const_cast(sClipModes); break; case kParamFilter: parameter.name = "Filter"; parameter.symbol = "filter"; parameter.ranges.min = 20.0f; parameter.ranges.def = 1000.0f; parameter.ranges.max = 10000.0f; parameter.hints = kParameterIsAutomatable; break; case kParamFilterFeedback: parameter.name = "Filter Feedback"; parameter.symbol = "filterfeedback"; parameter.ranges.min = 0.0f; parameter.ranges.def = .1f; parameter.ranges.max = 0.99f; parameter.hints = kParameterIsAutomatable; 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; } } float getParameterValue(uint32_t index) const override { switch (index) { case kParamGain: return gain_.getGain(); case kParamClipMode: return (float)clipper_.getMode(); case kParamFilter: return (float)filter_.getCutOff(); case kParamFilterFeedback: return (float)filter_.getFeedback(); case kParamMixVolume: return mixer_.getInputGain(kChannelWet); } return 0.0f; } void setParameterValue(uint32_t index, float value) override { switch (index) { case kParamGain: gain_.setGain(value); break; case kParamClipMode: value = std::fmin(std::fmax(value, 0.0f), static_cast(Clipper::kClipperModeCount - 1)); clipper_.setMode(static_cast(std::lround(value))); break; case kParamFilter: filter_.setCutOff(value); break; case kParamFilterFeedback: filter_.setFeedback(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 { if (frames > BUFFER_SIZE) { for (uint32_t i = 0; i < frames; ++i) { outputs[0][i] = inputs[0][i]; outputs[1][i] = inputs[1][i]; } return; } gain_.processStereo(inputs[0], inputs[1], buffers_.clippedL, buffers_.clippedR, frames); clipper_.processStereo(buffers_.clippedL, buffers_.clippedR, buffers_.clippedL, buffers_.clippedR, frames); filter_.processStereo(buffers_.clippedL, buffers_.clippedR, buffers_.lpL, buffers_.lpR, frames); const float *inputsL[2] = {inputs[0], buffers_.lpL}; const float *inputsR[2] = {inputs[1], buffers_.lpR}; mixer_.processStereo(inputsL, inputsR, outputs[0], outputs[1], frames); } void sampleRateChanged(double newSr) override { filter_.setSampleRate(static_cast(newSr)); } private: Gain gain_; Clipper clipper_; Mixer<2> mixer_; Filter filter_; AudioBuffers buffers_; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SquidgeDistortion); }; Plugin *createPlugin() { return new SquidgeDistortion(); } END_NAMESPACE_DISTRHO