Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: Biquad_multiChan.cpp
- Revision:
- 0:675506e540be
diff -r 000000000000 -r 675506e540be Biquad_multiChan.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Biquad_multiChan.cpp Mon Mar 23 19:22:04 2015 +0000
@@ -0,0 +1,180 @@
+//
+// Biquad.cpp
+//
+// Created by Nigel Redmon on 11/24/12
+// EarLevel Engineering: earlevel.com
+// Copyright 2012 Nigel Redmon
+//
+// For a complete explanation of the Biquad code:
+// http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
+//
+// License:
+//
+// This source code is provided as is, without warranty.
+// You may copy and distribute verbatim copies of this document.
+// You may modify and use this source code to create binary code
+// for your own purposes, free or commercial.
+//
+// Extended by Chip Audette to handle multiple channels of data
+// that are being filtered by the same coefficients
+//
+
+#include <math.h>
+#include "Biquad_multiChan.h"
+
+
+/*
+Biquad_multiChan::Biquad_multiChan() {
+ type = bq_type_lowpass;
+ a0 = 1.0;
+ a1 = a2 = b1 = b2 = 0.0;
+ Fc = 0.50;
+ Q = 0.707;
+ peakGain = 0.0;
+ z1 = z2 = 0.0;
+}
+*/
+
+Biquad_multiChan::Biquad_multiChan(int N,int type, double Fc, double Q, double peakGainDB) {
+ setBiquad(type, Fc, Q, peakGainDB);
+
+ Nchan = N;
+ z1 = new double[Nchan];
+ z2 = new double[Nchan];
+ for (int Ichan=0;Ichan<Nchan;Ichan++) {
+ z1[Ichan]=0.0;
+ z2[Ichan]=0.0;
+ }
+}
+
+Biquad_multiChan::~Biquad_multiChan() {
+ delete z2;
+ delete z1;
+}
+
+void Biquad_multiChan::setType(int type) {
+ this->type = type;
+ calcBiquad();
+}
+
+void Biquad_multiChan::setQ(double Q) {
+ this->Q = Q;
+ calcBiquad();
+}
+
+void Biquad_multiChan::setFc(double Fc) {
+ this->Fc = Fc;
+ calcBiquad();
+}
+
+void Biquad_multiChan::setPeakGain(double peakGainDB) {
+ this->peakGain = peakGainDB;
+ calcBiquad();
+}
+
+void Biquad_multiChan::setBiquad(int type, double Fc, double Q, double peakGainDB) {
+ this->type = type;
+ this->Q = Q;
+ this->Fc = Fc;
+ setPeakGain(peakGainDB);
+}
+
+void Biquad_multiChan::calcBiquad(void) {
+ double norm;
+ double V = pow(10, fabs(peakGain) / 20.0);
+ double K = tan(M_PI * Fc);
+ switch (this->type) {
+ case bq_type_lowpass:
+ norm = 1 / (1 + K / Q + K * K);
+ a0 = K * K * norm;
+ a1 = 2 * a0;
+ a2 = a0;
+ b1 = 2 * (K * K - 1) * norm;
+ b2 = (1 - K / Q + K * K) * norm;
+ break;
+
+ case bq_type_highpass:
+ norm = 1 / (1 + K / Q + K * K);
+ a0 = 1 * norm;
+ a1 = -2 * a0;
+ a2 = a0;
+ b1 = 2 * (K * K - 1) * norm;
+ b2 = (1 - K / Q + K * K) * norm;
+ break;
+
+ case bq_type_bandpass:
+ norm = 1.0 / (1.0 + K / Q + K * K);
+ a0 = K / Q * norm;
+ a1 = 0.0;
+ a2 = -a0;
+ b1 = 2.0 * (K * K - 1.0) * norm;
+ b2 = (1.0 - K / Q + K * K) * norm;
+ break;
+
+ case bq_type_notch:
+ norm = 1.0 / (1.0 + K / Q + K * K);
+ a0 = (1 + K * K) * norm;
+ a1 = 2.0 * (K * K - 1) * norm;
+ a2 = a0;
+ b1 = a1;
+ b2 = (1.0 - K / Q + K * K) * norm;
+ break;
+
+ case bq_type_peak:
+ if (peakGain >= 0) { // boost
+ norm = 1 / (1 + 1/Q * K + K * K);
+ a0 = (1 + V/Q * K + K * K) * norm;
+ a1 = 2 * (K * K - 1) * norm;
+ a2 = (1 - V/Q * K + K * K) * norm;
+ b1 = a1;
+ b2 = (1 - 1/Q * K + K * K) * norm;
+ }
+ else { // cut
+ norm = 1 / (1 + V/Q * K + K * K);
+ a0 = (1 + 1/Q * K + K * K) * norm;
+ a1 = 2 * (K * K - 1) * norm;
+ a2 = (1 - 1/Q * K + K * K) * norm;
+ b1 = a1;
+ b2 = (1 - V/Q * K + K * K) * norm;
+ }
+ break;
+ case bq_type_lowshelf:
+ if (peakGain >= 0) { // boost
+ norm = 1 / (1 + sqrt(2) * K + K * K);
+ a0 = (1 + sqrt(2*V) * K + V * K * K) * norm;
+ a1 = 2 * (V * K * K - 1) * norm;
+ a2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
+ b1 = 2 * (K * K - 1) * norm;
+ b2 = (1 - sqrt(2) * K + K * K) * norm;
+ }
+ else { // cut
+ norm = 1 / (1 + sqrt(2*V) * K + V * K * K);
+ a0 = (1 + sqrt(2) * K + K * K) * norm;
+ a1 = 2 * (K * K - 1) * norm;
+ a2 = (1 - sqrt(2) * K + K * K) * norm;
+ b1 = 2 * (V * K * K - 1) * norm;
+ b2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
+ }
+ break;
+ case bq_type_highshelf:
+ if (peakGain >= 0) { // boost
+ norm = 1 / (1 + sqrt(2) * K + K * K);
+ a0 = (V + sqrt(2*V) * K + K * K) * norm;
+ a1 = 2 * (K * K - V) * norm;
+ a2 = (V - sqrt(2*V) * K + K * K) * norm;
+ b1 = 2 * (K * K - 1) * norm;
+ b2 = (1 - sqrt(2) * K + K * K) * norm;
+ }
+ else { // cut
+ norm = 1 / (V + sqrt(2*V) * K + K * K);
+ a0 = (1 + sqrt(2) * K + K * K) * norm;
+ a1 = 2 * (K * K - 1) * norm;
+ a2 = (1 - sqrt(2) * K + K * K) * norm;
+ b1 = 2 * (K * K - V) * norm;
+ b2 = (V - sqrt(2*V) * K + K * K) * norm;
+ }
+ break;
+ }
+
+ return;
+}