108 lines
3.8 KiB
C++
108 lines
3.8 KiB
C++
#pragma once
|
|
|
|
#include <JuceHeader.h>
|
|
|
|
namespace serum
|
|
{
|
|
|
|
// ===========================================================================
|
|
// Small RBJ-cookbook biquad (direct form 1) used by EQ and the Hyper crossover.
|
|
// ===========================================================================
|
|
class Biquad
|
|
{
|
|
public:
|
|
void setSampleRate (double sr) noexcept { sampleRate = sr; }
|
|
|
|
void clear() noexcept
|
|
{
|
|
x1 = x2 = y1 = y2 = 0.0;
|
|
}
|
|
|
|
float process (float in) noexcept
|
|
{
|
|
const double out = b0 * in + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
|
|
x2 = x1; x1 = in;
|
|
y2 = y1; y1 = out;
|
|
return (float) out;
|
|
}
|
|
|
|
void setLowpass (double freq, double q)
|
|
{
|
|
const double w0 = 2.0 * juce::MathConstants<double>::pi * freq / sampleRate;
|
|
const double cw = std::cos (w0);
|
|
const double sw = std::sin (w0);
|
|
const double alpha = sw / (2.0 * q);
|
|
const double a0 = 1.0 + alpha;
|
|
b0 = ((1.0 - cw) / 2.0) / a0;
|
|
b1 = (1.0 - cw) / a0;
|
|
b2 = b0;
|
|
a1 = (-2.0 * cw) / a0;
|
|
a2 = (1.0 - alpha) / a0;
|
|
}
|
|
|
|
void setHighpass (double freq, double q)
|
|
{
|
|
const double w0 = 2.0 * juce::MathConstants<double>::pi * freq / sampleRate;
|
|
const double cw = std::cos (w0);
|
|
const double sw = std::sin (w0);
|
|
const double alpha = sw / (2.0 * q);
|
|
const double a0 = 1.0 + alpha;
|
|
b0 = ((1.0 + cw) / 2.0) / a0;
|
|
b1 = -(1.0 + cw) / a0;
|
|
b2 = b0;
|
|
a1 = (-2.0 * cw) / a0;
|
|
a2 = (1.0 - alpha) / a0;
|
|
}
|
|
|
|
void setLowShelf (double freq, double gainDb)
|
|
{
|
|
const double a = std::pow (10.0, gainDb / 40.0);
|
|
const double w0 = 2.0 * juce::MathConstants<double>::pi * freq / sampleRate;
|
|
const double cw = std::cos (w0);
|
|
const double sw = std::sin (w0);
|
|
const double alpha = sw / 2.0 * std::sqrt (2.0);
|
|
const double a0 = (a + 1.0) + (a - 1.0) * cw + 2.0 * std::sqrt (a) * alpha;
|
|
b0 = (a * ((a + 1.0) - (a - 1.0) * cw + 2.0 * std::sqrt (a) * alpha)) / a0;
|
|
b1 = (2.0 * a * ((a - 1.0) - (a + 1.0) * cw)) / a0;
|
|
b2 = (a * ((a + 1.0) - (a - 1.0) * cw - 2.0 * std::sqrt (a) * alpha)) / a0;
|
|
a1 = (-2.0 * ((a - 1.0) + (a + 1.0) * cw)) / a0;
|
|
a2 = ((a + 1.0) + (a - 1.0) * cw - 2.0 * std::sqrt (a) * alpha) / a0;
|
|
}
|
|
|
|
void setHighShelf (double freq, double gainDb)
|
|
{
|
|
const double a = std::pow (10.0, gainDb / 40.0);
|
|
const double w0 = 2.0 * juce::MathConstants<double>::pi * freq / sampleRate;
|
|
const double cw = std::cos (w0);
|
|
const double sw = std::sin (w0);
|
|
const double alpha = sw / 2.0 * std::sqrt (2.0);
|
|
const double a0 = (a + 1.0) - (a - 1.0) * cw + 2.0 * std::sqrt (a) * alpha;
|
|
b0 = (a * ((a + 1.0) + (a - 1.0) * cw + 2.0 * std::sqrt (a) * alpha)) / a0;
|
|
b1 = (-2.0 * a * ((a - 1.0) + (a + 1.0) * cw)) / a0;
|
|
b2 = (a * ((a + 1.0) + (a - 1.0) * cw - 2.0 * std::sqrt (a) * alpha)) / a0;
|
|
a1 = (2.0 * ((a - 1.0) - (a + 1.0) * cw)) / a0;
|
|
a2 = ((a + 1.0) - (a - 1.0) * cw - 2.0 * std::sqrt (a) * alpha) / a0;
|
|
}
|
|
|
|
void setPeak (double freq, double gainDb, double q)
|
|
{
|
|
const double a = std::pow (10.0, gainDb / 40.0);
|
|
const double w0 = 2.0 * juce::MathConstants<double>::pi * freq / sampleRate;
|
|
const double cw = std::cos (w0);
|
|
const double sw = std::sin (w0);
|
|
const double alpha = sw / (2.0 * q);
|
|
const double a0 = 1.0 + alpha / a;
|
|
b0 = (1.0 + alpha * a) / a0;
|
|
b1 = (-2.0 * cw) / a0;
|
|
b2 = (1.0 - alpha * a) / a0;
|
|
a1 = (-2.0 * cw) / a0;
|
|
a2 = (1.0 - alpha / a) / a0;
|
|
}
|
|
|
|
double sampleRate = 44100.0;
|
|
double b0 = 1.0, b1 = 0.0, b2 = 0.0, a1 = 0.0, a2 = 0.0;
|
|
double x1 = 0.0, x2 = 0.0, y1 = 0.0, y2 = 0.0;
|
|
};
|
|
|
|
} // namespace serum
|