annotate maths/MathUtilities.cpp @ 54:5bec06ecc88a

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