2 * Basic one-pole one-zero filters based on bilinear transform.
3 * Copyright (C) 2001-2007 Krzysztof Foltman
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02111-1307, USA.
20 #ifndef __CALF_ONEPOLE_H
21 #define __CALF_ONEPOLE_H
23 #include "primitives.h"
28 * one-pole filter, for floating point values
29 * coefficient calculation is based on bilinear transform, and the code itself is based on my very old OneSignal lib
30 * lp and hp are *somewhat* tested, allpass is not tested at all
31 * don't use this for integers because it won't work
33 template<class T
= float, class Coeff
= float>
37 typedef std::complex<double> cfloat
;
47 /// Set coefficients for a lowpass filter
48 void set_lp(float fc
, float sr
)
52 Coeff x
= tan (M_PI
* fc
/ (2 * sr
));
58 /// Set coefficients for an allpass filter
59 void set_ap(float fc
, float sr
)
63 Coeff x
= tan (M_PI
* fc
/ (2 * sr
));
69 /// Set coefficients for an allpass filter, using omega instead of fc and sr
70 /// omega = (PI / 2) * fc / sr
71 void set_ap_w(float w
)
81 /// Set coefficients for a highpass filter
82 void set_hp(float fc
, float sr
)
86 Coeff x
= tan (M_PI
* fc
/ (2 * sr
));
93 /// Process one sample
94 inline T
process(T in
)
96 T out
= in
* a0
+ x1
* a1
- y1
* b1
;
102 /// Process one sample, assuming it's a lowpass filter (optimized special case)
103 inline T
process_lp(T in
)
105 T out
= (in
+ x1
) * a0
- y1
* b1
;
111 /// Process one sample, assuming it's a highpass filter (optimized special case)
112 inline T
process_hp(T in
)
114 T out
= (in
- x1
) * a0
- y1
* b1
;
120 /// Process one sample, assuming it's an allpass filter (optimized special case)
121 inline T
process_ap(T in
)
123 T out
= (in
- y1
) * a0
+ x1
;
129 /// Process one sample using external state variables
130 inline T
process_ap(T in
, float &x1
, float &y1
)
132 T out
= (in
- y1
) * a0
+ x1
;
138 /// Process one sample using external state variables, including filter coeff
139 inline T
process_ap(T in
, float &x1
, float &y1
, float a0
)
141 T out
= (in
- y1
) * a0
+ x1
;
147 inline bool empty() const {
151 inline void sanitize()
164 inline void copy_coeffs(const onepole
<U
> &src
)
171 /// Return the filter's gain at frequency freq
172 /// @param freq Frequency to look up
173 /// @param sr Filter sample rate (used to convert frequency to angular frequency)
174 float freq_gain(float freq
, float sr
) const
176 freq
*= 2.0 * M_PI
/ sr
;
177 cfloat z
= 1.0 / exp(cfloat(0.0, freq
));
179 return std::abs(h_z(z
));
182 /// Return H(z) the filter's gain at frequency freq
183 /// @param z Z variable (e^jw)
184 cfloat
h_z(const cfloat
&z
) const
186 return (cfloat(a0
) + double(a1
) * z
) / (cfloat(1.0) + double(b1
) * z
);