gelyk/Source/EqualizerDSP.h
2026-08-29 22:55:17 +02:00

92 lines
2.7 KiB
C++

#pragma once
#include <JuceHeader.h>
namespace gelyk
{
// A single peaking/shelf filter band with smoothed coefficients.
struct FilterBand
{
enum class Type
{
lowShelf,
peak,
highShelf
};
Type type = Type::peak;
float gainDb = 0.0f; // target gain in dB
float freq = 1000.0f; // centre/corner frequency
float q = 1.0f;
void prepare(double sampleRate, int blockSize);
void reset();
// Sets the desired (target) values; the coefficients are then smoothed in
// `process` to avoid zipper noise when a slider is dragged.
void setTargets(float gain, float freq, float q);
void process(juce::dsp::AudioBlock<float>& block);
using Filter = juce::dsp::IIR::Filter<float>;
using Coeffs = juce::dsp::IIR::Coefficients<float>;
Filter left, right;
private:
void updateCoeffs();
double sampleRate = 44100.0;
float targetGain = 0.0f, targetFreq = 1000.0f, targetQ = 1.0f;
float curGain = 0.0f, curFreq = 1000.0f, curQ = 1.0f;
};
// Computes the total summed magnitude response (in dB) of a series filter chain
// at `numBins` log-spaced frequencies from 20 Hz to 20 kHz. Uses the current
// gains, frequencies and Q values and the same coefficient maths as the audio path,
// so it exactly matches what is heard.
void computeEQResponse(const FilterBand::Type* types,
const float* gains, const float* freqs, const float* qs,
int numBands, double sampleRate, float* outDb, int numBins);
// Simple background "realtime" analyser: it keeps a circular ring buffer
// of the most recent input, computes an FFT magnitude spectrum periodically
// in a background thread, and exposes the result thread-safely for the UI.
class SpectrumAnalyser : public juce::Timer
{
public:
SpectrumAnalyser();
~SpectrumAnalyser() override = default;
void prepare(double sampleRate, int maxBlockSize);
void push(const float* const* channels, int numChannels, int numSamples);
void startBackground();
void stopBackground();
// Copies the latest spectrum into `dest` (size destSize) with equal
// log-spaced bands, returning the number of bins written.
int copySpectrum(juce::Array<float>& dest, juce::Array<float>& freqBins,
int maxBins) const;
void setEnabled(bool enabled);
private:
void timerCallback() override;
void runAnalysis();
mutable juce::CriticalSection spectrumLock;
juce::Array<float> readySpectrum; // magnitude per bin
juce::dsp::FFT fft;
std::vector<float> fftBuffer;
juce::AudioBuffer<float> ring;
int ringFill = 0;
int ringChannels = 0;
double sampleRate = 44100.0;
std::atomic<bool> enabled { true };
};
} // namespace gelyk