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