andrewm@0: /*
andrewm@0: TouchKeys: multi-touch musical keyboard control software
andrewm@0: Copyright (c) 2013 Andrew McPherson
andrewm@0:
andrewm@0: This program is free software: you can redistribute it and/or modify
andrewm@0: it under the terms of the GNU General Public License as published by
andrewm@0: the Free Software Foundation, either version 3 of the License, or
andrewm@0: (at your option) any later version.
andrewm@0:
andrewm@0: This program is distributed in the hope that it will be useful,
andrewm@0: but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0: GNU General Public License for more details.
andrewm@0:
andrewm@0: You should have received a copy of the GNU General Public License
andrewm@0: along with this program. If not, see .
andrewm@0:
andrewm@0: =====================================================================
andrewm@0:
andrewm@0: IIRFilter.cpp: template class handling an Nth-order IIR filter on data
andrewm@0: in a given Node.
andrewm@0: */
andrewm@0:
andrewm@20: #ifdef _MSC_VER
andrewm@20: #define _USE_MATH_DEFINES
andrewm@20: #endif
andrewm@20: #include
andrewm@0: #include "IIRFilter.h"
andrewm@0:
andrewm@0: // These are static functions to design IIR filters specifically for floating-point datatypes.
andrewm@0: // vector and be converted to another type at the end if needed.
andrewm@0:
andrewm@0: void designFirstOrderLowpass(std::vector& bCoeffs, std::vector& aCoeffs,
andrewm@0: double cutoffFrequency, double sampleFrequency) {
andrewm@0: bCoeffs.clear();
andrewm@0: aCoeffs.clear();
andrewm@0:
andrewm@0: double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
andrewm@0: double n = 1.0 / (1.0 + omega);
andrewm@0:
andrewm@0: bCoeffs.push_back(omega * n); // B0
andrewm@0: bCoeffs.push_back(omega * n); // B1
andrewm@0: aCoeffs.push_back((omega - 1) * n); // A1
andrewm@0: }
andrewm@0:
andrewm@0: void designFirstOrderHighpass(std::vector& bCoeffs, std::vector& aCoeffs,
andrewm@0: double cutoffFrequency, double sampleFrequency) {
andrewm@0: bCoeffs.clear();
andrewm@0: aCoeffs.clear();
andrewm@0:
andrewm@0: double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
andrewm@0: double n = 1.0 / (1.0 + omega);
andrewm@0:
andrewm@0: bCoeffs.push_back(n); // B0
andrewm@0: bCoeffs.push_back(-n); // B1
andrewm@0: aCoeffs.push_back((omega - 1) * n); // A1
andrewm@0: }
andrewm@0:
andrewm@0: void designSecondOrderLowpass(std::vector& bCoeffs, std::vector& aCoeffs,
andrewm@0: double cutoffFrequency, double q, double sampleFrequency) {
andrewm@0: bCoeffs.clear();
andrewm@0: aCoeffs.clear();
andrewm@0:
andrewm@0: double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
andrewm@0: double n = 1.0 / (omega*omega + omega/q + 1.0);
andrewm@0: double b0 = n * omega * omega;
andrewm@0:
andrewm@0: bCoeffs.push_back(b0); // B0
andrewm@0: bCoeffs.push_back(2.0 * b0); // B1
andrewm@0: bCoeffs.push_back(b0); // B2
andrewm@0: aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
andrewm@0: aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
andrewm@0: }
andrewm@0:
andrewm@0: void designSecondOrderHighpass(std::vector& bCoeffs, std::vector& aCoeffs,
andrewm@0: double cutoffFrequency, double q, double sampleFrequency) {
andrewm@0: bCoeffs.clear();
andrewm@0: aCoeffs.clear();
andrewm@0:
andrewm@0: double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
andrewm@0: double n = 1.0 / (omega*omega + omega/q + 1.0);
andrewm@0:
andrewm@0: bCoeffs.push_back(n); // B0
andrewm@0: bCoeffs.push_back(-2.0 * n); // B1
andrewm@0: bCoeffs.push_back(n); // B2
andrewm@0: aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
andrewm@0: aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
andrewm@0: }
andrewm@0:
andrewm@0: void designSecondOrderBandpass(std::vector& bCoeffs, std::vector& aCoeffs,
andrewm@0: double cutoffFrequency, double q, double sampleFrequency) {
andrewm@0: bCoeffs.clear();
andrewm@0: aCoeffs.clear();
andrewm@0:
andrewm@0: double omega = tan(M_PI * cutoffFrequency / sampleFrequency);
andrewm@0: double n = 1.0 / (omega*omega + omega/q + 1.0);
andrewm@0: double b0 = n * omega / q;
andrewm@0: bCoeffs.push_back(b0); // B0
andrewm@0: bCoeffs.push_back(0.0); // B1
andrewm@0: bCoeffs.push_back(-b0); // B2
andrewm@0: aCoeffs.push_back(2.0 * n * (omega * omega - 1.0)); // A1
andrewm@0: aCoeffs.push_back(n * (omega * omega - omega / q + 1.0));
andrewm@0: }