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; x1 = x;
18 4979784 : y2 = y1; y1 = y;
19 4979784 : return y;
20 : }
21 :
22 552 : void reset() { x1 = x2 = y1 = y2 = 0; }
23 :
24 : // --- Coefficient computation (Audio EQ Cookbook formulas) ---
25 :
26 297 : void set_low_shelf(float freq, float gain_db, float q, int sample_rate) {
27 297 : float A = std::pow(10.0f, gain_db / 40.0f);
28 297 : float w0 = TWO_PI * freq / sample_rate;
29 297 : float cos_w0 = std::cos(w0);
30 297 : float sin_w0 = std::sin(w0);
31 297 : float alpha = sin_w0 / (2.0f * q);
32 297 : float sqA = std::sqrt(A);
33 :
34 297 : float a0 = (A + 1) + (A - 1) * cos_w0 + 2 * sqA * alpha;
35 297 : b0 = (A * ((A + 1) - (A - 1) * cos_w0 + 2 * sqA * alpha)) / a0;
36 297 : b1 = (2 * A * ((A - 1) - (A + 1) * cos_w0)) / a0;
37 297 : b2 = (A * ((A + 1) - (A - 1) * cos_w0 - 2 * sqA * alpha)) / a0;
38 297 : a1 = (-2 * ((A - 1) + (A + 1) * cos_w0)) / a0;
39 297 : a2 = ((A + 1) + (A - 1) * cos_w0 - 2 * sqA * alpha) / a0;
40 297 : }
41 :
42 297 : void set_peaking(float freq, float gain_db, float q, int sample_rate) {
43 297 : float A = std::pow(10.0f, gain_db / 40.0f);
44 297 : float w0 = TWO_PI * freq / sample_rate;
45 297 : float cos_w0 = std::cos(w0);
46 297 : float sin_w0 = std::sin(w0);
47 297 : float alpha = sin_w0 / (2.0f * q);
48 :
49 297 : float a0 = 1 + alpha / A;
50 297 : b0 = (1 + alpha * A) / a0;
51 297 : b1 = (-2 * cos_w0) / a0;
52 297 : b2 = (1 - alpha * A) / a0;
53 297 : a1 = (-2 * cos_w0) / a0;
54 297 : a2 = (1 - alpha / A) / a0;
55 297 : }
56 :
57 297 : void set_high_shelf(float freq, float gain_db, float q, int sample_rate) {
58 297 : float A = std::pow(10.0f, gain_db / 40.0f);
59 297 : float w0 = TWO_PI * freq / sample_rate;
60 297 : float cos_w0 = std::cos(w0);
61 297 : float sin_w0 = std::sin(w0);
62 297 : float alpha = sin_w0 / (2.0f * q);
63 297 : float sqA = std::sqrt(A);
64 :
65 297 : float a0 = (A + 1) - (A - 1) * cos_w0 + 2 * sqA * alpha;
66 297 : b0 = (A * ((A + 1) + (A - 1) * cos_w0 + 2 * sqA * alpha)) / a0;
67 297 : b1 = (-2 * A * ((A - 1) + (A + 1) * cos_w0)) / a0;
68 297 : b2 = (A * ((A + 1) + (A - 1) * cos_w0 - 2 * sqA * alpha)) / a0;
69 297 : a1 = (2 * ((A - 1) - (A + 1) * cos_w0)) / a0;
70 297 : a2 = ((A + 1) - (A - 1) * cos_w0 - 2 * sqA * alpha) / a0;
71 297 : }
72 : };
73 :
74 : /**
75 : * One-pole low-pass filter for tone controls and DC blocking.
76 : */
77 558 : struct OnePole {
78 341 : float state = 0.0f;
79 :
80 29208 : float lp(float input, float coeff) {
81 29208 : state += coeff * (input - state);
82 29208 : return state;
83 : }
84 :
85 26136 : float hp(float input, float coeff) {
86 26136 : state += coeff * (input - state);
87 26136 : return input - state;
88 : }
89 :
90 842 : void reset() { state = 0.0f; }
91 : };
92 :
93 : } // namespace Amplitron
|