83 lines
2.3 KiB
C++
83 lines
2.3 KiB
C++
#include "EqProcessor.h"
|
|
#include <cmath>
|
|
#include <numbers>
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
|
|
namespace engine {
|
|
|
|
EqProcessor::EqProcessor() {
|
|
for (int b = 0; b < BANDS; ++b) {
|
|
m_gainDb[b] = 0.f;
|
|
recomputeBiquad(b);
|
|
}
|
|
}
|
|
|
|
void EqProcessor::setSampleRate(int sr) {
|
|
m_sampleRate = sr;
|
|
for (int b = 0; b < BANDS; ++b)
|
|
recomputeBiquad(b);
|
|
}
|
|
|
|
void EqProcessor::setBand(int band, float dB) {
|
|
if (band < 0 || band >= BANDS) return;
|
|
m_gainDb[band] = dB;
|
|
recomputeBiquad(band);
|
|
}
|
|
|
|
float EqProcessor::band(int band) const {
|
|
return (band >= 0 && band < BANDS) ? m_gainDb[band] : 0.f;
|
|
}
|
|
|
|
void EqProcessor::reset() {
|
|
std::memset(m_state, 0, sizeof(m_state));
|
|
}
|
|
|
|
void EqProcessor::process(AudioBuffer &buf) {
|
|
const int channels = buf.channels;
|
|
const int count = buf.sampleCount();
|
|
float *samples = buf.samples.data();
|
|
|
|
for (int band = 0; band < BANDS; ++band) {
|
|
if (std::abs(m_gainDb[band]) < 0.01f) continue;
|
|
|
|
const float b0 = m_coeff[band][0], b1 = m_coeff[band][1], b2 = m_coeff[band][2];
|
|
const float a1 = m_coeff[band][3], a2 = m_coeff[band][4];
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
const int ch = i % channels;
|
|
float &z1 = m_state[band][ch][0];
|
|
float &z2 = m_state[band][ch][1];
|
|
|
|
float x = samples[i];
|
|
float y = b0 * x + z1;
|
|
z1 = b1 * x - a1 * y + z2;
|
|
z2 = b2 * x - a2 * y;
|
|
samples[i] = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EqProcessor::recomputeBiquad(int band) {
|
|
const float sr = static_cast<float>(m_sampleRate);
|
|
const float f0 = FREQS[band];
|
|
const float dBg = m_gainDb[band];
|
|
const float Q = 1.41421356f; // sqrt(2) , Butterworth Q
|
|
const float A = std::pow(10.f, dBg / 40.f);
|
|
const double w0 = 2.0 * std::numbers::pi * f0 / sr;
|
|
const double cW = std::cos(w0);
|
|
const double sW = std::sin(w0);
|
|
const double alp = sW / (2.0 * Q);
|
|
|
|
// Peaking EQ biquad
|
|
const double b0 = 1 + alp * A, b1 = -2 * cW, b2 = 1 - alp * A;
|
|
const double a0 = 1 + alp / A, a1 = -2 * cW, a2 = 1 - alp / A;
|
|
|
|
m_coeff[band][0] = float(b0 / a0);
|
|
m_coeff[band][1] = float(b1 / a0);
|
|
m_coeff[band][2] = float(b2 / a0);
|
|
m_coeff[band][3] = float(a1 / a0);
|
|
m_coeff[band][4] = float(a2 / a0);
|
|
}
|
|
|
|
} // namespace engine
|