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