Open Ephys GUI
 All Classes Functions Variables
PoleFilter.h
1 /*******************************************************************************
2 
3 "A Collection of Useful C++ Classes for Digital Signal Processing"
4  By Vincent Falco
5 
6 Official project location:
7 http://code.google.com/p/dspfilterscpp/
8 
9 See Documentation.cpp for contact information, notes, and bibliography.
10 
11 --------------------------------------------------------------------------------
12 
13 License: MIT License (http://www.opensource.org/licenses/mit-license.php)
14 Copyright (c) 2009 by Vincent Falco
15 
16 Permission is hereby granted, free of charge, to any person obtaining a copy
17 of this software and associated documentation files (the "Software"), to deal
18 in the Software without restriction, including without limitation the rights
19 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 copies of the Software, and to permit persons to whom the Software is
21 furnished to do so, subject to the following conditions:
22 
23 The above copyright notice and this permission notice shall be included in
24 all copies or substantial portions of the Software.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 THE SOFTWARE.
33 
34 *******************************************************************************/
35 
36 #ifndef DSPFILTERS_POLEFILTER_H
37 #define DSPFILTERS_POLEFILTER_H
38 
39 #include "Common.h"
40 #include "MathSupplement.h"
41 #include "Cascade.h"
42 
43 namespace Dsp {
44 
45 /*
46  * Base for filters designed via algorithmic placement of poles and zeros.
47  *
48  * Typically, the filter is first designed as a half-band low pass or
49  * low shelf analog filter (s-plane). Then, using a transformation such
50  * as the ones from Constantinides, the poles and zeros of the analog filter
51  * are calculated in the z-plane.
52  *
53  */
54 
55 // Factored implementations to reduce template instantiations
56 
57 class PoleFilterBase2 : public Cascade
58 {
59 public:
60  // This gets the poles/zeros directly from the digital
61  // prototype. It is used to double check the correctness
62  // of the recovery of pole/zeros from biquad coefficients.
63  //
64  // It can also be used to accelerate the interpolation
65  // of pole/zeros for parameter modulation, since a pole
66  // filter already has them calculated
67 
68 #if 1
69  // Commenting this out will pass the call to the Cascade,
70  // which tries to compute the poles and zeros from the biquad
71  // coefficients.
72  std::vector<PoleZeroPair> getPoleZeros () const
73  {
74  std::vector<PoleZeroPair> vpz;
75  const int pairs = (m_digitalProto.getNumPoles () + 1) / 2;
76  for (int i = 0; i < pairs; ++i)
77  vpz.push_back (m_digitalProto[i]);
78  return vpz;
79  }
80 #endif
81 
82 protected:
83  LayoutBase m_digitalProto;
84 };
85 
86 // Serves a container to hold the analog prototype
87 // and the digital pole/zero layout.
88 template <class AnalogPrototype>
90 {
91 protected:
92  void setPrototypeStorage (const LayoutBase& analogStorage,
93  const LayoutBase& digitalStorage)
94  {
95  m_analogProto.setStorage (analogStorage);
96  m_digitalProto = digitalStorage;
97  }
98 
99 protected:
100  AnalogPrototype m_analogProto;
101 };
102 
103 //------------------------------------------------------------------------------
104 
105 // Storage for pole filters
106 template <class BaseClass,
107  int MaxAnalogPoles,
108  int MaxDigitalPoles = MaxAnalogPoles>
109 struct PoleFilter : BaseClass
110  , CascadeStages <(MaxDigitalPoles + 1) / 2>
111 {
112  PoleFilter ()
113  {
114  // This glues together the factored base classes
115  // with the templatized storage classes.
116  BaseClass::setCascadeStorage (this->getCascadeStorage());
117  BaseClass::setPrototypeStorage (m_analogStorage, m_digitalStorage);
118  }
119 
120 private:
121  Layout <MaxAnalogPoles> m_analogStorage;
122  Layout <MaxDigitalPoles> m_digitalStorage;
123 };
124 
125 //------------------------------------------------------------------------------
126 
127 /*
128  * s-plane to z-plane transforms
129  *
130  * For pole filters, an analog prototype is created via placement of
131  * poles and zeros in the s-plane. The analog prototype is either
132  * a halfband low pass or a halfband low shelf. The poles, zeros,
133  * and normalization parameters are transformed into the z-plane
134  * using variants of the bilinear transformation.
135  *
136  */
137 
138 // low pass to low pass
140 {
141 public:
142  LowPassTransform (double fc,
143  LayoutBase& digital,
144  LayoutBase const& analog);
145 
146 private:
147  complex_t transform (complex_t c);
148 
149  double f;
150 };
151 
152 //------------------------------------------------------------------------------
153 
154 // low pass to high pass
156 {
157 public:
158  HighPassTransform (double fc,
159  LayoutBase& digital,
160  LayoutBase const& analog);
161 
162 private:
163  complex_t transform (complex_t c);
164 
165  double f;
166 };
167 
168 //------------------------------------------------------------------------------
169 
170 // low pass to band pass transform
172 {
173 
174 public:
175  BandPassTransform (double fc,
176  double fw,
177  LayoutBase& digital,
178  LayoutBase const& analog);
179 
180 private:
181  ComplexPair transform (complex_t c);
182 
183  double wc;
184  double wc2;
185  double a;
186  double b;
187  double a2;
188  double b2;
189  double ab;
190  double ab_2;
191 };
192 
193 //------------------------------------------------------------------------------
194 
195 // low pass to band stop transform
197 {
198 public:
199  BandStopTransform (double fc,
200  double fw,
201  LayoutBase& digital,
202  LayoutBase const& analog);
203 
204 private:
205  ComplexPair transform (complex_t c);
206 
207  double wc;
208  double wc2;
209  double a;
210  double b;
211  double a2;
212  double b2;
213 };
214 
215 }
216 
217 #endif