mirror of
https://codeberg.org/armin/gelyk.git
synced 2026-10-11 17:01:53 +02:00
181 lines
6 KiB
C++
181 lines
6 KiB
C++
#include "PluginProcessor.h"
|
|
#include "PluginEditor.h"
|
|
#include "GitInfo.h"
|
|
|
|
namespace gelyk
|
|
{
|
|
|
|
namespace
|
|
{
|
|
juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout()
|
|
{
|
|
juce::AudioProcessorValueTreeState::ParameterLayout layout;
|
|
|
|
auto addGain = [&](juce::String id, juce::String name, float def)
|
|
{
|
|
layout.add(std::make_unique<juce::AudioParameterFloat>(
|
|
id, name, juce::NormalisableRange<float>(-24.0f, 24.0f, 0.01f), def));
|
|
};
|
|
|
|
auto addQ = [&](juce::String id, juce::String name, float def)
|
|
{
|
|
layout.add(std::make_unique<juce::AudioParameterFloat>(
|
|
id, name, juce::NormalisableRange<float>(0.1f, 6.0f, 0.01f), def));
|
|
};
|
|
|
|
auto addFreq = [&](juce::String id, juce::String name, float def)
|
|
{
|
|
auto range = juce::NormalisableRange<float>(20.0f, 20000.0f, 0.5f);
|
|
range.setSkewForCentre(1000.0f);
|
|
layout.add(std::make_unique<juce::AudioParameterFloat>(id, name, range, def));
|
|
};
|
|
|
|
addGain("gain0", "Low Shelf Gain", 0.0f);
|
|
addGain("gain1", "Low Gain", 0.0f);
|
|
addGain("gain2", "Low-Mid Gain", 0.0f);
|
|
addGain("gain3", "Mid Gain", 0.0f);
|
|
addGain("gain4", "High-Mid Gain", 0.0f);
|
|
addGain("gain5", "High Gain", 0.0f);
|
|
addGain("gain6", "High Shelf Gain", 0.0f);
|
|
|
|
addQ("q0", "Low Shelf Q", 0.71f);
|
|
addQ("q1", "Low Q", 1.0f);
|
|
addQ("q2", "Low-Mid Q", 1.0f);
|
|
addQ("q3", "Mid Q", 1.0f);
|
|
addQ("q4", "High-Mid Q", 1.0f);
|
|
addQ("q5", "High Q", 1.0f);
|
|
addQ("q6", "High Shelf Q", 0.71f);
|
|
|
|
addFreq("freq0", "Low Shelf Freq", 60.0f);
|
|
addFreq("freq1", "Low Freq", 160.0f);
|
|
addFreq("freq2", "Low-Mid Freq", 400.0f);
|
|
addFreq("freq3", "Mid Freq", 800.0f);
|
|
addFreq("freq4", "High-Mid Freq", 1600.0f);
|
|
addFreq("freq5", "High Freq", 4000.0f);
|
|
addFreq("freq6", "High Shelf Freq", 10000.0f);
|
|
|
|
layout.add(std::make_unique<juce::AudioParameterFloat>(
|
|
"master", "Master", juce::NormalisableRange<float>(-24.0f, 24.0f, 0.01f), 0.0f));
|
|
|
|
layout.add(std::make_unique<juce::AudioParameterBool>(
|
|
"analyserEnabled", "Analyser", true));
|
|
|
|
return layout;
|
|
}
|
|
|
|
const char* const bandTypes[7] = { "lowShelf", "peak", "peak", "peak", "peak", "peak", "highShelf" };
|
|
const float bandFreqs[7] = { 60.0f, 160.0f, 400.0f, 800.0f, 1600.0f, 4000.0f, 10000.0f };
|
|
} // namespace
|
|
|
|
GelykEQAudioProcessor::GelykEQAudioProcessor()
|
|
: AudioProcessor(BusesProperties()
|
|
.withInput("Input", juce::AudioChannelSet::stereo(), true)
|
|
.withOutput("Output", juce::AudioChannelSet::stereo(), true)),
|
|
apvts(*this, nullptr, "Parameters", createParameterLayout())
|
|
{
|
|
buildVersion = ProjectInfo::versionString;
|
|
|
|
gitInfo = juce::String(GELYK_GIT_BRANCH) + " @ " + juce::String(GELYK_GIT_SHA) +
|
|
(juce::String(GELYK_GIT_DIRTY_STR).isNotEmpty() ? " (dirty)" : "") +
|
|
" | " + juce::String(GELYK_BUILD_DATE_STR);
|
|
}
|
|
|
|
void GelykEQAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
|
|
{
|
|
currentSampleRate = sampleRate;
|
|
|
|
for (int i = 0; i < numBands; ++i)
|
|
{
|
|
bands[i].type = (FilterBand::Type)
|
|
(juce::String(bandTypes[i]) == "lowShelf" ? 0 :
|
|
(juce::String(bandTypes[i]) == "highShelf" ? 2 : 1));
|
|
bands[i].freq = bandFreqs[i];
|
|
bands[i].prepare(sampleRate, samplesPerBlock);
|
|
bands[i].reset();
|
|
}
|
|
|
|
analyser.prepare(sampleRate, samplesPerBlock);
|
|
analyser.startBackground();
|
|
|
|
rebuildCoefficients();
|
|
}
|
|
|
|
void GelykEQAudioProcessor::releaseResources()
|
|
{
|
|
analyser.stopBackground();
|
|
}
|
|
|
|
void GelykEQAudioProcessor::rebuildCoefficients()
|
|
{
|
|
for (int i = 0; i < numBands; ++i)
|
|
{
|
|
float gain = apvts.getRawParameterValue("gain" + juce::String(i))->load();
|
|
float q = apvts.getRawParameterValue("q" + juce::String(i))->load();
|
|
bands[i].gainDb = gain;
|
|
bands[i].q = q;
|
|
bands[i].prepare(currentSampleRate, 512);
|
|
}
|
|
}
|
|
|
|
void GelykEQAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer&)
|
|
{
|
|
juce::ScopedNoDenormals noDenormals;
|
|
|
|
const int numChannels = buffer.getNumChannels();
|
|
const int numSamples = buffer.getNumSamples();
|
|
|
|
if (numChannels < 1)
|
|
return;
|
|
|
|
// Feed the analyser with the input.
|
|
if (apvts.getRawParameterValue("analyserEnabled")->load() > 0.5f)
|
|
{
|
|
const float* chans[2] = { buffer.getReadPointer(0),
|
|
numChannels > 1 ? buffer.getReadPointer(1) : buffer.getReadPointer(0) };
|
|
analyser.push(chans, numChannels > 1 ? 2 : 1, numSamples);
|
|
}
|
|
|
|
// Refresh band coefficient targets (cheap) from smoothed params each block.
|
|
for (int i = 0; i < numBands; ++i)
|
|
{
|
|
float gain = apvts.getRawParameterValue("gain" + juce::String(i))->load();
|
|
float q = apvts.getRawParameterValue("q" + juce::String(i))->load();
|
|
float freq = apvts.getRawParameterValue("freq" + juce::String(i))->load();
|
|
bands[i].setTargets(gain, freq, q);
|
|
}
|
|
|
|
juce::dsp::AudioBlock<float> block(buffer);
|
|
|
|
for (int i = 0; i < numBands; ++i)
|
|
bands[i].process(block);
|
|
|
|
float master = apvts.getRawParameterValue("master")->load();
|
|
if (std::abs(master) > 0.001f)
|
|
buffer.applyGain(juce::Decibels::decibelsToGain(master));
|
|
}
|
|
|
|
void GelykEQAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
|
{
|
|
auto state = apvts.copyState();
|
|
std::unique_ptr<juce::XmlElement> xml(state.createXml());
|
|
copyXmlToBinary(*xml, destData);
|
|
}
|
|
|
|
void GelykEQAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
|
{
|
|
std::unique_ptr<juce::XmlElement> xml(getXmlFromBinary(data, sizeInBytes));
|
|
if (xml != nullptr && xml->hasTagName(apvts.state.getType()))
|
|
apvts.replaceState(juce::ValueTree::fromXml(*xml));
|
|
}
|
|
|
|
juce::AudioProcessorEditor* GelykEQAudioProcessor::createEditor()
|
|
{
|
|
return new GelykEQAudioProcessorEditor(*this);
|
|
}
|
|
|
|
} // namespace gelyk
|
|
|
|
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
|
{
|
|
return new gelyk::GelykEQAudioProcessor();
|
|
}
|