From bd9aa2fa67ce5112c30f5bea3847c93ea6748c47 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 13 Jul 2026 01:44:11 +0200 Subject: [PATCH] add bypass parameter and DSP bypass logic --- Source/PluginProcessor.cpp | 46 ++++++++++++++++++++++++++++++++++---- Source/PluginProcessor.h | 16 +++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 65ba982..4b8afe4 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -21,11 +21,17 @@ SaftpumpeProcessor::SaftpumpeProcessor() std::make_unique( mixID, "Mix", juce::NormalisableRange(0.0f, 1.0f, 0.01f), 1.0f), std::make_unique( - autoReleaseID, "Auto Release", juce::NormalisableRange(0.0f, 1.0f, 0.01f), 1.0f) + autoReleaseID, "Auto Release", juce::NormalisableRange(0.0f, 1.0f, 0.01f), 1.0f), + std::make_unique( + bypassID, "Bypass", false) }) { inputScope.fill(0.0f); outputScope.fill(0.0f); + fftInput.fill(0.0f); + fftOutput.fill(0.0f); + inputSpectrum.fill(0.0f); + outputSpectrum.fill(0.0f); } SaftpumpeProcessor::~SaftpumpeProcessor() {} @@ -36,6 +42,7 @@ void SaftpumpeProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) { compressorL.reset(); compressorR.reset(); scopeIndex = 0; + fftIndex = 0; } void SaftpumpeProcessor::releaseResources() {} @@ -51,6 +58,8 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer& buffer, juce::Mi updateCompressorParams(); + bool bypassed = parameters.getRawParameterValue(bypassID)->load() > 0.5f; + float maxInput = 0.0f; float maxOutput = 0.0f; float maxGR = 0.0f; @@ -67,9 +76,16 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer& buffer, juce::Mi if (absIn > maxInput) maxInput = absIn; inputScope[scopeIndex] = inL; + fftInput[fftIndex] = inL; - float outL = compressorL.processSample(inL); - float outR = compressorR.processSample(inR); + float outL, outR; + if (bypassed) { + outL = inL; + outR = inR; + } else { + outL = compressorL.processSample(inL); + outR = compressorR.processSample(inR); + } channelDataL[sample] = outL; if (channelDataR) channelDataR[sample] = outR; @@ -77,11 +93,33 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer& buffer, juce::Mi float absOut = std::max(std::abs(outL), std::abs(outR)); if (absOut > maxOutput) maxOutput = absOut; - float gr = std::abs(compressorL.getGainReduction()); + float gr = bypassed ? 0.0f : std::abs(compressorL.getGainReduction()); if (gr > maxGR) maxGR = gr; outputScope[scopeIndex] = outL; + fftOutput[fftIndex] = outL; scopeIndex = (scopeIndex + 1) % scopeSize; + fftIndex++; + + if (fftIndex >= fftSize) { + fftIndex = 0; + + auto computeSpectrum = [&](const std::array& input, + std::array& spectrum) { + std::array buf{}; + std::copy(input.begin(), input.end(), buf.begin()); + window.multiplyWithWindowingTable(buf.data(), fftSize); + fft.performFrequencyOnlyForwardTransform(buf.data(), true); + for (int i = 0; i < fftSize / 2; ++i) { + float db = (buf[i] > 0.00001f) ? 20.0f * std::log10(buf[i]) : -100.0f; + float norm = juce::jlimit(0.0f, 1.0f, (db + 80.0f) / 80.0f); + spectrum[i] = spectrum[i] * 0.7f + norm * 0.3f; + } + }; + + computeSpectrum(fftInput, inputSpectrum); + computeSpectrum(fftOutput, outputSpectrum); + } } currentInputLevel = currentInputLevel * 0.8f + (maxInput > 0.0001f ? 20.0f * std::log10(maxInput) : -100.0f) * 0.2f; diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index e8557ab..165a4d7 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "CompressorDSP.h" class SaftpumpeProcessor : public juce::AudioProcessor { @@ -39,6 +40,7 @@ public: static constexpr const char* makeupID = "makeup"; static constexpr const char* mixID = "mix"; static constexpr const char* autoReleaseID = "autoRelease"; + static constexpr const char* bypassID = "bypass"; juce::AudioProcessorValueTreeState parameters; @@ -46,11 +48,25 @@ public: float getInputLevel() const { return currentInputLevel; } float getOutputLevel() const { return currentOutputLevel; } + bool isSpectrumMode() const { return spectrumMode; } + void setSpectrumMode(bool on) { spectrumMode = on; } + static constexpr int scopeSize = 512; std::array inputScope{}; std::array outputScope{}; int scopeIndex = 0; + static constexpr int fftOrder = 10; + static constexpr int fftSize = 1 << fftOrder; + std::array fftInput{}; + std::array fftOutput{}; + int fftIndex = 0; + juce::dsp::FFT fft{ fftOrder }; + juce::dsp::WindowingFunction window{ fftSize, juce::dsp::WindowingFunction::hann, true }; + std::array inputSpectrum{}; + std::array outputSpectrum{}; + bool spectrumMode = false; + private: CompressorDSP compressorL; CompressorDSP compressorR;