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
|