52443fb384bcc4c3b24a1348130945e4959790c3
[ardour.git] / libs / qm-dsp / dsp / signalconditioning / DFProcess.cpp
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
3 /*
4     QM DSP Library
5
6     Centre for Digital Music, Queen Mary, University of London.
7     This file 2005-2006 Christian Landone.
8
9     Modifications:
10
11     - delta threshold
12     Description: add delta threshold used as offset in the smoothed
13     detection function
14     Author: Mathieu Barthet
15     Date: June 2010
16
17     This program is free software; you can redistribute it and/or
18     modify it under the terms of the GNU General Public License as
19     published by the Free Software Foundation; either version 2 of the
20     License, or (at your option) any later version.  See the file
21     COPYING included with this distribution for more information.
22 */
23
24 #include "DFProcess.h"
25 #include "maths/MathUtilities.h"
26
27 #include <cstring>
28
29 //////////////////////////////////////////////////////////////////////
30 // Construction/Destruction
31 //////////////////////////////////////////////////////////////////////
32
33 DFProcess::DFProcess( DFProcConfig Config )
34 {
35     filtSrc = NULL;
36     filtDst = NULL;     
37     m_filtScratchIn = NULL;
38     m_filtScratchOut = NULL;
39
40     m_FFOrd = 0;
41
42     initialise( Config );
43 }
44
45 DFProcess::~DFProcess()
46 {
47     deInitialise();
48 }
49
50 void DFProcess::initialise( DFProcConfig Config )
51 {
52     m_length = Config.length;
53     m_winPre = Config.winPre;
54     m_winPost = Config.winPost;
55     m_alphaNormParam = Config.AlphaNormParam;
56
57     m_isMedianPositive = Config.isMedianPositive;
58
59     filtSrc = new double[ m_length ];
60     filtDst = new double[ m_length ];
61
62         
63     //Low Pass Smoothing Filter Config
64     m_FilterConfigParams.ord = Config.LPOrd;
65     m_FilterConfigParams.ACoeffs = Config.LPACoeffs;
66     m_FilterConfigParams.BCoeffs = Config.LPBCoeffs;
67         
68     m_FiltFilt = new FiltFilt( m_FilterConfigParams );
69         
70     //add delta threshold
71     m_delta = Config.delta;
72 }
73
74 void DFProcess::deInitialise()
75 {
76     delete [] filtSrc;
77
78     delete [] filtDst;
79
80     delete [] m_filtScratchIn;
81
82     delete [] m_filtScratchOut;
83
84     delete m_FiltFilt;
85 }
86
87 void DFProcess::process(double *src, double* dst)
88 {
89     if (m_length == 0) return;
90
91     removeDCNormalize( src, filtSrc );
92
93     m_FiltFilt->process( filtSrc, filtDst, m_length );
94
95     medianFilter( filtDst, dst );
96 }
97
98
99 void DFProcess::medianFilter(double *src, double *dst)
100 {
101     int i,k,j,l;
102     int index = 0;
103
104     double val = 0;
105
106     double* y = new double[ m_winPost + m_winPre + 1];
107     memset( y, 0, sizeof( double ) * ( m_winPost + m_winPre + 1) );
108
109     double* scratch = new double[ m_length ];
110
111     for( i = 0; i < m_winPre; i++)
112     {
113         if (index >= m_length) break;
114
115         k = i + m_winPost + 1;
116
117         for( j = 0; j < k; j++)
118         {
119             y[ j ] = src[ j ];
120         }
121         scratch[ index ] = MathUtilities::median( y, k );
122         index++;
123     }
124
125     for(  i = 0; i + m_winPost + m_winPre < m_length; i ++)
126     {
127         if (index >= m_length) break;
128
129                          
130         l = 0;
131         for(  j  = i; j < ( i + m_winPost + m_winPre + 1); j++)
132         {
133             y[ l ] = src[ j ];
134             l++;
135         }
136
137         scratch[ index++ ] = MathUtilities::median( y, (m_winPost + m_winPre + 1 ));
138     }
139
140     for( i = std::max( m_length - m_winPost, 1); i < m_length; i++)
141     {
142         if (index >= m_length) break;
143
144         k = std::max( i - m_winPre, 1);
145
146         l = 0;
147         for( j = k; j < m_length; j++)
148         {
149             y[ l ] = src[ j ];
150
151             l++;
152         }
153                 
154         scratch[ index++ ] = MathUtilities::median( y, l); 
155     }
156
157
158     for( i = 0; i < m_length; i++ )
159     {
160         //add a delta threshold used as an offset when computing the smoothed detection function
161         //(helps to discard noise when detecting peaks) 
162         val = src[ i ] - scratch[ i ] - m_delta;
163                 
164         if( m_isMedianPositive )
165         {
166             if( val > 0 )
167             {
168                 dst[ i ]  = val;
169             }
170             else
171             {
172                 dst[ i ]  = 0;
173             }
174         }
175         else
176         {
177             dst[ i ]  = val;
178         }
179     }
180         
181     delete [] y;
182     delete [] scratch;
183 }
184
185
186 void DFProcess::removeDCNormalize( double *src, double*dst )
187 {
188     double DFmax = 0;
189     double DFMin = 0;
190     double DFAlphaNorm = 0;
191
192     MathUtilities::getFrameMinMax( src, m_length, &DFMin, &DFmax );
193
194     MathUtilities::getAlphaNorm( src, m_length, m_alphaNormParam, &DFAlphaNorm );
195
196     for( unsigned int i = 0; i< m_length; i++)
197     {
198         dst[ i ] = ( src[ i ] - DFMin ) / DFAlphaNorm; 
199     }
200 }