annotate src/dsp/MathUtilities.cpp @ 196:da283326bcd3 tip master

Update plugin versions in RDF
author Chris Cannam <cannam@all-day-breakfast.com>
date Fri, 28 Feb 2020 09:43:02 +0000
parents b87290781071
children
rev   line source
c@119 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@119 2 /*
c@119 3 Constant-Q library
c@119 4 Copyright (c) 2013-2014 Queen Mary, University of London
c@119 5
c@119 6 Permission is hereby granted, free of charge, to any person
c@119 7 obtaining a copy of this software and associated documentation
c@119 8 files (the "Software"), to deal in the Software without
c@119 9 restriction, including without limitation the rights to use, copy,
c@119 10 modify, merge, publish, distribute, sublicense, and/or sell copies
c@119 11 of the Software, and to permit persons to whom the Software is
c@119 12 furnished to do so, subject to the following conditions:
c@119 13
c@119 14 The above copyright notice and this permission notice shall be
c@119 15 included in all copies or substantial portions of the Software.
c@119 16
c@119 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c@119 18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c@119 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c@119 20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
c@119 21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
c@119 22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
c@119 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
c@119 24
c@119 25 Except as contained in this notice, the names of the Centre for
c@119 26 Digital Music; Queen Mary, University of London; and Chris Cannam
c@119 27 shall not be used in advertising or otherwise to promote the sale,
c@119 28 use or other dealings in this Software without prior written
c@119 29 authorization.
c@119 30 */
c@119 31
c@119 32 #include "MathUtilities.h"
c@119 33
c@119 34 #include <iostream>
c@119 35 #include <algorithm>
c@119 36 #include <vector>
c@119 37 #include <cmath>
c@119 38
c@119 39
c@119 40 double MathUtilities::mod(double x, double y)
c@119 41 {
c@119 42 double a = floor( x / y );
c@119 43
c@119 44 double b = x - ( y * a );
c@119 45 return b;
c@119 46 }
c@119 47
c@119 48 double MathUtilities::princarg(double ang)
c@119 49 {
c@119 50 double ValOut;
c@119 51
c@119 52 ValOut = mod( ang + M_PI, -2 * M_PI ) + M_PI;
c@119 53
c@119 54 return ValOut;
c@119 55 }
c@119 56
c@119 57 void MathUtilities::getAlphaNorm(const double *data, unsigned int len, unsigned int alpha, double* ANorm)
c@119 58 {
c@119 59 unsigned int i;
c@119 60 double temp = 0.0;
c@119 61 double a=0.0;
c@119 62
c@119 63 for( i = 0; i < len; i++)
c@119 64 {
c@119 65 temp = data[ i ];
c@119 66
c@119 67 a += ::pow( fabs(temp), double(alpha) );
c@119 68 }
c@119 69 a /= ( double )len;
c@119 70 a = ::pow( a, ( 1.0 / (double) alpha ) );
c@119 71
c@119 72 *ANorm = a;
c@119 73 }
c@119 74
c@119 75 double MathUtilities::getAlphaNorm( const std::vector <double> &data, unsigned int alpha )
c@119 76 {
c@119 77 unsigned int i;
c@119 78 unsigned int len = data.size();
c@119 79 double temp = 0.0;
c@119 80 double a=0.0;
c@119 81
c@119 82 for( i = 0; i < len; i++)
c@119 83 {
c@119 84 temp = data[ i ];
c@119 85
c@119 86 a += ::pow( fabs(temp), double(alpha) );
c@119 87 }
c@119 88 a /= ( double )len;
c@119 89 a = ::pow( a, ( 1.0 / (double) alpha ) );
c@119 90
c@119 91 return a;
c@119 92 }
c@119 93
c@119 94 double MathUtilities::round(double x)
c@119 95 {
c@119 96 if (x < 0) {
c@119 97 return -floor(-x + 0.5);
c@119 98 } else {
c@119 99 return floor(x + 0.5);
c@119 100 }
c@119 101 }
c@119 102
c@119 103 double MathUtilities::median(const double *src, unsigned int len)
c@119 104 {
c@119 105 if (len == 0) return 0;
c@119 106
c@119 107 std::vector<double> scratch;
c@126 108 for (int i = 0; i < (int)len; ++i) scratch.push_back(src[i]);
c@119 109 std::sort(scratch.begin(), scratch.end());
c@119 110
c@119 111 int middle = len/2;
c@119 112 if (len % 2 == 0) {
c@119 113 return (scratch[middle] + scratch[middle - 1]) / 2;
c@119 114 } else {
c@119 115 return scratch[middle];
c@119 116 }
c@119 117 }
c@119 118
c@119 119 double MathUtilities::sum(const double *src, unsigned int len)
c@119 120 {
c@119 121 unsigned int i ;
c@119 122 double retVal =0.0;
c@119 123
c@119 124 for( i = 0; i < len; i++)
c@119 125 {
c@119 126 retVal += src[ i ];
c@119 127 }
c@119 128
c@119 129 return retVal;
c@119 130 }
c@119 131
c@119 132 double MathUtilities::mean(const double *src, unsigned int len)
c@119 133 {
c@119 134 double retVal =0.0;
c@119 135
c@119 136 if (len == 0) return 0;
c@119 137
c@119 138 double s = sum( src, len );
c@119 139
c@119 140 retVal = s / (double)len;
c@119 141
c@119 142 return retVal;
c@119 143 }
c@119 144
c@119 145 double MathUtilities::mean(const std::vector<double> &src,
c@119 146 unsigned int start,
c@119 147 unsigned int count)
c@119 148 {
c@119 149 double sum = 0.;
c@119 150
c@119 151 if (count == 0) return 0;
c@119 152
c@119 153 for (int i = 0; i < (int)count; ++i)
c@119 154 {
c@119 155 sum += src[start + i];
c@119 156 }
c@119 157
c@119 158 return sum / count;
c@119 159 }
c@119 160
c@119 161 void MathUtilities::getFrameMinMax(const double *data, unsigned int len, double *min, double *max)
c@119 162 {
c@119 163 unsigned int i;
c@119 164 double temp = 0.0;
c@119 165
c@119 166 if (len == 0) {
c@119 167 *min = *max = 0;
c@119 168 return;
c@119 169 }
c@119 170
c@119 171 *min = data[0];
c@119 172 *max = data[0];
c@119 173
c@119 174 for( i = 0; i < len; i++)
c@119 175 {
c@119 176 temp = data[ i ];
c@119 177
c@119 178 if( temp < *min )
c@119 179 {
c@119 180 *min = temp ;
c@119 181 }
c@119 182 if( temp > *max )
c@119 183 {
c@119 184 *max = temp ;
c@119 185 }
c@119 186
c@119 187 }
c@119 188 }
c@119 189
c@119 190 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
c@119 191 {
c@119 192 unsigned int index = 0;
c@119 193 unsigned int i;
c@119 194 double temp = 0.0;
c@119 195
c@119 196 double max = pData[0];
c@119 197
c@119 198 for( i = 0; i < Length; i++)
c@119 199 {
c@119 200 temp = pData[ i ];
c@119 201
c@119 202 if( temp > max )
c@119 203 {
c@119 204 max = temp ;
c@119 205 index = i;
c@119 206 }
c@119 207
c@119 208 }
c@119 209
c@119 210 if (pMax) *pMax = max;
c@119 211
c@119 212
c@119 213 return index;
c@119 214 }
c@119 215
c@119 216 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
c@119 217 {
c@119 218 unsigned int index = 0;
c@119 219 unsigned int i;
c@119 220 double temp = 0.0;
c@119 221
c@119 222 double max = data[0];
c@119 223
c@119 224 for( i = 0; i < data.size(); i++)
c@119 225 {
c@119 226 temp = data[ i ];
c@119 227
c@119 228 if( temp > max )
c@119 229 {
c@119 230 max = temp ;
c@119 231 index = i;
c@119 232 }
c@119 233
c@119 234 }
c@119 235
c@119 236 if (pMax) *pMax = max;
c@119 237
c@119 238
c@119 239 return index;
c@119 240 }
c@119 241
c@119 242 void MathUtilities::circShift( double* pData, int length, int shift)
c@119 243 {
c@119 244 shift = shift % length;
c@119 245 double temp;
c@119 246 int i,n;
c@119 247
c@119 248 for( i = 0; i < shift; i++)
c@119 249 {
c@119 250 temp=*(pData + length - 1);
c@119 251
c@119 252 for( n = length-2; n >= 0; n--)
c@119 253 {
c@119 254 *(pData+n+1)=*(pData+n);
c@119 255 }
c@119 256
c@119 257 *pData = temp;
c@119 258 }
c@119 259 }
c@119 260
c@119 261 int MathUtilities::compareInt (const void * a, const void * b)
c@119 262 {
c@119 263 return ( *(int*)a - *(int*)b );
c@119 264 }
c@119 265
c@119 266 void MathUtilities::normalise(double *data, int length, NormaliseType type)
c@119 267 {
c@119 268 switch (type) {
c@119 269
c@119 270 case NormaliseNone: return;
c@119 271
c@119 272 case NormaliseUnitSum:
c@119 273 {
c@119 274 double sum = 0.0;
c@119 275 for (int i = 0; i < length; ++i) {
c@119 276 sum += data[i];
c@119 277 }
c@119 278 if (sum != 0.0) {
c@119 279 for (int i = 0; i < length; ++i) {
c@119 280 data[i] /= sum;
c@119 281 }
c@119 282 }
c@119 283 }
c@119 284 break;
c@119 285
c@119 286 case NormaliseUnitMax:
c@119 287 {
c@119 288 double max = 0.0;
c@119 289 for (int i = 0; i < length; ++i) {
c@119 290 if (fabs(data[i]) > max) {
c@119 291 max = fabs(data[i]);
c@119 292 }
c@119 293 }
c@119 294 if (max != 0.0) {
c@119 295 for (int i = 0; i < length; ++i) {
c@119 296 data[i] /= max;
c@119 297 }
c@119 298 }
c@119 299 }
c@119 300 break;
c@119 301
c@119 302 }
c@119 303 }
c@119 304
c@119 305 void MathUtilities::normalise(std::vector<double> &data, NormaliseType type)
c@119 306 {
c@119 307 switch (type) {
c@119 308
c@119 309 case NormaliseNone: return;
c@119 310
c@119 311 case NormaliseUnitSum:
c@119 312 {
c@119 313 double sum = 0.0;
c@119 314 for (int i = 0; i < (int)data.size(); ++i) sum += data[i];
c@119 315 if (sum != 0.0) {
c@119 316 for (int i = 0; i < (int)data.size(); ++i) data[i] /= sum;
c@119 317 }
c@119 318 }
c@119 319 break;
c@119 320
c@119 321 case NormaliseUnitMax:
c@119 322 {
c@119 323 double max = 0.0;
c@119 324 for (int i = 0; i < (int)data.size(); ++i) {
c@119 325 if (fabs(data[i]) > max) max = fabs(data[i]);
c@119 326 }
c@119 327 if (max != 0.0) {
c@119 328 for (int i = 0; i < (int)data.size(); ++i) data[i] /= max;
c@119 329 }
c@119 330 }
c@119 331 break;
c@119 332
c@119 333 }
c@119 334 }
c@119 335
c@119 336 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
c@119 337 {
c@119 338 int sz = int(data.size());
c@119 339 if (sz == 0) return;
c@119 340
c@119 341 std::vector<double> smoothed(sz);
c@119 342
c@119 343 int p_pre = 8;
c@119 344 int p_post = 7;
c@119 345
c@119 346 for (int i = 0; i < sz; ++i) {
c@119 347
c@119 348 int first = std::max(0, i - p_pre);
c@119 349 int last = std::min(sz - 1, i + p_post);
c@119 350
c@119 351 smoothed[i] = mean(data, first, last - first + 1);
c@119 352 }
c@119 353
c@119 354 for (int i = 0; i < sz; i++) {
c@119 355 data[i] -= smoothed[i];
c@119 356 if (data[i] < 0.0) data[i] = 0.0;
c@119 357 }
c@119 358 }
c@119 359
c@119 360 bool
c@119 361 MathUtilities::isPowerOfTwo(int x)
c@119 362 {
c@119 363 if (x < 1) return false;
c@119 364 if (x & (x-1)) return false;
c@119 365 return true;
c@119 366 }
c@119 367
c@119 368 int
c@119 369 MathUtilities::nextPowerOfTwo(int x)
c@119 370 {
c@119 371 if (isPowerOfTwo(x)) return x;
c@119 372 if (x < 1) return 1;
c@119 373 int n = 1;
c@119 374 while (x) { x >>= 1; n <<= 1; }
c@119 375 return n;
c@119 376 }
c@119 377
c@119 378 int
c@119 379 MathUtilities::previousPowerOfTwo(int x)
c@119 380 {
c@119 381 if (isPowerOfTwo(x)) return x;
c@119 382 if (x < 1) return 1;
c@119 383 int n = 1;
c@119 384 x >>= 1;
c@119 385 while (x) { x >>= 1; n <<= 1; }
c@119 386 return n;
c@119 387 }
c@119 388
c@119 389 int
c@119 390 MathUtilities::nearestPowerOfTwo(int x)
c@119 391 {
c@119 392 if (isPowerOfTwo(x)) return x;
c@119 393 int n0 = previousPowerOfTwo(x), n1 = nextPowerOfTwo(x);
c@119 394 if (x - n0 < n1 - x) return n0;
c@119 395 else return n1;
c@119 396 }
c@119 397
c@119 398 double
c@119 399 MathUtilities::factorial(int x)
c@119 400 {
c@119 401 if (x < 0) return 0;
c@119 402 double f = 1;
c@119 403 for (int i = 1; i <= x; ++i) {
c@119 404 f = f * i;
c@119 405 }
c@119 406 return f;
c@119 407 }
c@119 408
c@119 409 int
c@119 410 MathUtilities::gcd(int a, int b)
c@119 411 {
c@119 412 int c = a % b;
c@119 413 if (c == 0) {
c@119 414 return b;
c@119 415 } else {
c@119 416 return gcd(b, c);
c@119 417 }
c@119 418 }
c@119 419