Mercurial > hg > qm-dsp
comparison dsp/signalconditioning/Filter.cpp @ 193:ca658c7215a9
Faster filter implementation with explicit FIR support
author | Chris Cannam |
---|---|
date | Wed, 07 Oct 2015 10:36:09 +0100 |
parents | e5907ae6de17 |
children | ccd2019190bf |
comparison
equal
deleted
inserted
replaced
192:3780b91297ea | 193:ca658c7215a9 |
---|---|
2 | 2 |
3 /* | 3 /* |
4 QM DSP Library | 4 QM DSP Library |
5 | 5 |
6 Centre for Digital Music, Queen Mary, University of London. | 6 Centre for Digital Music, Queen Mary, University of London. |
7 This file 2005-2006 Christian Landone. | |
8 | 7 |
9 This program is free software; you can redistribute it and/or | 8 This program is free software; you can redistribute it and/or |
10 modify it under the terms of the GNU General Public License as | 9 modify it under the terms of the GNU General Public License as |
11 published by the Free Software Foundation; either version 2 of the | 10 published by the Free Software Foundation; either version 2 of the |
12 License, or (at your option) any later version. See the file | 11 License, or (at your option) any later version. See the file |
13 COPYING included with this distribution for more information. | 12 COPYING included with this distribution for more information. |
14 */ | 13 */ |
15 | 14 |
16 #include "Filter.h" | 15 #include "Filter.h" |
17 | 16 |
18 ////////////////////////////////////////////////////////////////////// | 17 #include <stdexcept> |
19 // Construction/Destruction | |
20 ////////////////////////////////////////////////////////////////////// | |
21 | 18 |
22 Filter::Filter( FilterConfig Config ) | 19 using namespace std; |
20 | |
21 Filter::Filter(Parameters params) | |
23 { | 22 { |
24 m_ord = 0; | 23 if (params.a.empty()) { |
25 m_outBuffer = NULL; | 24 m_fir = true; |
26 m_inBuffer = NULL; | 25 if (params.b.empty()) { |
26 throw logic_error("Filter must have at least one pair of coefficients"); | |
27 } | |
28 } else { | |
29 m_fir = false; | |
30 if (params.a.size() != params.b.size()) { | |
31 throw logic_error("Inconsistent numbers of filter coefficients"); | |
32 } | |
33 } | |
34 | |
35 m_sz = int(params.b.size()); | |
36 m_order = m_sz - 1; | |
27 | 37 |
28 initialise( Config ); | 38 m_a = params.a; |
39 m_b = params.b; | |
40 | |
41 // We keep some empty space at the start of the buffer, and | |
42 // encroach gradually into it as we add individual sample | |
43 // calculations at the start. Then when we run out of space, we | |
44 // move the buffer back to the end and begin again. This is | |
45 // significantly faster than moving the whole buffer along in | |
46 // 1-sample steps every time. | |
47 | |
48 m_offmax = 20; | |
49 m_offa = m_offmax; | |
50 m_offb = m_offmax; | |
51 | |
52 if (!m_fir) { | |
53 m_bufa.resize(m_order + m_offmax); | |
54 } | |
55 | |
56 m_bufb.resize(m_sz + m_offmax); | |
29 } | 57 } |
30 | 58 |
31 Filter::~Filter() | 59 Filter::~Filter() |
32 { | 60 { |
33 deInitialise(); | |
34 } | 61 } |
35 | 62 |
36 void Filter::initialise( FilterConfig Config ) | 63 void |
64 Filter::reset() | |
37 { | 65 { |
38 m_ord = Config.ord; | 66 m_offb = m_offmax; |
39 m_ACoeffs = Config.ACoeffs; | 67 m_offa = m_offmax; |
40 m_BCoeffs = Config.BCoeffs; | |
41 | 68 |
42 m_inBuffer = new double[ m_ord + 1 ]; | 69 if (!m_fir) { |
43 m_outBuffer = new double[ m_ord + 1 ]; | 70 m_bufa.assign(m_bufa.size(), 0.0); |
71 } | |
44 | 72 |
45 reset(); | 73 m_bufb.assign(m_bufb.size(), 0.0); |
46 } | 74 } |
47 | 75 |
48 void Filter::deInitialise() | 76 void |
77 Filter::process(const double *const __restrict__ in, | |
78 double *const __restrict__ out, | |
79 const int n) | |
49 { | 80 { |
50 delete[] m_inBuffer; | 81 for (int s = 0; s < n; ++s) { |
51 delete[] m_outBuffer; | 82 |
83 if (m_offb > 0) --m_offb; | |
84 else { | |
85 for (int i = m_sz - 2; i >= 0; --i) { | |
86 m_bufb[i + m_offmax + 1] = m_bufb[i]; | |
87 } | |
88 m_offb = m_offmax; | |
89 } | |
90 m_bufb[m_offb] = in[s]; | |
91 | |
92 double b_sum = 0.0; | |
93 for (int i = 0; i < m_sz; ++i) { | |
94 b_sum += m_b[i] * m_bufb[i + m_offb]; | |
95 } | |
96 | |
97 double outval; | |
98 | |
99 if (m_fir) { | |
100 | |
101 outval = b_sum; | |
102 | |
103 } else { | |
104 | |
105 double a_sum = 0.0; | |
106 for (int i = 0; i < m_order; ++i) { | |
107 a_sum += m_a[i + 1] * m_bufa[i + m_offa]; | |
108 } | |
109 | |
110 outval = b_sum - a_sum; | |
111 | |
112 if (m_offa > 0) --m_offa; | |
113 else { | |
114 for (int i = m_order - 2; i >= 0; --i) { | |
115 m_bufa[i + m_offmax + 1] = m_bufa[i]; | |
116 } | |
117 m_offa = m_offmax; | |
118 } | |
119 m_bufa[m_offa] = outval; | |
120 } | |
121 | |
122 out[s] = outval; | |
123 } | |
52 } | 124 } |
53 | 125 |
54 void Filter::reset() | |
55 { | |
56 for( unsigned int i = 0; i < m_ord+1; i++ ){ m_inBuffer[ i ] = 0.0; } | |
57 for(unsigned int i = 0; i < m_ord+1; i++ ){ m_outBuffer[ i ] = 0.0; } | |
58 } | |
59 | |
60 void Filter::process( double *src, double *dst, unsigned int length ) | |
61 { | |
62 unsigned int SP,i,j; | |
63 | |
64 double xin,xout; | |
65 | |
66 for (SP=0;SP<length;SP++) | |
67 { | |
68 xin=src[SP]; | |
69 /* move buffer */ | |
70 for ( i = 0; i < m_ord; i++) {m_inBuffer[ m_ord - i ]=m_inBuffer[ m_ord - i - 1 ];} | |
71 m_inBuffer[0]=xin; | |
72 | |
73 xout=0.0; | |
74 for (j=0;j< m_ord + 1; j++) | |
75 xout = xout + m_BCoeffs[ j ] * m_inBuffer[ j ]; | |
76 for (j = 0; j < m_ord; j++) | |
77 xout= xout - m_ACoeffs[ j + 1 ] * m_outBuffer[ j ]; | |
78 | |
79 dst[ SP ] = xout; | |
80 for ( i = 0; i < m_ord - 1; i++ ) { m_outBuffer[ m_ord - i - 1 ] = m_outBuffer[ m_ord - i - 2 ];} | |
81 m_outBuffer[0]=xout; | |
82 | |
83 } /* end of SP loop */ | |
84 } | |
85 | |
86 | |
87 |