annotate maths/MathUtilities.cpp @ 298:255e431ae3d4

* Key detector: when returning key strengths, use the peak value of the three underlying chromagram correlations (from 36-bin chromagram) corresponding to each key, instead of the mean. Rationale: This is the same method as used when returning the key value, and it's nice to have the same results in both returned value and plot. The peak performed better than the sum with a simple test set of triads, so it seems reasonable to change the plot to match the key output rather than the other way around. * FFT: kiss_fftr returns only the non-conjugate bins, synthesise the rest rather than leaving them (perhaps dangerously) undefined. Fixes an uninitialised data error in chromagram that could cause garbage results from key detector. * Constant Q: remove precalculated values again, I reckon they're not proving such a good tradeoff.
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 05 Jun 2009 15:12:39 +0000
parents 5e125f030287
children 702ff8c08137
rev   line source
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@283 166
c@283 167 if (len == 0) {
c@283 168 *min = *max = 0;
c@283 169 return;
c@283 170 }
c@241 171
c@241 172 *min = data[0];
c@241 173 *max = data[0];
c@241 174
c@241 175 for( i = 0; i < len; i++)
c@241 176 {
c@241 177 temp = data[ i ];
c@241 178
c@241 179 if( temp < *min )
c@241 180 {
c@241 181 *min = temp ;
c@241 182 }
c@241 183 if( temp > *max )
c@241 184 {
c@241 185 *max = temp ;
c@241 186 }
c@241 187
c@241 188 }
c@241 189 }
c@241 190
c@241 191 int MathUtilities::getMax( double* pData, unsigned int Length, double* pMax )
c@241 192 {
c@241 193 unsigned int index = 0;
c@241 194 unsigned int i;
c@241 195 double temp = 0.0;
c@241 196
c@241 197 double max = pData[0];
c@241 198
c@241 199 for( i = 0; i < Length; i++)
c@241 200 {
c@241 201 temp = pData[ i ];
c@241 202
c@241 203 if( temp > max )
c@241 204 {
c@241 205 max = temp ;
c@241 206 index = i;
c@241 207 }
c@241 208
c@241 209 }
c@241 210
c@279 211 if (pMax) *pMax = max;
c@279 212
c@279 213
c@279 214 return index;
c@279 215 }
c@279 216
c@279 217 int MathUtilities::getMax( const std::vector<double> & data, double* pMax )
c@279 218 {
c@279 219 unsigned int index = 0;
c@279 220 unsigned int i;
c@279 221 double temp = 0.0;
c@279 222
c@279 223 double max = data[0];
c@279 224
c@279 225 for( i = 0; i < data.size(); i++)
c@279 226 {
c@279 227 temp = data[ i ];
c@279 228
c@279 229 if( temp > max )
c@279 230 {
c@279 231 max = temp ;
c@279 232 index = i;
c@279 233 }
c@279 234
c@279 235 }
c@279 236
c@279 237 if (pMax) *pMax = max;
c@241 238
c@241 239
c@241 240 return index;
c@241 241 }
c@241 242
c@241 243 void MathUtilities::circShift( double* pData, int length, int shift)
c@241 244 {
c@241 245 shift = shift % length;
c@241 246 double temp;
c@241 247 int i,n;
c@241 248
c@241 249 for( i = 0; i < shift; i++)
c@241 250 {
c@241 251 temp=*(pData + length - 1);
c@241 252
c@241 253 for( n = length-2; n >= 0; n--)
c@241 254 {
c@241 255 *(pData+n+1)=*(pData+n);
c@241 256 }
c@241 257
c@241 258 *pData = temp;
c@241 259 }
c@241 260 }
c@241 261
c@241 262 int MathUtilities::compareInt (const void * a, const void * b)
c@241 263 {
c@241 264 return ( *(int*)a - *(int*)b );
c@241 265 }
c@241 266
c@259 267 void MathUtilities::normalise(double *data, int length, NormaliseType type)
c@259 268 {
c@259 269 switch (type) {
c@259 270
c@259 271 case NormaliseNone: return;
c@259 272
c@259 273 case NormaliseUnitSum:
c@259 274 {
c@259 275 double sum = 0.0;
c@259 276 for (int i = 0; i < length; ++i) {
c@259 277 sum += data[i];
c@259 278 }
c@259 279 if (sum != 0.0) {
c@259 280 for (int i = 0; i < length; ++i) {
c@259 281 data[i] /= sum;
c@259 282 }
c@259 283 }
c@259 284 }
c@259 285 break;
c@259 286
c@259 287 case NormaliseUnitMax:
c@259 288 {
c@259 289 double max = 0.0;
c@259 290 for (int i = 0; i < length; ++i) {
c@259 291 if (fabs(data[i]) > max) {
c@259 292 max = fabs(data[i]);
c@259 293 }
c@259 294 }
c@259 295 if (max != 0.0) {
c@259 296 for (int i = 0; i < length; ++i) {
c@259 297 data[i] /= max;
c@259 298 }
c@259 299 }
c@259 300 }
c@259 301 break;
c@259 302
c@259 303 }
c@259 304 }
c@259 305
c@259 306 void MathUtilities::normalise(std::vector<double> &data, NormaliseType type)
c@259 307 {
c@259 308 switch (type) {
c@259 309
c@259 310 case NormaliseNone: return;
c@259 311
c@259 312 case NormaliseUnitSum:
c@259 313 {
c@259 314 double sum = 0.0;
c@259 315 for (int i = 0; i < data.size(); ++i) sum += data[i];
c@259 316 if (sum != 0.0) {
c@259 317 for (int i = 0; i < data.size(); ++i) data[i] /= sum;
c@259 318 }
c@259 319 }
c@259 320 break;
c@259 321
c@259 322 case NormaliseUnitMax:
c@259 323 {
c@259 324 double max = 0.0;
c@259 325 for (int i = 0; i < data.size(); ++i) {
c@259 326 if (fabs(data[i]) > max) max = fabs(data[i]);
c@259 327 }
c@259 328 if (max != 0.0) {
c@259 329 for (int i = 0; i < data.size(); ++i) data[i] /= max;
c@259 330 }
c@259 331 }
c@259 332 break;
c@259 333
c@259 334 }
c@259 335 }
c@259 336
c@279 337 void MathUtilities::adaptiveThreshold(std::vector<double> &data)
c@279 338 {
c@279 339 int sz = int(data.size());
c@279 340 if (sz == 0) return;
c@279 341
c@279 342 std::vector<double> smoothed(sz);
c@279 343
c@279 344 int p_pre = 8;
c@279 345 int p_post = 7;
c@279 346
c@279 347 for (int i = 0; i < sz; ++i) {
c@279 348
c@279 349 int first = std::max(0, i - p_pre);
c@279 350 int last = std::min(sz - 1, i + p_post);
c@279 351
c@279 352 smoothed[i] = mean(data, first, last - first + 1);
c@279 353 }
c@279 354
c@279 355 for (int i = 0; i < sz; i++) {
c@279 356 data[i] -= smoothed[i];
c@279 357 if (data[i] < 0.0) data[i] = 0.0;
c@279 358 }
c@279 359 }
c@259 360
c@280 361 bool
c@280 362 MathUtilities::isPowerOfTwo(int x)
c@280 363 {
c@280 364 if (x < 2) return false;
c@280 365 if (x & (x-1)) return false;
c@280 366 return true;
c@280 367 }
c@280 368
c@280 369 int
c@280 370 MathUtilities::nextPowerOfTwo(int x)
c@280 371 {
c@280 372 if (isPowerOfTwo(x)) return x;
c@280 373 int n = 1;
c@280 374 while (x) { x >>= 1; n <<= 1; }
c@280 375 return n;
c@280 376 }
c@280 377
c@280 378 int
c@280 379 MathUtilities::previousPowerOfTwo(int x)
c@280 380 {
c@280 381 if (isPowerOfTwo(x)) return x;
c@280 382 int n = 1;
c@280 383 x >>= 1;
c@280 384 while (x) { x >>= 1; n <<= 1; }
c@280 385 return n;
c@280 386 }
c@280 387
c@280 388 int
c@280 389 MathUtilities::nearestPowerOfTwo(int x)
c@280 390 {
c@280 391 if (isPowerOfTwo(x)) return x;
c@280 392 int n0 = previousPowerOfTwo(x), n1 = nearestPowerOfTwo(x);
c@280 393 if (x - n0 < n1 - x) return n0;
c@280 394 else return n1;
c@280 395 }
c@280 396