kwave  18.07.70
LowPassFilter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  LowPassFilter.cpp - transmission function of a low pass filter
3  -------------------
4  begin : Mar 15 2003
5  copyright : (C) 2003 by Thomas Eschenbacher
6  email : Thomas Eschenbacher <thomas.eschenbacher@gmx.de>
7 
8  filter functions:
9  Copyright (C) 1998 Juhana Sadeharju <kouhia@nic.funet.fi>
10  ***************************************************************************/
11 
12 /***************************************************************************
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  ***************************************************************************/
20 
21 #include "config.h"
22 #include <complex>
23 #include <math.h>
24 
25 #include "LowPassFilter.h"
26 
27 //***************************************************************************
29  :Kwave::SampleSource(Q_NULLPTR), m_buffer(blockSize()),
30  m_f_cutoff(M_PI)
31 {
32  initFilter();
33 }
34 
35 //***************************************************************************
37 {
38 }
39 
40 //***************************************************************************
42 {
43  emit output(m_buffer);
44 }
45 
46 //***************************************************************************
48 {
49  m_filter.x1 = 0.0;
50  m_filter.x2 = 0.0;
51  m_filter.y1 = 0.0;
52  m_filter.y2 = 0.0;
53  m_filter.y = 0.0;
54 }
55 
56 //***************************************************************************
57 /*
58  * Presence and Shelve filters as given in
59  * James A. Moorer
60  * The manifold joys of conformal mapping:
61  * applications to digital filtering in the studio
62  * JAES, Vol. 31, No. 11, 1983 November
63  */
64 
65 /*#define SPN MINDOUBLE*/
66 #define SPN 0.00001
67 
68 static void shelve(double cf, double boost,
69  double *a0, double *a1, double *a2,
70  double *b1, double *b2)
71 {
72  double a, A, F, tmp, b0, recipb0, asq, F2, gamma2, siggam2, gam2p1;
73  double gamman, gammad, ta0, ta1, ta2, tb0, tb1, tb2, aa1, ab1;
74 
75  a = tan(M_PI * (cf - 0.25));
76  asq = a * a;
77  A = pow(10.0, boost / 20.0);
78  if ((boost < 6.0) && (boost > -6.0)) F = sqrt(A);
79  else if (A > 1.0) F = A / sqrt(2.0);
80  else F = A*sqrt(2.0);
81 
82  F2 = F * F;
83  tmp = A * A - F2;
84  if (fabs(tmp) <= SPN) gammad = 1.0;
85  else gammad = pow((F2 - 1.0) / tmp, 0.25);
86  gamman = sqrt(A) * gammad;
87 
88  gamma2 = gamman * gamman;
89  gam2p1 = 1.0 + gamma2;
90  siggam2 = 2.0 * sqrt(2.0) / 2.0 * gamman;
91  ta0 = gam2p1 + siggam2;
92  ta1 = -2.0 * (1.0 - gamma2);
93  ta2 = gam2p1 - siggam2;
94 
95  gamma2 = gammad * gammad;
96  gam2p1 = 1.0 + gamma2;
97  siggam2 = 2.0 * sqrt(2.0) / 2.0 * gammad;
98  tb0 = gam2p1 + siggam2;
99  tb1 = -2.0 * (1.0 - gamma2);
100  tb2 = gam2p1 - siggam2;
101 
102  aa1 = a * ta1;
103  *a0 = ta0 + aa1 + asq * ta2;
104  *a1 = 2.0 * a * (ta0 + ta2) + (1.0 + asq) * ta1;
105  *a2 = asq * ta0 + aa1 + ta2;
106 
107  ab1 = a * tb1;
108  b0 = tb0 + ab1 + asq * tb2;
109  *b1 = 2.0 * a * (tb0 + tb2) + (1.0 + asq) * tb1;
110  *b2 = asq * tb0 + ab1 + tb2;
111 
112  recipb0 = 1.0 / b0;
113  *a0 *= recipb0;
114  *a1 *= recipb0;
115  *a2 *= recipb0;
116  *b1 *= recipb0;
117  *b2 *= recipb0;
118 }
119 
120 //***************************************************************************
122 {
123  double gain;
124  double boost = 80.0;
125 
126  gain = pow(10.0, boost / 20.0);
127  shelve(freq / (2 * M_PI), boost,
128  &m_filter.cx, &m_filter.cx1, &m_filter.cx2,
129  &m_filter.cy1, &m_filter.cy2);
130  m_filter.cx /= gain;
131  m_filter.cx1 /= gain;
132  m_filter.cx2 /= gain;
133  m_filter.cy1 = -m_filter.cy1;
134  m_filter.cy2 = -m_filter.cy2;
135 }
136 
137 //***************************************************************************
139 {
140  const Kwave::SampleArray &in = data;
141  bool ok = m_buffer.resize(in.size());
142  Q_ASSERT(ok);
143  Q_UNUSED(ok);
144 
146 
147  for (unsigned i = 0; i < in.size(); i++)
148  {
149  // do the filtering
150  m_filter.x = sample2double(in[i]);
151  m_filter.y =
152  m_filter.cx * m_filter.x +
153  m_filter.cx1 * m_filter.x1 +
154  m_filter.cx2 * m_filter.x2 +
155  m_filter.cy1 * m_filter.y1 +
156  m_filter.cy2 * m_filter.y2;
157  m_filter.x2 = m_filter.x1;
158  m_filter.x1 = m_filter.x;
159  m_filter.y2 = m_filter.y1;
160  m_filter.y1 = m_filter.y;
161  m_buffer[i] = double2sample(0.95 * m_filter.y);
162  }
163 }
164 
165 //***************************************************************************
166 double Kwave::LowPassFilter::at(double f)
167 {
168  /*
169  * filter function as extracted from the aRts code:
170  *
171  * y[t] = cx*x[t] + cx1*x[t-1] + cx2*x[t-2]
172  * + cy1*y[t-1] + cy2*y[t-2];
173  *
174  * convert filter coefficients to our notation:
175  */
176  double a0, a1, a2, b1, b2;
177  a0 = m_filter.cx;
178  a1 = m_filter.cx1;
179  a2 = m_filter.cx2;
180  b1 = m_filter.cy1;
181  b2 = m_filter.cy2;
182 
183  /*
184  * a0*z^2 + a1*z + a2
185  * H(z) = ------------------ | z = e ^ (j*2*pi*f)
186  * z^2 - b1*z - b0
187  */
188  std::complex<double> h;
189  std::complex<double> w;
190  std::complex<double> j(0.0,1.0);
191  std::complex<double> z;
192 
193  w = f;
194  z = std::exp(j*w);
195 
196  // get h[z] at z=e^jw
197  h = 0.95 * (a0 * (z*z) + (a1*z) + a2) / ((z*z) - (b1*z) - b2);
198 
199  return sqrt(std::norm(h));
200 }
201 
202 //***************************************************************************
203 void Kwave::LowPassFilter::setFrequency(const QVariant fc)
204 {
205 
206  double new_freq = QVariant(fc).toDouble();
207  if (qFuzzyCompare(new_freq, m_f_cutoff)) return; // nothing to do
208 
209  m_f_cutoff = new_freq;
210  initFilter();
212 }
213 
214 //***************************************************************************
215 //***************************************************************************
virtual ~LowPassFilter() Q_DECL_OVERRIDE
Definition: App.h:33
static void shelve(double cf, double boost, double *a0, double *a1, double *a2, double *b1, double *b2)
virtual double at(double f) Q_DECL_OVERRIDE
Kwave::SampleArray m_buffer
Definition: LowPassFilter.h:78
void input(Kwave::SampleArray data)
void output(Kwave::SampleArray data)
static double sample2double(const sample_t s)
Definition: Sample.h:73
void setFrequency(const QVariant fc)
static sample_t double2sample(const double f)
Definition: Sample.h:81
virtual void goOn() Q_DECL_OVERRIDE
unsigned int size() const
void normed_setfilter_shelvelowpass(double freq)
#define SPN
bool resize(unsigned int size) Q_REQUIRED_RESULT
struct Kwave::LowPassFilter::@13 m_filter