andrewm@0
|
1 /*
|
andrewm@0
|
2 TouchKeys: multi-touch musical keyboard control software
|
andrewm@0
|
3 Copyright (c) 2013 Andrew McPherson
|
andrewm@0
|
4
|
andrewm@0
|
5 This program is free software: you can redistribute it and/or modify
|
andrewm@0
|
6 it under the terms of the GNU General Public License as published by
|
andrewm@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
andrewm@0
|
8 (at your option) any later version.
|
andrewm@0
|
9
|
andrewm@0
|
10 This program is distributed in the hope that it will be useful,
|
andrewm@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
andrewm@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
andrewm@0
|
13 GNU General Public License for more details.
|
andrewm@0
|
14
|
andrewm@0
|
15 You should have received a copy of the GNU General Public License
|
andrewm@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
andrewm@0
|
17
|
andrewm@0
|
18 =====================================================================
|
andrewm@0
|
19
|
andrewm@0
|
20 IIRFilter.cpp: template class handling an Nth-order IIR filter on data
|
andrewm@0
|
21 in a given Node.
|
andrewm@0
|
22 */
|
andrewm@0
|
23
|
andrewm@0
|
24 #include "IIRFilter.h"
|
andrewm@0
|
25 #include <cmath>
|
andrewm@0
|
26
|
andrewm@0
|
27 // These are static functions to design IIR filters specifically for floating-point datatypes.
|
andrewm@0
|
28 // vector<double> and be converted to another type at the end if needed.
|
andrewm@0
|
29
|
andrewm@0
|
30 void designFirstOrderLowpass(std::vector<double>& bCoeffs, std::vector<double>& aCoeffs,
|
andrewm@0
|
31 double cutoffFrequency, double sampleFrequency) {
|
andrewm@0
|
32 bCoeffs.clear();
|
andrewm@0
|
33 aCoeffs.clear();
|
andrewm@0
|
34
|
andrewm@0
|
35 double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
|
andrewm@0
|
36 double n = 1.0 / (1.0 + omega);
|
andrewm@0
|
37
|
andrewm@0
|
38 bCoeffs.push_back(omega * n); // B0
|
andrewm@0
|
39 bCoeffs.push_back(omega * n); // B1
|
andrewm@0
|
40 aCoeffs.push_back((omega - 1) * n); // A1
|
andrewm@0
|
41 }
|
andrewm@0
|
42
|
andrewm@0
|
43 void designFirstOrderHighpass(std::vector<double>& bCoeffs, std::vector<double>& aCoeffs,
|
andrewm@0
|
44 double cutoffFrequency, double sampleFrequency) {
|
andrewm@0
|
45 bCoeffs.clear();
|
andrewm@0
|
46 aCoeffs.clear();
|
andrewm@0
|
47
|
andrewm@0
|
48 double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
|
andrewm@0
|
49 double n = 1.0 / (1.0 + omega);
|
andrewm@0
|
50
|
andrewm@0
|
51 bCoeffs.push_back(n); // B0
|
andrewm@0
|
52 bCoeffs.push_back(-n); // B1
|
andrewm@0
|
53 aCoeffs.push_back((omega - 1) * n); // A1
|
andrewm@0
|
54 }
|
andrewm@0
|
55
|
andrewm@0
|
56 void designSecondOrderLowpass(std::vector<double>& bCoeffs, std::vector<double>& aCoeffs,
|
andrewm@0
|
57 double cutoffFrequency, double q, double sampleFrequency) {
|
andrewm@0
|
58 bCoeffs.clear();
|
andrewm@0
|
59 aCoeffs.clear();
|
andrewm@0
|
60
|
andrewm@0
|
61 double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
|
andrewm@0
|
62 double n = 1.0 / (omega*omega + omega/q + 1.0);
|
andrewm@0
|
63 double b0 = n * omega * omega;
|
andrewm@0
|
64
|
andrewm@0
|
65 bCoeffs.push_back(b0); // B0
|
andrewm@0
|
66 bCoeffs.push_back(2.0 * b0); // B1
|
andrewm@0
|
67 bCoeffs.push_back(b0); // B2
|
andrewm@0
|
68 aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
|
andrewm@0
|
69 aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
|
andrewm@0
|
70 }
|
andrewm@0
|
71
|
andrewm@0
|
72 void designSecondOrderHighpass(std::vector<double>& bCoeffs, std::vector<double>& aCoeffs,
|
andrewm@0
|
73 double cutoffFrequency, double q, double sampleFrequency) {
|
andrewm@0
|
74 bCoeffs.clear();
|
andrewm@0
|
75 aCoeffs.clear();
|
andrewm@0
|
76
|
andrewm@0
|
77 double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
|
andrewm@0
|
78 double n = 1.0 / (omega*omega + omega/q + 1.0);
|
andrewm@0
|
79
|
andrewm@0
|
80 bCoeffs.push_back(n); // B0
|
andrewm@0
|
81 bCoeffs.push_back(-2.0 * n); // B1
|
andrewm@0
|
82 bCoeffs.push_back(n); // B2
|
andrewm@0
|
83 aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
|
andrewm@0
|
84 aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
|
andrewm@0
|
85 }
|
andrewm@0
|
86
|
andrewm@0
|
87 void designSecondOrderBandpass(std::vector<double>& bCoeffs, std::vector<double>& aCoeffs,
|
andrewm@0
|
88 double cutoffFrequency, double q, double sampleFrequency) {
|
andrewm@0
|
89 bCoeffs.clear();
|
andrewm@0
|
90 aCoeffs.clear();
|
andrewm@0
|
91
|
andrewm@0
|
92 double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
|
andrewm@0
|
93 double n = 1.0 / (omega*omega + omega/q + 1.0);
|
andrewm@0
|
94 double b0 = n * omega / q;
|
andrewm@0
|
95 bCoeffs.push_back(b0); // B0
|
andrewm@0
|
96 bCoeffs.push_back(0.0); // B1
|
andrewm@0
|
97 bCoeffs.push_back(-b0); // B2
|
andrewm@0
|
98 aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
|
andrewm@0
|
99 aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
|
andrewm@0
|
100 } |