c@241
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@241
|
2
|
c@241
|
3 /*
|
c@241
|
4 QM DSP Library
|
c@241
|
5
|
c@241
|
6 Centre for Digital Music, Queen Mary, University of London.
|
c@241
|
7 This file copyright 2005-2006 Christian Landone.
|
c@241
|
8 All rights reserved.
|
c@241
|
9 */
|
c@241
|
10
|
c@241
|
11 #include "MathUtilities.h"
|
c@241
|
12
|
c@241
|
13 #include <iostream>
|
c@241
|
14 #include <cmath>
|
c@241
|
15
|
c@241
|
16
|
c@241
|
17 double MathUtilities::mod(double x, double y)
|
c@241
|
18 {
|
c@241
|
19 double a = floor( x / y );
|
c@241
|
20
|
c@241
|
21 double b = x - ( y * a );
|
c@241
|
22 return b;
|
c@241
|
23 }
|
c@241
|
24
|
c@241
|
25 double MathUtilities::princarg(double ang)
|
c@241
|
26 {
|
c@241
|
27 double ValOut;
|
c@241
|
28
|
c@241
|
29 ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
|
c@241
|
30
|
c@241
|
31 return ValOut;
|
c@241
|
32 }
|
c@241
|
33
|
c@241
|
34 void MathUtilities::getAlphaNorm(const double *data, unsigned int len, unsigned int alpha, double* ANorm)
|
c@241
|
35 {
|
c@241
|
36 unsigned int i;
|
c@241
|
37 double temp = 0.0;
|
c@241
|
38 double a=0.0;
|
c@241
|
39
|
c@241
|
40 for( i = 0; i < len; i++)
|
c@241
|
41 {
|
c@241
|
42 temp = data[ i ];
|
c@241
|
43
|
c@241
|
44 a += ::pow( fabs(temp), alpha );
|
c@241
|
45 }
|
c@241
|
46 a /= ( double )len;
|
c@241
|
47 a = ::pow( a, ( 1.0 / (double) alpha ) );
|
c@241
|
48
|
c@241
|
49 *ANorm = a;
|
c@241
|
50 }
|
c@241
|
51
|
c@241
|
52 double MathUtilities::getAlphaNorm( const std::vector <double> &data, unsigned int alpha )
|
c@241
|
53 {
|
c@241
|
54 unsigned int i;
|
c@241
|
55 unsigned int len = data.size();
|
c@241
|
56 double temp = 0.0;
|
c@241
|
57 double a=0.0;
|
c@241
|
58
|
c@241
|
59 for( i = 0; i < len; i++)
|
c@241
|
60 {
|
c@241
|
61 temp = data[ i ];
|
c@241
|
62
|
c@241
|
63 a += ::pow( fabs(temp), alpha );
|
c@241
|
64 }
|
c@241
|
65 a /= ( double )len;
|
c@241
|
66 a = ::pow( a, ( 1.0 / (double) alpha ) );
|
c@241
|
67
|
c@241
|
68 return a;
|
c@241
|
69 }
|
c@241
|
70
|
c@241
|
71 double MathUtilities::round(double x)
|
c@241
|
72 {
|
c@241
|
73 double val = (double)floor(x + 0.5);
|
c@241
|
74
|
c@241
|
75 return val;
|
c@241
|
76 }
|
c@241
|
77
|
c@241
|
78 double MathUtilities::median(const double *src, unsigned int len)
|
c@241
|
79 {
|
c@241
|
80 unsigned int i, j;
|
c@241
|
81 double tmp = 0.0;
|
c@241
|
82 double tempMedian;
|
c@241
|
83 double medianVal;
|
c@241
|
84
|
c@241
|
85 double* scratch = new double[ len ];//Vector < double > sortedX = Vector < double > ( size );
|
c@241
|
86
|
c@241
|
87 for ( i = 0; i < len; i++ )
|
c@241
|
88 {
|
c@241
|
89 scratch[i] = src[i];
|
c@241
|
90 }
|
c@241
|
91
|
c@241
|
92 for ( i = 0; i < len - 1; i++ )
|
c@241
|
93 {
|
c@241
|
94 for ( j = 0; j < len - 1 - i; j++ )
|
c@241
|
95 {
|
c@241
|
96 if ( scratch[j + 1] < scratch[j] )
|
c@241
|
97 {
|
c@241
|
98 // compare the two neighbors
|
c@241
|
99 tmp = scratch[j]; // swap a[j] and a[j+1]
|
c@241
|
100 scratch[j] = scratch[j + 1];
|
c@241
|
101 scratch[j + 1] = tmp;
|
c@241
|
102 }
|
c@241
|
103 }
|
c@241
|
104 }
|
c@241
|
105 int middle;
|
c@241
|
106 if ( len % 2 == 0 )
|
c@241
|
107 {
|
c@241
|
108 middle = len / 2;
|
c@241
|
109 tempMedian = ( scratch[middle] + scratch[middle - 1] ) / 2;
|
c@241
|
110 }
|
c@241
|
111 else
|
c@241
|
112 {
|
c@241
|
113 middle = ( int )floor( len / 2.0 );
|
c@241
|
114 tempMedian = scratch[middle];
|
c@241
|
115 }
|
c@241
|
116
|
c@241
|
117 medianVal = tempMedian;
|
c@241
|
118
|
c@241
|
119 delete [] scratch;
|
c@241
|
120 return medianVal;
|
c@241
|
121 }
|
c@241
|
122
|
c@241
|
123 double MathUtilities::sum(const double *src, unsigned int len)
|
c@241
|
124 {
|
c@241
|
125 unsigned int i ;
|
c@241
|
126 double retVal =0.0;
|
c@241
|
127
|
c@241
|
128 for( i = 0; i < len; i++)
|
c@241
|
129 {
|
c@241
|
130 retVal += src[ i ];
|
c@241
|
131 }
|
c@241
|
132
|
c@241
|
133 return retVal;
|
c@241
|
134 }
|
c@241
|
135
|
c@241
|
136 double MathUtilities::mean(const double *src, unsigned int len)
|
c@241
|
137 {
|
c@241
|
138 double retVal =0.0;
|
c@241
|
139
|
c@241
|
140 double s = sum( src, len );
|
c@241
|
141
|
c@241
|
142 retVal = s / (double)len;
|
c@241
|
143
|
c@241
|
144 return retVal;
|
c@241
|
145 }
|
c@241
|
146
|
c@279
|
147 double MathUtilities::mean(const std::vector<double> &src,
|
c@279
|
148 unsigned int start,
|
c@279
|
149 unsigned int count)
|
c@279
|
150 {
|
c@279
|
151 double sum = 0.;
|
c@279
|
152
|
c@279
|
153 for (int i = 0; i < count; ++i)
|
c@279
|
154 {
|
c@279
|
155 sum += src[start + i];
|
c@279
|
156 }
|
c@279
|
157
|
c@279
|
158 return sum / count;
|
c@279
|
159 }
|
c@279
|
160
|
c@241
|
161 void MathUtilities::getFrameMinMax(const double *data, unsigned int len, double *min, double *max)
|
c@241
|
162 {
|
c@241
|
163 unsigned int i;
|
c@241
|
164 double temp = 0.0;
|
c@241
|
165 double a=0.0;
|
c@241
|
166
|
c@241
|
167 *min = data[0];
|
c@241
|
168 *max = data[0];
|
c@241
|
169
|
c@241
|
170 for( i = 0; i < len; i++)
|
c@241
|
171 {
|
c@241
|
172 temp = data[ i ];
|
c@241
|
173
|
c@241
|
174 if( temp < *min )
|
c@241
|
175 {
|
c@241
|
176 *min = temp ;
|
c@241
|
177 }
|
c@241
|
178 if( temp > *max )
|
c@241
|
179 {
|
c@241
|
180 *max = temp ;
|
c@241
|
181 }
|
c@241
|
182
|
c@241
|
183 }
|
c@241
|
184 }
|
c@241
|
185
|
c@241
|
186 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
|
c@241
|
187 {
|
c@241
|
188 unsigned int index = 0;
|
c@241
|
189 unsigned int i;
|
c@241
|
190 double temp = 0.0;
|
c@241
|
191
|
c@241
|
192 double max = pData[0];
|
c@241
|
193
|
c@241
|
194 for( i = 0; i < Length; i++)
|
c@241
|
195 {
|
c@241
|
196 temp = pData[ i ];
|
c@241
|
197
|
c@241
|
198 if( temp > max )
|
c@241
|
199 {
|
c@241
|
200 max = temp ;
|
c@241
|
201 index = i;
|
c@241
|
202 }
|
c@241
|
203
|
c@241
|
204 }
|
c@241
|
205
|
c@279
|
206 if (pMax) *pMax = max;
|
c@279
|
207
|
c@279
|
208
|
c@279
|
209 return index;
|
c@279
|
210 }
|
c@279
|
211
|
c@279
|
212 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
|
c@279
|
213 {
|
c@279
|
214 unsigned int index = 0;
|
c@279
|
215 unsigned int i;
|
c@279
|
216 double temp = 0.0;
|
c@279
|
217
|
c@279
|
218 double max = data[0];
|
c@279
|
219
|
c@279
|
220 for( i = 0; i < data.size(); i++)
|
c@279
|
221 {
|
c@279
|
222 temp = data[ i ];
|
c@279
|
223
|
c@279
|
224 if( temp > max )
|
c@279
|
225 {
|
c@279
|
226 max = temp ;
|
c@279
|
227 index = i;
|
c@279
|
228 }
|
c@279
|
229
|
c@279
|
230 }
|
c@279
|
231
|
c@279
|
232 if (pMax) *pMax = max;
|
c@241
|
233
|
c@241
|
234
|
c@241
|
235 return index;
|
c@241
|
236 }
|
c@241
|
237
|
c@241
|
238 void MathUtilities::circShift( double* pData, int length, int shift)
|
c@241
|
239 {
|
c@241
|
240 shift = shift % length;
|
c@241
|
241 double temp;
|
c@241
|
242 int i,n;
|
c@241
|
243
|
c@241
|
244 for( i = 0; i < shift; i++)
|
c@241
|
245 {
|
c@241
|
246 temp=*(pData + length - 1);
|
c@241
|
247
|
c@241
|
248 for( n = length-2; n >= 0; n--)
|
c@241
|
249 {
|
c@241
|
250 *(pData+n+1)=*(pData+n);
|
c@241
|
251 }
|
c@241
|
252
|
c@241
|
253 *pData = temp;
|
c@241
|
254 }
|
c@241
|
255 }
|
c@241
|
256
|
c@241
|
257 int MathUtilities::compareInt (const void * a, const void * b)
|
c@241
|
258 {
|
c@241
|
259 return ( *(int*)a - *(int*)b );
|
c@241
|
260 }
|
c@241
|
261
|
c@259
|
262 void MathUtilities::normalise(double *data, int length, NormaliseType type)
|
c@259
|
263 {
|
c@259
|
264 switch (type) {
|
c@259
|
265
|
c@259
|
266 case NormaliseNone: return;
|
c@259
|
267
|
c@259
|
268 case NormaliseUnitSum:
|
c@259
|
269 {
|
c@259
|
270 double sum = 0.0;
|
c@259
|
271 for (int i = 0; i < length; ++i) {
|
c@259
|
272 sum += data[i];
|
c@259
|
273 }
|
c@259
|
274 if (sum != 0.0) {
|
c@259
|
275 for (int i = 0; i < length; ++i) {
|
c@259
|
276 data[i] /= sum;
|
c@259
|
277 }
|
c@259
|
278 }
|
c@259
|
279 }
|
c@259
|
280 break;
|
c@259
|
281
|
c@259
|
282 case NormaliseUnitMax:
|
c@259
|
283 {
|
c@259
|
284 double max = 0.0;
|
c@259
|
285 for (int i = 0; i < length; ++i) {
|
c@259
|
286 if (fabs(data[i]) > max) {
|
c@259
|
287 max = fabs(data[i]);
|
c@259
|
288 }
|
c@259
|
289 }
|
c@259
|
290 if (max != 0.0) {
|
c@259
|
291 for (int i = 0; i < length; ++i) {
|
c@259
|
292 data[i] /= max;
|
c@259
|
293 }
|
c@259
|
294 }
|
c@259
|
295 }
|
c@259
|
296 break;
|
c@259
|
297
|
c@259
|
298 }
|
c@259
|
299 }
|
c@259
|
300
|
c@259
|
301 void MathUtilities::normalise(std::vector<double> &data, NormaliseType type)
|
c@259
|
302 {
|
c@259
|
303 switch (type) {
|
c@259
|
304
|
c@259
|
305 case NormaliseNone: return;
|
c@259
|
306
|
c@259
|
307 case NormaliseUnitSum:
|
c@259
|
308 {
|
c@259
|
309 double sum = 0.0;
|
c@259
|
310 for (int i = 0; i < data.size(); ++i) sum += data[i];
|
c@259
|
311 if (sum != 0.0) {
|
c@259
|
312 for (int i = 0; i < data.size(); ++i) data[i] /= sum;
|
c@259
|
313 }
|
c@259
|
314 }
|
c@259
|
315 break;
|
c@259
|
316
|
c@259
|
317 case NormaliseUnitMax:
|
c@259
|
318 {
|
c@259
|
319 double max = 0.0;
|
c@259
|
320 for (int i = 0; i < data.size(); ++i) {
|
c@259
|
321 if (fabs(data[i]) > max) max = fabs(data[i]);
|
c@259
|
322 }
|
c@259
|
323 if (max != 0.0) {
|
c@259
|
324 for (int i = 0; i < data.size(); ++i) data[i] /= max;
|
c@259
|
325 }
|
c@259
|
326 }
|
c@259
|
327 break;
|
c@259
|
328
|
c@259
|
329 }
|
c@259
|
330 }
|
c@259
|
331
|
c@279
|
332 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
|
c@279
|
333 {
|
c@279
|
334 int sz = int(data.size());
|
c@279
|
335 if (sz == 0) return;
|
c@279
|
336
|
c@279
|
337 std::vector<double> smoothed(sz);
|
c@279
|
338
|
c@279
|
339 int p_pre = 8;
|
c@279
|
340 int p_post = 7;
|
c@279
|
341
|
c@279
|
342 for (int i = 0; i < sz; ++i) {
|
c@279
|
343
|
c@279
|
344 int first = std::max(0, i - p_pre);
|
c@279
|
345 int last = std::min(sz - 1, i + p_post);
|
c@279
|
346
|
c@279
|
347 smoothed[i] = mean(data, first, last - first + 1);
|
c@279
|
348 }
|
c@279
|
349
|
c@279
|
350 for (int i = 0; i < sz; i++) {
|
c@279
|
351 data[i] -= smoothed[i];
|
c@279
|
352 if (data[i] < 0.0) data[i] = 0.0;
|
c@279
|
353 }
|
c@279
|
354 }
|
c@259
|
355
|
c@259
|
356
|