andrewm@0
|
1 //
|
andrewm@0
|
2 // Biquad.cpp
|
andrewm@0
|
3 //
|
andrewm@0
|
4 // Created by Nigel Redmon on 11/24/12
|
andrewm@0
|
5 // EarLevel Engineering: earlevel.com
|
andrewm@0
|
6 // Copyright 2012 Nigel Redmon
|
andrewm@0
|
7 //
|
andrewm@0
|
8 // For a complete explanation of the Biquad code:
|
andrewm@0
|
9 // http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
|
andrewm@0
|
10 //
|
andrewm@0
|
11 // License:
|
andrewm@0
|
12 //
|
andrewm@0
|
13 // This source code is provided as is, without warranty.
|
andrewm@0
|
14 // You may copy and distribute verbatim copies of this document.
|
andrewm@0
|
15 // You may modify and use this source code to create binary code
|
andrewm@0
|
16 // for your own purposes, free or commercial.
|
andrewm@0
|
17 //
|
andrewm@0
|
18
|
andrewm@0
|
19 #include <math.h>
|
andrewm@0
|
20 #include "Biquad.h"
|
andrewm@0
|
21 #include <iostream>
|
andrewm@0
|
22
|
andrewm@0
|
23 Biquad::Biquad() {
|
andrewm@0
|
24 type = bq_type_lowpass;
|
andrewm@0
|
25 a0 = 1.0;
|
andrewm@0
|
26 a1 = a2 = b1 = b2 = 0.0;
|
andrewm@0
|
27 Fc = 0.50;
|
andrewm@0
|
28 Q = 0.707;
|
andrewm@0
|
29 peakGain = 0.0;
|
andrewm@0
|
30 z1 = z2 = 0.0;
|
andrewm@0
|
31 }
|
andrewm@0
|
32
|
andrewm@0
|
33 Biquad::Biquad(int type, double Fc, double Q, double peakGainDB) {
|
andrewm@0
|
34 setBiquad(type, Fc, Q, peakGainDB);
|
andrewm@0
|
35 z1 = z2 = 0.0;
|
andrewm@0
|
36 }
|
andrewm@0
|
37
|
andrewm@0
|
38 Biquad::~Biquad() {
|
andrewm@0
|
39 }
|
andrewm@0
|
40
|
andrewm@0
|
41 void Biquad::setType(int type) {
|
andrewm@0
|
42 this->type = type;
|
andrewm@0
|
43 calcBiquad();
|
andrewm@0
|
44 }
|
andrewm@0
|
45
|
andrewm@0
|
46 void Biquad::setQ(double Q) {
|
andrewm@0
|
47 this->Q = Q;
|
andrewm@0
|
48 calcBiquad();
|
andrewm@0
|
49 }
|
andrewm@0
|
50
|
andrewm@0
|
51 void Biquad::setFc(double Fc) {
|
andrewm@0
|
52 this->Fc = Fc;
|
andrewm@0
|
53 calcBiquad();
|
andrewm@0
|
54 }
|
andrewm@0
|
55
|
andrewm@0
|
56 void Biquad::setPeakGain(double peakGainDB) {
|
andrewm@0
|
57 this->peakGain = peakGainDB;
|
andrewm@0
|
58 calcBiquad();
|
andrewm@0
|
59 }
|
andrewm@0
|
60
|
andrewm@0
|
61 void Biquad::setBiquad(int type, double Fc, double Q, double peakGainDB) {
|
andrewm@0
|
62 this->type = type;
|
andrewm@0
|
63 this->Q = Q;
|
andrewm@0
|
64 this->Fc = Fc;
|
andrewm@0
|
65 startFc = Fc;
|
andrewm@0
|
66 startQ = Q;
|
andrewm@0
|
67 startPeakGain = peakGainDB;
|
andrewm@0
|
68 setPeakGain(peakGainDB);
|
andrewm@0
|
69 }
|
andrewm@0
|
70
|
andrewm@0
|
71 void Biquad::calcBiquad(void) {
|
andrewm@0
|
72 double norm;
|
andrewm@0
|
73 double V = pow(10, fabs(peakGain) / 20.0);
|
andrewm@0
|
74 double K = tan(M_PI * Fc);
|
andrewm@0
|
75 switch (this->type) {
|
andrewm@0
|
76 case bq_type_lowpass:
|
andrewm@0
|
77 norm = 1 / (1 + K / Q + K * K);
|
andrewm@0
|
78 a0 = K * K * norm;
|
andrewm@0
|
79 a1 = 2 * a0;
|
andrewm@0
|
80 a2 = a0;
|
andrewm@0
|
81 b1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
82 b2 = (1 - K / Q + K * K) * norm;
|
andrewm@0
|
83 break;
|
andrewm@0
|
84
|
andrewm@0
|
85 case bq_type_highpass:
|
andrewm@0
|
86 norm = 1 / (1 + K / Q + K * K);
|
andrewm@0
|
87 a0 = 1 * norm;
|
andrewm@0
|
88 a1 = -2 * a0;
|
andrewm@0
|
89 a2 = a0;
|
andrewm@0
|
90 b1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
91 b2 = (1 - K / Q + K * K) * norm;
|
andrewm@0
|
92 break;
|
andrewm@0
|
93
|
andrewm@0
|
94 case bq_type_bandpass:
|
andrewm@0
|
95 norm = 1 / (1 + K / Q + K * K);
|
andrewm@0
|
96 a0 = K / Q * norm;
|
andrewm@0
|
97 a1 = 0;
|
andrewm@0
|
98 a2 = -a0;
|
andrewm@0
|
99 b1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
100 b2 = (1 - K / Q + K * K) * norm;
|
andrewm@0
|
101 break;
|
andrewm@0
|
102
|
andrewm@0
|
103 case bq_type_notch:
|
andrewm@0
|
104 norm = 1 / (1 + K / Q + K * K);
|
andrewm@0
|
105 a0 = (1 + K * K) * norm;
|
andrewm@0
|
106 a1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
107 a2 = a0;
|
andrewm@0
|
108 b1 = a1;
|
andrewm@0
|
109 b2 = (1 - K / Q + K * K) * norm;
|
andrewm@0
|
110 break;
|
andrewm@0
|
111
|
andrewm@0
|
112 case bq_type_peak:
|
andrewm@0
|
113 if (peakGain >= 0) { // boost
|
andrewm@0
|
114 norm = 1 / (1 + 1/Q * K + K * K);
|
andrewm@0
|
115 a0 = (1 + V/Q * K + K * K) * norm;
|
andrewm@0
|
116 a1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
117 a2 = (1 - V/Q * K + K * K) * norm;
|
andrewm@0
|
118 b1 = a1;
|
andrewm@0
|
119 b2 = (1 - 1/Q * K + K * K) * norm;
|
andrewm@0
|
120 }
|
andrewm@0
|
121 else { // cut
|
andrewm@0
|
122 norm = 1 / (1 + V/Q * K + K * K);
|
andrewm@0
|
123 a0 = (1 + 1/Q * K + K * K) * norm;
|
andrewm@0
|
124 a1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
125 a2 = (1 - 1/Q * K + K * K) * norm;
|
andrewm@0
|
126 b1 = a1;
|
andrewm@0
|
127 b2 = (1 - V/Q * K + K * K) * norm;
|
andrewm@0
|
128 }
|
andrewm@0
|
129 break;
|
andrewm@0
|
130 case bq_type_lowshelf:
|
andrewm@0
|
131 if (peakGain >= 0) { // boost
|
andrewm@0
|
132 norm = 1 / (1 + sqrt(2) * K + K * K);
|
andrewm@0
|
133 a0 = (1 + sqrt(2*V) * K + V * K * K) * norm;
|
andrewm@0
|
134 a1 = 2 * (V * K * K - 1) * norm;
|
andrewm@0
|
135 a2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
|
andrewm@0
|
136 b1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
137 b2 = (1 - sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
138 }
|
andrewm@0
|
139 else { // cut
|
andrewm@0
|
140 norm = 1 / (1 + sqrt(2*V) * K + V * K * K);
|
andrewm@0
|
141 a0 = (1 + sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
142 a1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
143 a2 = (1 - sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
144 b1 = 2 * (V * K * K - 1) * norm;
|
andrewm@0
|
145 b2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
|
andrewm@0
|
146 }
|
andrewm@0
|
147 break;
|
andrewm@0
|
148 case bq_type_highshelf:
|
andrewm@0
|
149 if (peakGain >= 0) { // boost
|
andrewm@0
|
150 norm = 1 / (1 + sqrt(2) * K + K * K);
|
andrewm@0
|
151 a0 = (V + sqrt(2*V) * K + K * K) * norm;
|
andrewm@0
|
152 a1 = 2 * (K * K - V) * norm;
|
andrewm@0
|
153 a2 = (V - sqrt(2*V) * K + K * K) * norm;
|
andrewm@0
|
154 b1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
155 b2 = (1 - sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
156 }
|
andrewm@0
|
157 else { // cut
|
andrewm@0
|
158 norm = 1 / (V + sqrt(2*V) * K + K * K);
|
andrewm@0
|
159 a0 = (1 + sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
160 a1 = 2 * (K * K - 1) * norm;
|
andrewm@0
|
161 a2 = (1 - sqrt(2) * K + K * K) * norm;
|
andrewm@0
|
162 b1 = 2 * (K * K - V) * norm;
|
andrewm@0
|
163 b2 = (V - sqrt(2*V) * K + K * K) * norm;
|
andrewm@0
|
164 }
|
andrewm@0
|
165 break;
|
andrewm@0
|
166 }
|
andrewm@0
|
167
|
andrewm@0
|
168 return;
|
andrewm@0
|
169 }
|