saftpumpe/Source/PluginProcessor.cpp

126 lines
5.1 KiB
C++
Raw Normal View History

2026-07-12 14:18:24 +02:00
#include "PluginProcessor.h"
#include "PluginEditor.h"
SaftpumpeProcessor::SaftpumpeProcessor()
: AudioProcessor(BusesProperties()
.withInput("Input", juce::AudioChannelSet::stereo(), true)
.withOutput("Output", juce::AudioChannelSet::stereo(), true)),
parameters(*this, nullptr, "Parameters", {
std::make_unique<juce::AudioParameterFloat>(
thresholdID, "Threshold", juce::NormalisableRange<float>(-48.0f, 0.0f, 0.1f), -20.0f),
std::make_unique<juce::AudioParameterFloat>(
ratioID, "Ratio", juce::NormalisableRange<float>(1.0f, 20.0f, 0.1f, 0.5f), 4.0f),
std::make_unique<juce::AudioParameterFloat>(
attackID, "Attack", juce::NormalisableRange<float>(0.001f, 0.1f, 0.001f, 0.5f), 0.03f),
std::make_unique<juce::AudioParameterFloat>(
releaseID, "Release", juce::NormalisableRange<float>(0.05f, 1.5f, 0.01f, 0.5f), 0.3f),
std::make_unique<juce::AudioParameterFloat>(
kneeID, "Knee", juce::NormalisableRange<float>(0.0f, 12.0f, 0.5f), 6.0f),
std::make_unique<juce::AudioParameterFloat>(
makeupID, "Makeup", juce::NormalisableRange<float>(0.0f, 24.0f, 0.1f), 0.0f),
std::make_unique<juce::AudioParameterFloat>(
mixID, "Mix", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f),
std::make_unique<juce::AudioParameterFloat>(
autoReleaseID, "Auto Release", juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 1.0f)
})
{
inputScope.fill(0.0f);
outputScope.fill(0.0f);
}
SaftpumpeProcessor::~SaftpumpeProcessor() {}
void SaftpumpeProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
compressorL.prepare(sampleRate, samplesPerBlock);
compressorR.prepare(sampleRate, samplesPerBlock);
compressorL.reset();
compressorR.reset();
scopeIndex = 0;
}
void SaftpumpeProcessor::releaseResources() {}
void SaftpumpeProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer&) {
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear(i, 0, buffer.getNumSamples());
updateCompressorParams();
float maxInput = 0.0f;
float maxOutput = 0.0f;
float maxGR = 0.0f;
int numSamples = buffer.getNumSamples();
float* channelDataL = buffer.getWritePointer(0);
float* channelDataR = (totalNumInputChannels > 1) ? buffer.getWritePointer(1) : nullptr;
for (int sample = 0; sample < numSamples; ++sample) {
float inL = channelDataL[sample];
float inR = channelDataR ? channelDataR[sample] : inL;
float absIn = std::max(std::abs(inL), std::abs(inR));
if (absIn > maxInput) maxInput = absIn;
inputScope[scopeIndex] = inL;
float outL = compressorL.processSample(inL);
float outR = compressorR.processSample(inR);
channelDataL[sample] = outL;
if (channelDataR) channelDataR[sample] = outR;
float absOut = std::max(std::abs(outL), std::abs(outR));
if (absOut > maxOutput) maxOutput = absOut;
float gr = std::abs(compressorL.getGainReduction());
if (gr > maxGR) maxGR = gr;
outputScope[scopeIndex] = outL;
scopeIndex = (scopeIndex + 1) % scopeSize;
}
currentInputLevel = currentInputLevel * 0.8f + (maxInput > 0.0001f ? 20.0f * std::log10(maxInput) : -100.0f) * 0.2f;
currentOutputLevel = currentOutputLevel * 0.8f + (maxOutput > 0.0001f ? 20.0f * std::log10(maxOutput) : -100.0f) * 0.2f;
currentGainReduction = currentGainReduction * 0.7f + maxGR * 0.3f;
}
void SaftpumpeProcessor::updateCompressorParams() {
CompressorDSP::Params p;
p.threshold = parameters.getRawParameterValue(thresholdID)->load();
p.ratio = parameters.getRawParameterValue(ratioID)->load();
p.attack = parameters.getRawParameterValue(attackID)->load();
p.release = parameters.getRawParameterValue(releaseID)->load();
p.knee = parameters.getRawParameterValue(kneeID)->load();
p.makeup = parameters.getRawParameterValue(makeupID)->load();
p.mix = parameters.getRawParameterValue(mixID)->load();
p.autoRelease = parameters.getRawParameterValue(autoReleaseID)->load() > 0.5f;
compressorL.setParams(p);
compressorR.setParams(p);
}
juce::AudioProcessorEditor* SaftpumpeProcessor::createEditor() {
return new SaftpumpeEditor(*this);
}
void SaftpumpeProcessor::getStateInformation(juce::MemoryBlock& destData) {
auto state = parameters.copyState();
std::unique_ptr<juce::XmlElement> xml(state.createXml());
copyXmlToBinary(*xml, destData);
}
void SaftpumpeProcessor::setStateInformation(const void* data, int sizeInBytes) {
std::unique_ptr<juce::XmlElement> xml(getXmlFromBinary(data, sizeInBytes));
if (xml && xml->hasTagName(parameters.state.getType())) {
parameters.replaceState(juce::ValueTree::fromXml(*xml));
}
}
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() {
return new SaftpumpeProcessor();
}