annotate maths/MathUtilities.cpp @ 96:88f3cfcff55f

A threshold (delta) is added in the peak picking parameters structure (PPickParams). It is used as an offset when computing the smoothed detection function. A constructor for the structure PPickParams is also added to set the parameters to 0 when a structure instance is created. Hence programmes using the peak picking parameter structure and which do not set the delta parameter (e.g. QM Vamp note onset detector) won't be affected by the modifications. Functions modified: - dsp/onsets/PeakPicking.cpp - dsp/onsets/PeakPicking.h - dsp/signalconditioning/DFProcess.cpp - dsp/signalconditioning/DFProcess.h
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Mon, 20 Jun 2011 19:01:48 +0100
parents e5907ae6de17
children 37449f085a4c
rev   line source
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