c@225
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@225
|
2
|
c@225
|
3 /*
|
c@225
|
4 QM DSP Library
|
c@225
|
5
|
c@225
|
6 Centre for Digital Music, Queen Mary, University of London.
|
c@309
|
7 This file 2005-2006 Christian Landone.
|
c@309
|
8
|
c@309
|
9 This program is free software; you can redistribute it and/or
|
c@309
|
10 modify it under the terms of the GNU General Public License as
|
c@309
|
11 published by the Free Software Foundation; either version 2 of the
|
c@309
|
12 License, or (at your option) any later version. See the file
|
c@309
|
13 COPYING included with this distribution for more information.
|
c@225
|
14 */
|
c@225
|
15
|
c@225
|
16 #include "FiltFilt.h"
|
c@225
|
17
|
c@417
|
18 FiltFilt::FiltFilt(Filter::Parameters parameters) :
|
c@417
|
19 m_filter(parameters)
|
c@225
|
20 {
|
c@417
|
21 m_ord = m_filter.getOrder();
|
c@225
|
22 }
|
c@225
|
23
|
c@225
|
24 FiltFilt::~FiltFilt()
|
c@225
|
25 {
|
c@225
|
26 }
|
c@225
|
27
|
cannam@506
|
28 void FiltFilt::process(const double *const QM_R__ src,
|
cannam@506
|
29 double *const QM_R__ dst,
|
cannam@506
|
30 const int length)
|
cannam@483
|
31 {
|
cannam@503
|
32 int i;
|
c@225
|
33
|
c@283
|
34 if (length == 0) return;
|
c@283
|
35
|
cannam@503
|
36 int nFilt = m_ord + 1;
|
cannam@503
|
37 int nFact = 3 * (nFilt - 1);
|
cannam@503
|
38 int nExt = length + 2 * nFact;
|
c@225
|
39
|
c@417
|
40 double *filtScratchIn = new double[ nExt ];
|
c@417
|
41 double *filtScratchOut = new double[ nExt ];
|
cannam@483
|
42
|
cannam@503
|
43 for (i = 0; i < nExt; i++) {
|
cannam@483
|
44 filtScratchIn[ i ] = 0.0;
|
cannam@483
|
45 filtScratchOut[ i ] = 0.0;
|
c@225
|
46 }
|
c@225
|
47
|
c@225
|
48 // Edge transients reflection
|
c@225
|
49 double sample0 = 2 * src[ 0 ];
|
c@225
|
50 double sampleN = 2 * src[ length - 1 ];
|
c@225
|
51
|
cannam@503
|
52 int index = 0;
|
cannam@503
|
53 for (i = nFact; i > 0; i--) {
|
cannam@506
|
54 if (i < length) {
|
cannam@506
|
55 filtScratchIn[index] = sample0 - src[ i ];
|
cannam@506
|
56 }
|
cannam@506
|
57 ++index;
|
c@225
|
58 }
|
c@225
|
59 index = 0;
|
cannam@503
|
60 for (i = 0; i < nFact; i++) {
|
cannam@507
|
61 if (i + 1 < length) {
|
cannam@506
|
62 filtScratchIn[(nExt - nFact) + index] =
|
cannam@506
|
63 sampleN - src[ (length - 2) - i ];
|
cannam@506
|
64 }
|
cannam@506
|
65 ++index;
|
c@225
|
66 }
|
c@225
|
67
|
c@225
|
68 index = 0;
|
cannam@503
|
69 for (i = 0; i < length; i++) {
|
cannam@483
|
70 filtScratchIn[ i + nFact ] = src[ i ];
|
c@225
|
71 }
|
cannam@506
|
72
|
c@225
|
73 ////////////////////////////////
|
cannam@503
|
74 // Do 0Ph filtering
|
cannam@503
|
75 m_filter.process(filtScratchIn, filtScratchOut, nExt);
|
cannam@483
|
76
|
c@225
|
77 // reverse the series for FILTFILT
|
cannam@503
|
78 for (i = 0; i < nExt; i++) {
|
cannam@483
|
79 filtScratchIn[ i ] = filtScratchOut[ nExt - i - 1];
|
c@225
|
80 }
|
c@225
|
81
|
cannam@506
|
82 // clear filter state
|
cannam@506
|
83 m_filter.reset();
|
cannam@506
|
84
|
c@225
|
85 // do FILTER again
|
cannam@503
|
86 m_filter.process(filtScratchIn, filtScratchOut, nExt);
|
cannam@506
|
87
|
c@225
|
88 // reverse the series back
|
cannam@503
|
89 for (i = 0; i < nExt; i++) {
|
cannam@483
|
90 filtScratchIn[ i ] = filtScratchOut[ nExt - i - 1 ];
|
c@225
|
91 }
|
cannam@503
|
92 for (i = 0; i < nExt; i++) {
|
cannam@483
|
93 filtScratchOut[ i ] = filtScratchIn[ i ];
|
c@225
|
94 }
|
c@225
|
95
|
c@225
|
96 index = 0;
|
cannam@503
|
97 for (i = 0; i < length; i++) {
|
cannam@483
|
98 dst[ index++ ] = filtScratchOut[ i + nFact ];
|
cannam@483
|
99 }
|
c@225
|
100
|
c@417
|
101 delete [] filtScratchIn;
|
c@417
|
102 delete [] filtScratchOut;
|
c@225
|
103 }
|
c@225
|
104
|