#include "EqProcessor.h" #include #include #include #include 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(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