LCOV - code coverage report
Current view: top level - src/audio/dsp - biquad.h (source / functions) Coverage Total Hit
Test: merged.info Lines: 100.0 % 61 61
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 8 8

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include "common.h"
       4              : 
       5              : namespace Amplitron {
       6              : 
       7              : /**
       8              :  * Transposed Direct Form II biquad filter.
       9              :  * Used by Equalizer, AmpSimulator, and CabinetSim.
      10              :  */
      11          476 : struct Biquad {
      12          387 :     float x1 = 0, x2 = 0, y1 = 0, y2 = 0;
      13          387 :     float b0 = 1, b1 = 0, b2 = 0, a1 = 0, a2 = 0;
      14              : 
      15      4979784 :     float process(float x) {
      16      4979784 :         float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
      17      4979784 :         x2 = x1;
      18      4979784 :         x1 = x;
      19      4979784 :         y2 = y1;
      20      4979784 :         y1 = y;
      21      4979784 :         return y;
      22              :     }
      23              : 
      24          552 :     void reset() { x1 = x2 = y1 = y2 = 0; }
      25              : 
      26              :     // --- Coefficient computation (Audio EQ Cookbook formulas) ---
      27              : 
      28          297 :     void set_low_shelf(float freq, float gain_db, float q, int sample_rate) {
      29          297 :         float A = std::pow(10.0f, gain_db / 40.0f);
      30          297 :         float w0 = TWO_PI * freq / sample_rate;
      31          297 :         float cos_w0 = std::cos(w0);
      32          297 :         float sin_w0 = std::sin(w0);
      33          297 :         float alpha = sin_w0 / (2.0f * q);
      34          297 :         float sqA = std::sqrt(A);
      35              : 
      36          297 :         float a0 = (A + 1) + (A - 1) * cos_w0 + 2 * sqA * alpha;
      37          297 :         b0 = (A * ((A + 1) - (A - 1) * cos_w0 + 2 * sqA * alpha)) / a0;
      38          297 :         b1 = (2 * A * ((A - 1) - (A + 1) * cos_w0)) / a0;
      39          297 :         b2 = (A * ((A + 1) - (A - 1) * cos_w0 - 2 * sqA * alpha)) / a0;
      40          297 :         a1 = (-2 * ((A - 1) + (A + 1) * cos_w0)) / a0;
      41          297 :         a2 = ((A + 1) + (A - 1) * cos_w0 - 2 * sqA * alpha) / a0;
      42          297 :     }
      43              : 
      44          297 :     void set_peaking(float freq, float gain_db, float q, int sample_rate) {
      45          297 :         float A = std::pow(10.0f, gain_db / 40.0f);
      46          297 :         float w0 = TWO_PI * freq / sample_rate;
      47          297 :         float cos_w0 = std::cos(w0);
      48          297 :         float sin_w0 = std::sin(w0);
      49          297 :         float alpha = sin_w0 / (2.0f * q);
      50              : 
      51          297 :         float a0 = 1 + alpha / A;
      52          297 :         b0 = (1 + alpha * A) / a0;
      53          297 :         b1 = (-2 * cos_w0) / a0;
      54          297 :         b2 = (1 - alpha * A) / a0;
      55          297 :         a1 = (-2 * cos_w0) / a0;
      56          297 :         a2 = (1 - alpha / A) / a0;
      57          297 :     }
      58              : 
      59          297 :     void set_high_shelf(float freq, float gain_db, float q, int sample_rate) {
      60          297 :         float A = std::pow(10.0f, gain_db / 40.0f);
      61          297 :         float w0 = TWO_PI * freq / sample_rate;
      62          297 :         float cos_w0 = std::cos(w0);
      63          297 :         float sin_w0 = std::sin(w0);
      64          297 :         float alpha = sin_w0 / (2.0f * q);
      65          297 :         float sqA = std::sqrt(A);
      66              : 
      67          297 :         float a0 = (A + 1) - (A - 1) * cos_w0 + 2 * sqA * alpha;
      68          297 :         b0 = (A * ((A + 1) + (A - 1) * cos_w0 + 2 * sqA * alpha)) / a0;
      69          297 :         b1 = (-2 * A * ((A - 1) + (A + 1) * cos_w0)) / a0;
      70          297 :         b2 = (A * ((A + 1) + (A - 1) * cos_w0 - 2 * sqA * alpha)) / a0;
      71          297 :         a1 = (2 * ((A - 1) - (A + 1) * cos_w0)) / a0;
      72          297 :         a2 = ((A + 1) - (A - 1) * cos_w0 - 2 * sqA * alpha) / a0;
      73          297 :     }
      74              : };
      75              : 
      76              : /**
      77              :  * One-pole low-pass filter for tone controls and DC blocking.
      78              :  */
      79          568 : struct OnePole {
      80          346 :     float state = 0.0f;
      81              : 
      82        29208 :     float lp(float input, float coeff) {
      83        29208 :         state += coeff * (input - state);
      84        29208 :         return state;
      85              :     }
      86              : 
      87        26136 :     float hp(float input, float coeff) {
      88        26136 :         state += coeff * (input - state);
      89        26136 :         return input - state;
      90              :     }
      91              : 
      92          863 :     void reset() { state = 0.0f; }
      93              : };
      94              : 
      95              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1