mirror of
https://codeberg.org/armin/saftpumpe.git
synced 2026-09-01 04:10:46 +02:00
add bypass parameter and DSP bypass logic
This commit is contained in:
parent
a82649e41e
commit
bd9aa2fa67
2 changed files with 58 additions and 4 deletions
|
|
@ -21,11 +21,17 @@ SaftpumpeProcessor::SaftpumpeProcessor()
|
||||||
std::make_unique<juce::AudioParameterFloat>(
|
std::make_unique<juce::AudioParameterFloat>(
|
||||||
mixID, "Mix", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f),
|
mixID, "Mix", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f),
|
||||||
std::make_unique<juce::AudioParameterFloat>(
|
std::make_unique<juce::AudioParameterFloat>(
|
||||||
autoReleaseID, "Auto Release", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f)
|
autoReleaseID, "Auto Release", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f),
|
||||||
|
std::make_unique<juce::AudioParameterBool>(
|
||||||
|
bypassID, "Bypass", false)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
inputScope.fill(0.0f);
|
inputScope.fill(0.0f);
|
||||||
outputScope.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() {}
|
SaftpumpeProcessor::~SaftpumpeProcessor() {}
|
||||||
|
|
@ -36,6 +42,7 @@ void SaftpumpeProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
|
||||||
compressorL.reset();
|
compressorL.reset();
|
||||||
compressorR.reset();
|
compressorR.reset();
|
||||||
scopeIndex = 0;
|
scopeIndex = 0;
|
||||||
|
fftIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaftpumpeProcessor::releaseResources() {}
|
void SaftpumpeProcessor::releaseResources() {}
|
||||||
|
|
@ -51,6 +58,8 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::Mi
|
||||||
|
|
||||||
updateCompressorParams();
|
updateCompressorParams();
|
||||||
|
|
||||||
|
bool bypassed = parameters.getRawParameterValue(bypassID)->load() > 0.5f;
|
||||||
|
|
||||||
float maxInput = 0.0f;
|
float maxInput = 0.0f;
|
||||||
float maxOutput = 0.0f;
|
float maxOutput = 0.0f;
|
||||||
float maxGR = 0.0f;
|
float maxGR = 0.0f;
|
||||||
|
|
@ -67,9 +76,16 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::Mi
|
||||||
if (absIn > maxInput) maxInput = absIn;
|
if (absIn > maxInput) maxInput = absIn;
|
||||||
|
|
||||||
inputScope[scopeIndex] = inL;
|
inputScope[scopeIndex] = inL;
|
||||||
|
fftInput[fftIndex] = inL;
|
||||||
|
|
||||||
float outL = compressorL.processSample(inL);
|
float outL, outR;
|
||||||
float outR = compressorR.processSample(inR);
|
if (bypassed) {
|
||||||
|
outL = inL;
|
||||||
|
outR = inR;
|
||||||
|
} else {
|
||||||
|
outL = compressorL.processSample(inL);
|
||||||
|
outR = compressorR.processSample(inR);
|
||||||
|
}
|
||||||
|
|
||||||
channelDataL[sample] = outL;
|
channelDataL[sample] = outL;
|
||||||
if (channelDataR) channelDataR[sample] = outR;
|
if (channelDataR) channelDataR[sample] = outR;
|
||||||
|
|
@ -77,11 +93,33 @@ void SaftpumpeProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::Mi
|
||||||
float absOut = std::max(std::abs(outL), std::abs(outR));
|
float absOut = std::max(std::abs(outL), std::abs(outR));
|
||||||
if (absOut > maxOutput) maxOutput = absOut;
|
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;
|
if (gr > maxGR) maxGR = gr;
|
||||||
|
|
||||||
outputScope[scopeIndex] = outL;
|
outputScope[scopeIndex] = outL;
|
||||||
|
fftOutput[fftIndex] = outL;
|
||||||
scopeIndex = (scopeIndex + 1) % scopeSize;
|
scopeIndex = (scopeIndex + 1) % scopeSize;
|
||||||
|
fftIndex++;
|
||||||
|
|
||||||
|
if (fftIndex >= fftSize) {
|
||||||
|
fftIndex = 0;
|
||||||
|
|
||||||
|
auto computeSpectrum = [&](const std::array<float, fftSize>& input,
|
||||||
|
std::array<float, fftSize / 2>& spectrum) {
|
||||||
|
std::array<float, fftSize * 2> 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;
|
currentInputLevel = currentInputLevel * 0.8f + (maxInput > 0.0001f ? 20.0f * std::log10(maxInput) : -100.0f) * 0.2f;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <juce_audio_processors/juce_audio_processors.h>
|
#include <juce_audio_processors/juce_audio_processors.h>
|
||||||
|
#include <juce_dsp/juce_dsp.h>
|
||||||
#include "CompressorDSP.h"
|
#include "CompressorDSP.h"
|
||||||
|
|
||||||
class SaftpumpeProcessor : public juce::AudioProcessor {
|
class SaftpumpeProcessor : public juce::AudioProcessor {
|
||||||
|
|
@ -39,6 +40,7 @@ public:
|
||||||
static constexpr const char* makeupID = "makeup";
|
static constexpr const char* makeupID = "makeup";
|
||||||
static constexpr const char* mixID = "mix";
|
static constexpr const char* mixID = "mix";
|
||||||
static constexpr const char* autoReleaseID = "autoRelease";
|
static constexpr const char* autoReleaseID = "autoRelease";
|
||||||
|
static constexpr const char* bypassID = "bypass";
|
||||||
|
|
||||||
juce::AudioProcessorValueTreeState parameters;
|
juce::AudioProcessorValueTreeState parameters;
|
||||||
|
|
||||||
|
|
@ -46,11 +48,25 @@ public:
|
||||||
float getInputLevel() const { return currentInputLevel; }
|
float getInputLevel() const { return currentInputLevel; }
|
||||||
float getOutputLevel() const { return currentOutputLevel; }
|
float getOutputLevel() const { return currentOutputLevel; }
|
||||||
|
|
||||||
|
bool isSpectrumMode() const { return spectrumMode; }
|
||||||
|
void setSpectrumMode(bool on) { spectrumMode = on; }
|
||||||
|
|
||||||
static constexpr int scopeSize = 512;
|
static constexpr int scopeSize = 512;
|
||||||
std::array<float, scopeSize> inputScope{};
|
std::array<float, scopeSize> inputScope{};
|
||||||
std::array<float, scopeSize> outputScope{};
|
std::array<float, scopeSize> outputScope{};
|
||||||
int scopeIndex = 0;
|
int scopeIndex = 0;
|
||||||
|
|
||||||
|
static constexpr int fftOrder = 10;
|
||||||
|
static constexpr int fftSize = 1 << fftOrder;
|
||||||
|
std::array<float, fftSize> fftInput{};
|
||||||
|
std::array<float, fftSize> fftOutput{};
|
||||||
|
int fftIndex = 0;
|
||||||
|
juce::dsp::FFT fft{ fftOrder };
|
||||||
|
juce::dsp::WindowingFunction<float> window{ fftSize, juce::dsp::WindowingFunction<float>::hann, true };
|
||||||
|
std::array<float, fftSize / 2> inputSpectrum{};
|
||||||
|
std::array<float, fftSize / 2> outputSpectrum{};
|
||||||
|
bool spectrumMode = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CompressorDSP compressorL;
|
CompressorDSP compressorL;
|
||||||
CompressorDSP compressorR;
|
CompressorDSP compressorR;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue