mirror of
https://codeberg.org/armin/gelyk.git
synced 2026-10-11 17:01:53 +02:00
init
This commit is contained in:
parent
b2b64fb26e
commit
517219e035
6 changed files with 733 additions and 110 deletions
|
|
@ -55,6 +55,8 @@ void computeEQResponse(const FilterBand::Type* types,
|
|||
|
||||
void FilterBand::prepare(double sampleRate, int blockSize)
|
||||
{
|
||||
this->sampleRate = sampleRate;
|
||||
|
||||
juce::dsp::ProcessSpec spec;
|
||||
spec.sampleRate = sampleRate;
|
||||
spec.maximumBlockSize = (juce::uint32) blockSize;
|
||||
|
|
@ -63,19 +65,42 @@ void FilterBand::prepare(double sampleRate, int blockSize)
|
|||
left.prepare(spec);
|
||||
right.prepare(spec);
|
||||
|
||||
// Start from the current (target) parameters with no ramp.
|
||||
targetGain = gainDb;
|
||||
targetFreq = freq;
|
||||
targetQ = q;
|
||||
curGain = gainDb;
|
||||
curFreq = freq;
|
||||
curQ = q;
|
||||
|
||||
updateCoeffs();
|
||||
}
|
||||
|
||||
void FilterBand::setTargets(float gain, float freq, float q)
|
||||
{
|
||||
gainDb = gain;
|
||||
this->freq = freq;
|
||||
this->q = q;
|
||||
targetGain = gain;
|
||||
targetFreq = freq;
|
||||
targetQ = q;
|
||||
}
|
||||
|
||||
void FilterBand::updateCoeffs()
|
||||
{
|
||||
const float db = juce::jlimit(-24.0f, 24.0f, curGain);
|
||||
Coeffs::Ptr c;
|
||||
const float db = juce::jlimit(-24.0f, 24.0f, gainDb);
|
||||
switch (type)
|
||||
{
|
||||
case Type::lowShelf:
|
||||
c = Coeffs::makeLowShelf(sampleRate, freq, q, juce::Decibels::decibelsToGain(db));
|
||||
c = Coeffs::makeLowShelf(sampleRate, curFreq, curQ, juce::Decibels::decibelsToGain(db));
|
||||
break;
|
||||
case Type::highShelf:
|
||||
c = Coeffs::makeHighShelf(sampleRate, freq, q, juce::Decibels::decibelsToGain(db));
|
||||
c = Coeffs::makeHighShelf(sampleRate, curFreq, curQ, juce::Decibels::decibelsToGain(db));
|
||||
break;
|
||||
case Type::peak:
|
||||
default:
|
||||
c = Coeffs::makePeakFilter(sampleRate, freq, q, juce::Decibels::decibelsToGain(db));
|
||||
c = Coeffs::makePeakFilter(sampleRate, curFreq, curQ, juce::Decibels::decibelsToGain(db));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -91,14 +116,52 @@ void FilterBand::reset()
|
|||
|
||||
void FilterBand::process(juce::dsp::AudioBlock<float>& block)
|
||||
{
|
||||
if (block.getNumChannels() < 2)
|
||||
const int numSamples = (int) block.getNumSamples();
|
||||
const auto numChannels = block.getNumChannels();
|
||||
|
||||
// One-pole (exponential) smoothing evaluated at block rate, using the real
|
||||
// number of samples in this block so the ramp is independent of host buffer
|
||||
// size. ~50 ms time constant: starts responding immediately and settles
|
||||
// within ~200 ms, giving a gentle glide without the multi-second lag the old
|
||||
// per-sample SmoothedValue ramp produced when only advanced once per block.
|
||||
if (numSamples > 0 && numChannels > 0)
|
||||
{
|
||||
const float alpha = 1.0f - std::exp(-(float) numSamples / (sampleRate * 0.05f));
|
||||
|
||||
const float g = curGain + (targetGain - curGain) * alpha;
|
||||
const float f = curFreq + (targetFreq - curFreq) * alpha;
|
||||
const float qv = curQ + (targetQ - curQ) * alpha;
|
||||
|
||||
if (std::abs(g - curGain) > 0.001f ||
|
||||
std::abs(f - curFreq) > 0.01f ||
|
||||
std::abs(qv - curQ) > 0.001f)
|
||||
{
|
||||
curGain = g;
|
||||
curFreq = f;
|
||||
curQ = qv;
|
||||
updateCoeffs();
|
||||
}
|
||||
}
|
||||
|
||||
if (numChannels < 1)
|
||||
return;
|
||||
|
||||
// Smooth the coefficients to avoid zipper noise, then process.
|
||||
// JUCE's IIR::Filter only processes mono (one channel pointer), so each
|
||||
// instance must be run on a single channel's own block. Previously the whole
|
||||
// (stereo) block was passed in, which made both filters operate on channel 0
|
||||
// only: the left went through twice and the right not at all. Splitting the
|
||||
// channels fixes the dead right channel and the doubled (rumble) low end.
|
||||
left.snapToZero();
|
||||
right.snapToZero();
|
||||
left.process(juce::dsp::ProcessContextReplacing<float>(block));
|
||||
right.process(juce::dsp::ProcessContextReplacing<float>(block));
|
||||
|
||||
auto leftBlock = block.getSingleChannelBlock(0);
|
||||
left.process(juce::dsp::ProcessContextReplacing<float>(leftBlock));
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
auto rightBlock = block.getSingleChannelBlock(1);
|
||||
right.process(juce::dsp::ProcessContextReplacing<float>(rightBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -182,13 +245,17 @@ void SpectrumAnalyser::runAnalysis()
|
|||
fft.performFrequencyOnlyForwardTransform(fftBuffer.data());
|
||||
|
||||
// Magnitude values (non-negative frequencies) are in the first size/2+1 entries.
|
||||
// Normalise so a full-scale sine reads as ~0 dB: JUCE's frequency-only FFT gives
|
||||
// a magnitude of ~N/2 for a unit sine at its bin, and the Hann window halves that
|
||||
// to N/4. Dividing by that reference keeps the -72..+12 dB display range meaningful.
|
||||
const float norm = 0.25f * (float) fftSize;
|
||||
const int numBins = juce::jmin((int) fftBuffer.size(), fftSize / 2 + 1);
|
||||
juce::Array<float> mags;
|
||||
mags.ensureStorageAllocated(numBins);
|
||||
for (int i = 0; i < numBins; ++i)
|
||||
{
|
||||
float mag = fftBuffer[(size_t) i];
|
||||
float db = 20.0f * std::log10(mag + 1.0e-9f);
|
||||
float db = 20.0f * std::log10(mag / norm + 1.0e-9f);
|
||||
mags.add(db);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue