1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application.
5  *
6  * ReZound is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * ReZound is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  */
20 
21 #ifndef __DSP_SinglePoleFilters_H__
22 #define __DSP_SinglePoleFilters_H__
23 
24 #include "../../config/common.h"
25 
26 #include <math.h>
27 
28 
29 /* --- TDSPSinglePoleLowpassFilter ----------------------
30  *	Based on designs in Chapter 19 of "The Scientist
31  *	and Engineer's Guide to Digital Signal Processing"
32  *
33  *	http://www.dspguide.com
34  *
35  *	Basically a simple RC lowpass filter
36  *
37  *	The first template parameter specifies the type of the input samples (and is thus
38  *	the type also of the output, the return value of processSample() ).  And The second
39  *	template parameter specifies the type of the coefficients used in the calculations.
40  */
41 // ??? an version that uses an LFO would be nice.. and pretty easy... just recalc a0 and b1 from the LFO each time
42 // ??? making prevSample variables might speed up computation since it wouldn't be converting back and forth float<==>integer
43 // ??? Equation 19-6 in the book shows 5 coefficients for a 4 stage lowpass filter as if DSP block had been done 4 times in series
44 template<class sample_t,class coefficient_t=float> class TDSPSinglePoleLowpassFilter
45 {
46 public:
47 	// the cut-off frequency is expressed in a fraction of the sampling rate [0,0.5]
TDSPSinglePoleLowpassFilter(const coefficient_t cutoffFreqFraction)48 	TDSPSinglePoleLowpassFilter(const coefficient_t cutoffFreqFraction) :
49 		b1(exp(-2.0*M_PI*cutoffFreqFraction)),
50 		a0(1.0-b1),
51 		prevSample(0)
52 	{
53 	}
54 
processSample(const sample_t inputSample)55 	const sample_t processSample(const sample_t inputSample)
56 	{
57 		return(prevSample=(sample_t)(a0*inputSample+b1*prevSample));
58 	}
59 
60 private:
61 	const coefficient_t b1,a0;
62 	sample_t prevSample; // 1 sample delay basically
63 };
64 
65 
66 
67 
68 
69 /* --- TDSPSinglePoleHighpassFilter ----------------------
70  *	Based on designs in Chapter 19 of "The Scientist
71  *	and Engineer's Guide to Digital Signal Processing"
72  *
73  *	http://www.dspguide.com/
74  *
75  *	Basically a simple RC highpass filter
76  *
77  *	The first template parameter specifies the type of the input samples (and is thus
78  *	the type also of the output, the return value of processSample() ).  And The second
79  *	template parameter specifies the type of the coefficients used in the calculations.
80  */
81 // ??? an version that uses an LFO would be nice.. and pretty easy... just recalc a0, a1 and b1 ... from the LFO each time
82 // ??? making prevSample variables might speed up computation since it wouldn't be converting back and forth float<==>integer
83 template<class sample_t,class coefficient_t=float> class TDSPSinglePoleHighpassFilter
84 {
85 public:
86 	// the cut-off frequency is expressed in a fraction of the sampling rate [0,0.5]
TDSPSinglePoleHighpassFilter(const coefficient_t cutoffFreqFraction)87 	TDSPSinglePoleHighpassFilter(const coefficient_t cutoffFreqFraction) :
88 		b1(exp(-2.0*M_PI*cutoffFreqFraction)),
89 		a0((1.0+b1)/2),
90 		a1(-(1.0+b1)/2),
91 		prevInputSample(0),
92 		prevOutputSample(0)
93 	{
94 	}
95 
processSample(const sample_t inputSample)96 	const sample_t processSample(const sample_t inputSample)
97 	{
98 		prevOutputSample=(sample_t)(a0*inputSample+a1*prevInputSample+b1*prevOutputSample);
99 		prevInputSample=inputSample;
100 		return(prevOutputSample);
101 	}
102 
103 private:
104 	const coefficient_t b1,a0,a1;
105 	sample_t prevInputSample; // 1 sample delay basically
106 	sample_t prevOutputSample; // 1 sample delay basically
107 };
108 
109 
110 
111 
112 
113 /* --- TDSPBandpassFilter --------------------------------
114  *	Based on designs in Chapter 19 of "The Scientist
115  *	and Engineer's Guide to Digital Signal Processing"
116  *
117  *	http://www.dspguide.com/
118  *
119  *	The first template parameter specifies the type of the input samples (and is thus
120  *	the type also of the output, the return value of processSample() ).  And The second
121  *	template parameter specifies the type of the coefficients used in the calculations.
122  *
123  *	***NOTE*** -- this is coded exactly the same as TDSPNotchFilter except in the calculation of a1 and a2
124  *		??? perhaps use inheritance
125  */
126 // ??? an version that uses LFO2 would be nice.. and pretty easy... just recalc a0 and b1 ... from the LFOs each time
127 // ??? making prevSample variables might speed up computation since it wouldn't be converting back and forth float<==>integer
128 template<class sample_t,class coefficient_t=float> class TDSPBandpassFilter
129 {
130 public:
131 	// the band frequency is expressed in a fraction of the sampling rate [0,0.5] as is the band width
TDSPBandpassFilter(const coefficient_t bandFreqFraction,const coefficient_t bandWidthFraction)132 	TDSPBandpassFilter(const coefficient_t bandFreqFraction,const coefficient_t bandWidthFraction) :
133 		R(1.0-3.0*bandWidthFraction),
134 		K((1.0-2.0*R*cos(2.0*M_PI*bandFreqFraction)+R*R)/(2.0-2.0*cos(2.0*M_PI*bandFreqFraction))),
135 		a0(1.0-K),
136 		a1(2.0*(K-R)*cos(2.0*M_PI*bandFreqFraction)),
137 		a2(R*R-K),
138 		b1(2.0*R*cos(2.0*M_PI*bandFreqFraction)),
139 		b2(-(R*R)),
140 		prevInputSample1(0),
141 		prevInputSample2(0),
142 		prevOutputSample1(0),
143 		prevOutputSample2(0)
144 	{
145 	}
146 
processSample(const sample_t inputSample)147 	const sample_t processSample(const sample_t inputSample)
148 	{
149 		const sample_t outputSample=(sample_t)(a0*inputSample+a1*prevInputSample1+a2*prevInputSample2+b1*prevOutputSample1+b2*prevOutputSample2);
150 
151 		prevOutputSample2=prevOutputSample1;
152 		prevOutputSample1=outputSample;
153 
154 		prevInputSample2=prevInputSample1;
155 		prevInputSample1=inputSample;
156 
157 		return(outputSample);
158 	}
159 
160 private:
161 	const coefficient_t R,K;
162 	const coefficient_t a0,a1,a2,b1,b2;
163 	sample_t prevInputSample1,prevInputSample2; // 2 sample delay basically
164 	sample_t prevOutputSample1,prevOutputSample2; // 2 sample delay basically
165 };
166 
167 
168 
169 
170 
171 /* --- TDSPNotchFilter -----------------------------------
172  *	Based on designs in Chapter 19 of "The Scientist
173  *	and Engineer's Guide to Digital Signal Processing"
174  *
175  *	http://www.dspguide.com/
176  *
177  *	The first template parameter specifies the type of the input samples (and is thus
178  *	the type also of the output, the return value of processSample() ).  And The second
179  *	template parameter specifies the type of the coefficients used in the calculations.
180  *
181  *	***NOTE*** -- this is coded exactly the same as TDSPBandpassFilter except in the calculation of a1 and a2
182  *		??? perhaps use inheritance
183  */
184 // ??? an version that uses LFO2 would be nice.. and pretty easy... just recalc a0 and b1 ... from the LFOs each time
185 // ??? making prevSample variables might speed up computation since it wouldn't be converting back and forth float<==>integer
186 template<class sample_t,class coefficient_t=float> class TDSPNotchFilter
187 {
188 public:
189 	// the band frequency is expressed in a fraction of the sampling rate [0,0.5] as is the band width
TDSPNotchFilter(const coefficient_t bandFreqFraction,const coefficient_t bandWidthFraction)190 	TDSPNotchFilter(const coefficient_t bandFreqFraction,const coefficient_t bandWidthFraction) :
191 		R(1.0-3.0*bandWidthFraction),
192 		K((1.0-2.0*R*cos(2.0*M_PI*bandFreqFraction)+R*R)/(2.0-2.0*cos(2.0*M_PI*bandFreqFraction))),
193 		a0(K),
194 		a1(-2.0*K*cos(2.0*M_PI*bandFreqFraction)),
195 		a2(K),
196 		b1(2.0*R*cos(2.0*M_PI*bandFreqFraction)),
197 		b2(-(R*R)),
198 		prevInputSample1(0),
199 		prevInputSample2(0),
200 		prevOutputSample1(0),
201 		prevOutputSample2(0)
202 	{
203 	}
204 
processSample(const sample_t inputSample)205 	const sample_t processSample(const sample_t inputSample)
206 	{
207 		const sample_t outputSample=(sample_t)(a0*inputSample+a1*prevInputSample1+a2*prevInputSample2+b1*prevOutputSample1+b2*prevOutputSample2);
208 
209 		prevOutputSample2=prevOutputSample1;
210 		prevOutputSample1=outputSample;
211 
212 		prevInputSample2=prevInputSample1;
213 		prevInputSample1=inputSample;
214 
215 		return(outputSample);
216 	}
217 
218 private:
219 	const coefficient_t R,K;
220 	const coefficient_t a0,a1,a2,b1,b2;
221 	sample_t prevInputSample1,prevInputSample2; // 2 sample delay basically
222 	sample_t prevOutputSample1,prevOutputSample2; // 2 sample delay basically
223 };
224 
225 #endif
226