annotate src/OnsetDetectionFunction.cpp @ 27:98f7a54faa0c develop

Changed all pointers to arrays in OnsetDetectionFunction into vectors
author Adam <adamstark.uk@gmail.com>
date Tue, 28 Jan 2014 00:19:21 +0000
parents a8e3e95d14e4
children bddd59087c36
rev   line source
adamstark@5 1 //=======================================================================
adamstark@5 2 /** @file OnsetDetectionFunction.cpp
adamstark@5 3 * @brief A class for calculating onset detection functions
adamstark@5 4 * @author Adam Stark
adamstark@5 5 * @copyright Copyright (C) 2008-2014 Queen Mary University of London
adamstark@5 6 *
adamstark@5 7 * This program is free software: you can redistribute it and/or modify
adamstark@5 8 * it under the terms of the GNU General Public License as published by
adamstark@5 9 * the Free Software Foundation, either version 3 of the License, or
adamstark@5 10 * (at your option) any later version.
adamstark@5 11 *
adamstark@5 12 * This program is distributed in the hope that it will be useful,
adamstark@5 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
adamstark@5 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
adamstark@5 15 * GNU General Public License for more details.
adamstark@5 16 *
adamstark@5 17 * You should have received a copy of the GNU General Public License
adamstark@5 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
adamstark@5 19 */
adamstark@5 20 //=======================================================================
adamstark@5 21
adamstark@5 22 #include <math.h>
adamstark@5 23 #include "OnsetDetectionFunction.h"
adamstark@5 24
adamstark@15 25 //=======================================================================
adamstark@22 26 OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType)
adamstark@5 27 {
adamstark@5 28 // indicate that we have not initialised yet
adamstark@27 29 initialised = false;
adamstark@5 30
adamstark@5 31 // set pi
adamstark@5 32 pi = 3.14159265358979;
adamstark@5 33
adamstark@5 34 // initialise with arguments to constructor
adamstark@22 35 initialise(hopSize_,frameSize_,onsetDetectionFunctionType_,windowType);
adamstark@5 36 }
adamstark@5 37
adamstark@5 38
adamstark@15 39 //=======================================================================
adamstark@22 40 OnsetDetectionFunction::~OnsetDetectionFunction()
adamstark@5 41 {
adamstark@27 42 if (initialised)
adamstark@27 43 {
adamstark@27 44 // destroy fft plan
adamstark@27 45 fftw_destroy_plan(p);
adamstark@27 46 fftw_free(complexIn);
adamstark@27 47 fftw_free(complexOut);
adamstark@27 48 }
adamstark@5 49 }
adamstark@5 50
adamstark@15 51 //=======================================================================
adamstark@22 52 void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType)
adamstark@5 53 {
adamstark@27 54 if (initialised) // if we have already initialised FFT plan
adamstark@5 55 {
adamstark@5 56 // destroy fft plan
adamstark@5 57 fftw_destroy_plan(p);
adamstark@22 58 fftw_free(complexIn);
adamstark@22 59 fftw_free(complexOut);
adamstark@27 60
adamstark@5 61 }
adamstark@5 62
adamstark@22 63 hopSize = hopSize_; // set hopsize
adamstark@22 64 frameSize = frameSize_; // set framesize
adamstark@5 65
adamstark@22 66 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type
adamstark@5 67
adamstark@5 68 // initialise buffers
adamstark@27 69 frame.resize(frameSize);
adamstark@27 70 window.resize(frameSize);
adamstark@27 71 magSpec.resize(frameSize);
adamstark@27 72 prevMagSpec.resize(frameSize);
adamstark@27 73 phase.resize(frameSize);
adamstark@27 74 prevPhase.resize(frameSize);
adamstark@27 75 prevPhase2.resize(frameSize);
adamstark@5 76
adamstark@5 77
adamstark@5 78 // set the window to the specified type
adamstark@22 79 switch (windowType){
adamstark@20 80 case RectangularWindow:
adamstark@22 81 calculateRectangularWindow(); // Rectangular window
adamstark@5 82 break;
adamstark@20 83 case HanningWindow:
adamstark@22 84 calculateHanningWindow(); // Hanning Window
adamstark@5 85 break;
adamstark@20 86 case HammingWindow:
adamstark@22 87 calclulateHammingWindow(); // Hamming Window
adamstark@5 88 break;
adamstark@20 89 case BlackmanWindow:
adamstark@22 90 calculateBlackmanWindow(); // Blackman Window
adamstark@5 91 break;
adamstark@20 92 case TukeyWindow:
adamstark@22 93 calculateTukeyWindow(); // Tukey Window
adamstark@5 94 break;
adamstark@5 95 default:
adamstark@22 96 calculateHanningWindow(); // DEFAULT: Hanning Window
adamstark@5 97 }
adamstark@5 98
adamstark@5 99 // initialise previous magnitude spectrum to zero
adamstark@22 100 for (int i = 0;i < frameSize;i++)
adamstark@5 101 {
adamstark@22 102 prevMagSpec[i] = 0.0;
adamstark@22 103 prevPhase[i] = 0.0;
adamstark@22 104 prevPhase2[i] = 0.0;
adamstark@5 105 frame[i] = 0.0;
adamstark@5 106 }
adamstark@5 107
adamstark@22 108 prevEnergySum = 0.0; // initialise previous energy sum value to zero
adamstark@5 109
adamstark@5 110 /* Init fft */
adamstark@22 111 complexIn = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * frameSize); // complex array to hold fft data
adamstark@22 112 complexOut = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * frameSize); // complex array to hold fft data
adamstark@22 113 p = fftw_plan_dft_1d(frameSize, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation
adamstark@5 114
adamstark@27 115 initialised = true;
adamstark@5 116 }
adamstark@5 117
adamstark@15 118 //=======================================================================
adamstark@22 119 void OnsetDetectionFunction :: setOnsetDetectionFunctionType(int onsetDetectionFunctionType_)
adamstark@5 120 {
adamstark@22 121 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type
adamstark@5 122 }
adamstark@5 123
adamstark@15 124 //=======================================================================
adamstark@22 125 double OnsetDetectionFunction :: calculateOnsetDetectionFunctionSample(double *buffer)
adamstark@5 126 {
adamstark@22 127 double odfSample;
adamstark@5 128
adamstark@5 129 // shift audio samples back in frame by hop size
adamstark@22 130 for (int i = 0; i < (frameSize-hopSize);i++)
adamstark@5 131 {
adamstark@22 132 frame[i] = frame[i+hopSize];
adamstark@5 133 }
adamstark@5 134
adamstark@5 135 // add new samples to frame from input buffer
adamstark@5 136 int j = 0;
adamstark@22 137 for (int i = (frameSize-hopSize);i < frameSize;i++)
adamstark@5 138 {
adamstark@22 139 frame[i] = buffer[j];
adamstark@5 140 j++;
adamstark@5 141 }
adamstark@5 142
adamstark@22 143 switch (onsetDetectionFunctionType){
adamstark@20 144 case EnergyEnvelope:
adamstark@20 145 {
adamstark@20 146 // calculate energy envelope detection function sample
adamstark@22 147 odfSample = energyEnvelope();
adamstark@5 148 break;
adamstark@20 149 }
adamstark@20 150 case EnergyDifference:
adamstark@20 151 {
adamstark@20 152 // calculate half-wave rectified energy difference detection function sample
adamstark@22 153 odfSample = energyDifference();
adamstark@5 154 break;
adamstark@20 155 }
adamstark@20 156 case SpectralDifference:
adamstark@20 157 {
adamstark@20 158 // calculate spectral difference detection function sample
adamstark@22 159 odfSample = spectralDifference();
adamstark@5 160 break;
adamstark@20 161 }
adamstark@20 162 case SpectralDifferenceHWR:
adamstark@20 163 {
adamstark@20 164 // calculate spectral difference detection function sample (half wave rectified)
adamstark@22 165 odfSample = spectralDifferenceHWR();
adamstark@5 166 break;
adamstark@20 167 }
adamstark@20 168 case PhaseDeviation:
adamstark@20 169 {
adamstark@20 170 // calculate phase deviation detection function sample (half wave rectified)
adamstark@22 171 odfSample = phaseDeviation();
adamstark@5 172 break;
adamstark@20 173 }
adamstark@20 174 case ComplexSpectralDifference:
adamstark@20 175 {
adamstark@20 176 // calcualte complex spectral difference detection function sample
adamstark@22 177 odfSample = complexSpectralDifference();
adamstark@5 178 break;
adamstark@20 179 }
adamstark@20 180 case ComplexSpectralDifferenceHWR:
adamstark@20 181 {
adamstark@20 182 // calcualte complex spectral difference detection function sample (half-wave rectified)
adamstark@22 183 odfSample = complexSpectralDifferenceHWR();
adamstark@5 184 break;
adamstark@20 185 }
adamstark@20 186 case HighFrequencyContent:
adamstark@20 187 {
adamstark@20 188 // calculate high frequency content detection function sample
adamstark@22 189 odfSample = highFrequencyContent();
adamstark@5 190 break;
adamstark@20 191 }
adamstark@20 192 case HighFrequencySpectralDifference:
adamstark@20 193 {
adamstark@20 194 // calculate high frequency spectral difference detection function sample
adamstark@22 195 odfSample = highFrequencySpectralDifference();
adamstark@5 196 break;
adamstark@20 197 }
adamstark@20 198 case HighFrequencySpectralDifferenceHWR:
adamstark@20 199 {
adamstark@20 200 // calculate high frequency spectral difference detection function (half-wave rectified)
adamstark@22 201 odfSample = highFrequencySpectralDifferenceHWR();
adamstark@20 202 break;
adamstark@20 203 }
adamstark@5 204 default:
adamstark@20 205 {
adamstark@22 206 odfSample = 1.0;
adamstark@20 207 }
adamstark@5 208 }
adamstark@5 209
adamstark@22 210 return odfSample;
adamstark@5 211 }
adamstark@5 212
adamstark@5 213
adamstark@15 214 //=======================================================================
adamstark@22 215 void OnsetDetectionFunction :: performFFT()
adamstark@5 216 {
adamstark@22 217 int fsize2 = (frameSize/2);
adamstark@5 218
adamstark@5 219 // window frame and copy to complex array, swapping the first and second half of the signal
adamstark@5 220 for (int i = 0;i < fsize2;i++)
adamstark@5 221 {
adamstark@22 222 complexIn[i][0] = frame[i+fsize2] * window[i+fsize2];
adamstark@22 223 complexIn[i][1] = 0.0;
adamstark@22 224 complexIn[i+fsize2][0] = frame[i] * window[i];
adamstark@22 225 complexIn[i+fsize2][1] = 0.0;
adamstark@5 226 }
adamstark@5 227
adamstark@5 228 // perform the fft
adamstark@5 229 fftw_execute(p);
adamstark@5 230 }
adamstark@5 231
adamstark@5 232 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 233 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 234 ////////////////////////////// Methods for Detection Functions /////////////////////////////////
adamstark@5 235
adamstark@15 236 //=======================================================================
adamstark@22 237 double OnsetDetectionFunction :: energyEnvelope()
adamstark@5 238 {
adamstark@5 239 double sum;
adamstark@5 240
adamstark@5 241 sum = 0; // initialise sum
adamstark@5 242
adamstark@5 243 // sum the squares of the samples
adamstark@22 244 for (int i = 0;i < frameSize;i++)
adamstark@5 245 {
adamstark@5 246 sum = sum + (frame[i]*frame[i]);
adamstark@5 247 }
adamstark@5 248
adamstark@5 249 return sum; // return sum
adamstark@5 250 }
adamstark@5 251
adamstark@15 252 //=======================================================================
adamstark@22 253 double OnsetDetectionFunction :: energyDifference()
adamstark@5 254 {
adamstark@5 255 double sum;
adamstark@5 256 double sample;
adamstark@5 257
adamstark@5 258 sum = 0; // initialise sum
adamstark@5 259
adamstark@5 260 // sum the squares of the samples
adamstark@22 261 for (int i = 0;i < frameSize;i++)
adamstark@5 262 {
adamstark@5 263 sum = sum + (frame[i]*frame[i]);
adamstark@5 264 }
adamstark@5 265
adamstark@22 266 sample = sum - prevEnergySum; // sample is first order difference in energy
adamstark@5 267
adamstark@22 268 prevEnergySum = sum; // store energy value for next calculation
adamstark@5 269
adamstark@5 270 if (sample > 0)
adamstark@5 271 {
adamstark@5 272 return sample; // return difference
adamstark@5 273 }
adamstark@5 274 else
adamstark@5 275 {
adamstark@5 276 return 0;
adamstark@5 277 }
adamstark@5 278 }
adamstark@5 279
adamstark@15 280 //=======================================================================
adamstark@22 281 double OnsetDetectionFunction :: spectralDifference()
adamstark@5 282 {
adamstark@5 283 double diff;
adamstark@5 284 double sum;
adamstark@5 285
adamstark@5 286 // perform the FFT
adamstark@22 287 performFFT();
adamstark@5 288
adamstark@5 289 // compute first (N/2)+1 mag values
adamstark@22 290 for (int i = 0;i < (frameSize/2)+1;i++)
adamstark@5 291 {
adamstark@22 292 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 293 }
adamstark@5 294 // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@22 295 for (int i = (frameSize/2)+1;i < frameSize;i++)
adamstark@5 296 {
adamstark@22 297 magSpec[i] = magSpec[frameSize-i];
adamstark@5 298 }
adamstark@5 299
adamstark@5 300 sum = 0; // initialise sum to zero
adamstark@5 301
adamstark@22 302 for (int i = 0;i < frameSize;i++)
adamstark@5 303 {
adamstark@5 304 // calculate difference
adamstark@22 305 diff = magSpec[i] - prevMagSpec[i];
adamstark@5 306
adamstark@5 307 // ensure all difference values are positive
adamstark@5 308 if (diff < 0)
adamstark@5 309 {
adamstark@5 310 diff = diff*-1;
adamstark@5 311 }
adamstark@5 312
adamstark@5 313 // add difference to sum
adamstark@5 314 sum = sum+diff;
adamstark@5 315
adamstark@5 316 // store magnitude spectrum bin for next detection function sample calculation
adamstark@22 317 prevMagSpec[i] = magSpec[i];
adamstark@5 318 }
adamstark@5 319
adamstark@5 320 return sum;
adamstark@5 321 }
adamstark@5 322
adamstark@15 323 //=======================================================================
adamstark@22 324 double OnsetDetectionFunction :: spectralDifferenceHWR()
adamstark@5 325 {
adamstark@5 326 double diff;
adamstark@5 327 double sum;
adamstark@5 328
adamstark@5 329 // perform the FFT
adamstark@22 330 performFFT();
adamstark@5 331
adamstark@5 332 // compute first (N/2)+1 mag values
adamstark@22 333 for (int i = 0;i < (frameSize/2)+1;i++)
adamstark@5 334 {
adamstark@22 335 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 336 }
adamstark@5 337 // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@22 338 for (int i = (frameSize/2)+1;i < frameSize;i++)
adamstark@5 339 {
adamstark@22 340 magSpec[i] = magSpec[frameSize-i];
adamstark@5 341 }
adamstark@5 342
adamstark@5 343 sum = 0; // initialise sum to zero
adamstark@5 344
adamstark@22 345 for (int i = 0;i < frameSize;i++)
adamstark@5 346 {
adamstark@5 347 // calculate difference
adamstark@22 348 diff = magSpec[i] - prevMagSpec[i];
adamstark@5 349
adamstark@5 350 // only add up positive differences
adamstark@5 351 if (diff > 0)
adamstark@5 352 {
adamstark@5 353 // add difference to sum
adamstark@5 354 sum = sum+diff;
adamstark@5 355 }
adamstark@5 356
adamstark@5 357
adamstark@5 358
adamstark@5 359 // store magnitude spectrum bin for next detection function sample calculation
adamstark@22 360 prevMagSpec[i] = magSpec[i];
adamstark@5 361 }
adamstark@5 362
adamstark@5 363 return sum;
adamstark@5 364 }
adamstark@5 365
adamstark@5 366
adamstark@15 367 //=======================================================================
adamstark@22 368 double OnsetDetectionFunction :: phaseDeviation()
adamstark@5 369 {
adamstark@5 370 double dev,pdev;
adamstark@5 371 double sum;
adamstark@5 372
adamstark@5 373 // perform the FFT
adamstark@22 374 performFFT();
adamstark@5 375
adamstark@5 376 sum = 0; // initialise sum to zero
adamstark@5 377
adamstark@5 378 // compute phase values from fft output and sum deviations
adamstark@22 379 for (int i = 0;i < frameSize;i++)
adamstark@5 380 {
adamstark@5 381 // calculate phase value
adamstark@22 382 phase[i] = atan2(complexOut[i][1],complexOut[i][0]);
adamstark@5 383
adamstark@5 384 // calculate magnitude value
adamstark@22 385 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 386
adamstark@5 387
adamstark@5 388 // if bin is not just a low energy bin then examine phase deviation
adamstark@22 389 if (magSpec[i] > 0.1)
adamstark@5 390 {
adamstark@22 391 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; // phase deviation
adamstark@5 392 pdev = princarg(dev); // wrap into [-pi,pi] range
adamstark@5 393
adamstark@5 394 // make all values positive
adamstark@5 395 if (pdev < 0)
adamstark@5 396 {
adamstark@5 397 pdev = pdev*-1;
adamstark@5 398 }
adamstark@5 399
adamstark@5 400 // add to sum
adamstark@5 401 sum = sum + pdev;
adamstark@5 402 }
adamstark@5 403
adamstark@5 404 // store values for next calculation
adamstark@22 405 prevPhase2[i] = prevPhase[i];
adamstark@22 406 prevPhase[i] = phase[i];
adamstark@5 407 }
adamstark@5 408
adamstark@5 409 return sum;
adamstark@5 410 }
adamstark@5 411
adamstark@15 412 //=======================================================================
adamstark@22 413 double OnsetDetectionFunction :: complexSpectralDifference()
adamstark@5 414 {
adamstark@5 415 double dev,pdev;
adamstark@5 416 double sum;
adamstark@5 417 double mag_diff,phase_diff;
adamstark@5 418 double value;
adamstark@5 419
adamstark@5 420 // perform the FFT
adamstark@22 421 performFFT();
adamstark@5 422
adamstark@5 423 sum = 0; // initialise sum to zero
adamstark@5 424
adamstark@5 425 // compute phase values from fft output and sum deviations
adamstark@22 426 for (int i = 0;i < frameSize;i++)
adamstark@5 427 {
adamstark@5 428 // calculate phase value
adamstark@22 429 phase[i] = atan2(complexOut[i][1],complexOut[i][0]);
adamstark@5 430
adamstark@5 431 // calculate magnitude value
adamstark@22 432 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 433
adamstark@5 434
adamstark@5 435 // phase deviation
adamstark@22 436 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i];
adamstark@5 437
adamstark@5 438 // wrap into [-pi,pi] range
adamstark@5 439 pdev = princarg(dev);
adamstark@5 440
adamstark@5 441
adamstark@5 442 // calculate magnitude difference (real part of Euclidean distance between complex frames)
adamstark@22 443 mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@5 444
adamstark@5 445 // calculate phase difference (imaginary part of Euclidean distance between complex frames)
adamstark@22 446 phase_diff = -magSpec[i]*sin(pdev);
adamstark@5 447
adamstark@5 448
adamstark@5 449
adamstark@5 450 // square real and imaginary parts, sum and take square root
adamstark@5 451 value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
adamstark@5 452
adamstark@5 453
adamstark@5 454 // add to sum
adamstark@5 455 sum = sum + value;
adamstark@5 456
adamstark@5 457
adamstark@5 458 // store values for next calculation
adamstark@22 459 prevPhase2[i] = prevPhase[i];
adamstark@22 460 prevPhase[i] = phase[i];
adamstark@22 461 prevMagSpec[i] = magSpec[i];
adamstark@5 462 }
adamstark@5 463
adamstark@5 464 return sum;
adamstark@5 465 }
adamstark@5 466
adamstark@15 467 //=======================================================================
adamstark@22 468 double OnsetDetectionFunction :: complexSpectralDifferenceHWR()
adamstark@5 469 {
adamstark@5 470 double dev,pdev;
adamstark@5 471 double sum;
adamstark@5 472 double mag_diff,phase_diff;
adamstark@5 473 double value;
adamstark@5 474
adamstark@5 475 // perform the FFT
adamstark@22 476 performFFT();
adamstark@5 477
adamstark@5 478 sum = 0; // initialise sum to zero
adamstark@5 479
adamstark@5 480 // compute phase values from fft output and sum deviations
adamstark@22 481 for (int i = 0;i < frameSize;i++)
adamstark@5 482 {
adamstark@5 483 // calculate phase value
adamstark@22 484 phase[i] = atan2(complexOut[i][1],complexOut[i][0]);
adamstark@5 485
adamstark@5 486 // calculate magnitude value
adamstark@22 487 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 488
adamstark@5 489
adamstark@5 490 // phase deviation
adamstark@22 491 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i];
adamstark@5 492
adamstark@5 493 // wrap into [-pi,pi] range
adamstark@5 494 pdev = princarg(dev);
adamstark@5 495
adamstark@5 496
adamstark@5 497 // calculate magnitude difference (real part of Euclidean distance between complex frames)
adamstark@22 498 mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@5 499
adamstark@5 500 // if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification)
adamstark@5 501 if (mag_diff > 0)
adamstark@5 502 {
adamstark@5 503 // calculate phase difference (imaginary part of Euclidean distance between complex frames)
adamstark@22 504 phase_diff = -magSpec[i]*sin(pdev);
adamstark@5 505
adamstark@5 506 // square real and imaginary parts, sum and take square root
adamstark@5 507 value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
adamstark@5 508
adamstark@5 509 // add to sum
adamstark@5 510 sum = sum + value;
adamstark@5 511 }
adamstark@5 512
adamstark@5 513 // store values for next calculation
adamstark@22 514 prevPhase2[i] = prevPhase[i];
adamstark@22 515 prevPhase[i] = phase[i];
adamstark@22 516 prevMagSpec[i] = magSpec[i];
adamstark@5 517 }
adamstark@5 518
adamstark@5 519 return sum;
adamstark@5 520 }
adamstark@5 521
adamstark@5 522
adamstark@15 523 //=======================================================================
adamstark@22 524 double OnsetDetectionFunction :: highFrequencyContent()
adamstark@5 525 {
adamstark@5 526 double sum;
adamstark@5 527
adamstark@5 528 // perform the FFT
adamstark@22 529 performFFT();
adamstark@5 530
adamstark@5 531 sum = 0; // initialise sum to zero
adamstark@5 532
adamstark@5 533 // compute phase values from fft output and sum deviations
adamstark@22 534 for (int i = 0;i < frameSize;i++)
adamstark@5 535 {
adamstark@5 536 // calculate magnitude value
adamstark@22 537 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 538
adamstark@5 539
adamstark@22 540 sum = sum + (magSpec[i]*((double) (i+1)));
adamstark@5 541
adamstark@5 542 // store values for next calculation
adamstark@22 543 prevMagSpec[i] = magSpec[i];
adamstark@5 544 }
adamstark@5 545
adamstark@5 546 return sum;
adamstark@5 547 }
adamstark@5 548
adamstark@15 549 //=======================================================================
adamstark@22 550 double OnsetDetectionFunction :: highFrequencySpectralDifference()
adamstark@5 551 {
adamstark@5 552 double sum;
adamstark@5 553 double mag_diff;
adamstark@5 554
adamstark@5 555 // perform the FFT
adamstark@22 556 performFFT();
adamstark@5 557
adamstark@5 558 sum = 0; // initialise sum to zero
adamstark@5 559
adamstark@5 560 // compute phase values from fft output and sum deviations
adamstark@22 561 for (int i = 0;i < frameSize;i++)
adamstark@5 562 {
adamstark@5 563 // calculate magnitude value
adamstark@22 564 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 565
adamstark@5 566 // calculate difference
adamstark@22 567 mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@5 568
adamstark@5 569 if (mag_diff < 0)
adamstark@5 570 {
adamstark@5 571 mag_diff = -mag_diff;
adamstark@5 572 }
adamstark@5 573
adamstark@5 574 sum = sum + (mag_diff*((double) (i+1)));
adamstark@5 575
adamstark@5 576 // store values for next calculation
adamstark@22 577 prevMagSpec[i] = magSpec[i];
adamstark@5 578 }
adamstark@5 579
adamstark@5 580 return sum;
adamstark@5 581 }
adamstark@5 582
adamstark@15 583 //=======================================================================
adamstark@22 584 double OnsetDetectionFunction :: highFrequencySpectralDifferenceHWR()
adamstark@5 585 {
adamstark@5 586 double sum;
adamstark@5 587 double mag_diff;
adamstark@5 588
adamstark@5 589 // perform the FFT
adamstark@22 590 performFFT();
adamstark@5 591
adamstark@5 592 sum = 0; // initialise sum to zero
adamstark@5 593
adamstark@5 594 // compute phase values from fft output and sum deviations
adamstark@22 595 for (int i = 0;i < frameSize;i++)
adamstark@5 596 {
adamstark@5 597 // calculate magnitude value
adamstark@22 598 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@5 599
adamstark@5 600 // calculate difference
adamstark@22 601 mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@5 602
adamstark@5 603 if (mag_diff > 0)
adamstark@5 604 {
adamstark@5 605 sum = sum + (mag_diff*((double) (i+1)));
adamstark@5 606 }
adamstark@5 607
adamstark@5 608 // store values for next calculation
adamstark@22 609 prevMagSpec[i] = magSpec[i];
adamstark@5 610 }
adamstark@5 611
adamstark@5 612 return sum;
adamstark@5 613 }
adamstark@5 614
adamstark@5 615
adamstark@5 616 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 617 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 618 ////////////////////////////// Methods to Calculate Windows ////////////////////////////////////
adamstark@5 619
adamstark@15 620 //=======================================================================
adamstark@22 621 void OnsetDetectionFunction :: calculateHanningWindow()
adamstark@5 622 {
adamstark@5 623 double N; // variable to store framesize minus 1
adamstark@5 624
adamstark@22 625 N = (double) (frameSize-1); // framesize minus 1
adamstark@5 626
adamstark@5 627 // Hanning window calculation
adamstark@22 628 for (int n = 0;n < frameSize;n++)
adamstark@5 629 {
adamstark@5 630 window[n] = 0.5*(1-cos(2*pi*(n/N)));
adamstark@5 631 }
adamstark@5 632 }
adamstark@5 633
adamstark@15 634 //=======================================================================
adamstark@22 635 void OnsetDetectionFunction :: calclulateHammingWindow()
adamstark@5 636 {
adamstark@5 637 double N; // variable to store framesize minus 1
adamstark@5 638 double n_val; // double version of index 'n'
adamstark@5 639
adamstark@22 640 N = (double) (frameSize-1); // framesize minus 1
adamstark@5 641 n_val = 0;
adamstark@5 642
adamstark@5 643 // Hamming window calculation
adamstark@22 644 for (int n = 0;n < frameSize;n++)
adamstark@5 645 {
adamstark@5 646 window[n] = 0.54 - (0.46*cos(2*pi*(n_val/N)));
adamstark@5 647 n_val = n_val+1;
adamstark@5 648 }
adamstark@5 649 }
adamstark@5 650
adamstark@15 651 //=======================================================================
adamstark@22 652 void OnsetDetectionFunction :: calculateBlackmanWindow()
adamstark@5 653 {
adamstark@5 654 double N; // variable to store framesize minus 1
adamstark@5 655 double n_val; // double version of index 'n'
adamstark@5 656
adamstark@22 657 N = (double) (frameSize-1); // framesize minus 1
adamstark@5 658 n_val = 0;
adamstark@5 659
adamstark@5 660 // Blackman window calculation
adamstark@22 661 for (int n = 0;n < frameSize;n++)
adamstark@5 662 {
adamstark@5 663 window[n] = 0.42 - (0.5*cos(2*pi*(n_val/N))) + (0.08*cos(4*pi*(n_val/N)));
adamstark@5 664 n_val = n_val+1;
adamstark@5 665 }
adamstark@5 666 }
adamstark@5 667
adamstark@15 668 //=======================================================================
adamstark@22 669 void OnsetDetectionFunction :: calculateTukeyWindow()
adamstark@5 670 {
adamstark@5 671 double N; // variable to store framesize minus 1
adamstark@5 672 double n_val; // double version of index 'n'
adamstark@5 673 double alpha; // alpha [default value = 0.5];
adamstark@5 674
adamstark@5 675 alpha = 0.5;
adamstark@5 676
adamstark@22 677 N = (double) (frameSize-1); // framesize minus 1
adamstark@5 678
adamstark@5 679 // Tukey window calculation
adamstark@5 680
adamstark@22 681 n_val = (double) (-1*((frameSize/2)))+1;
adamstark@5 682
adamstark@22 683 for (int n = 0;n < frameSize;n++) // left taper
adamstark@5 684 {
adamstark@5 685 if ((n_val >= 0) && (n_val <= (alpha*(N/2))))
adamstark@5 686 {
adamstark@5 687 window[n] = 1.0;
adamstark@5 688 }
adamstark@5 689 else if ((n_val <= 0) && (n_val >= (-1*alpha*(N/2))))
adamstark@5 690 {
adamstark@5 691 window[n] = 1.0;
adamstark@5 692 }
adamstark@5 693 else
adamstark@5 694 {
adamstark@5 695 window[n] = 0.5*(1+cos(pi*(((2*n_val)/(alpha*N))-1)));
adamstark@5 696 }
adamstark@5 697
adamstark@5 698 n_val = n_val+1;
adamstark@5 699 }
adamstark@5 700
adamstark@5 701 }
adamstark@5 702
adamstark@15 703 //=======================================================================
adamstark@22 704 void OnsetDetectionFunction :: calculateRectangularWindow()
adamstark@5 705 {
adamstark@5 706 // Rectangular window calculation
adamstark@22 707 for (int n = 0;n < frameSize;n++)
adamstark@5 708 {
adamstark@5 709 window[n] = 1.0;
adamstark@5 710 }
adamstark@5 711 }
adamstark@5 712
adamstark@5 713
adamstark@5 714
adamstark@5 715 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 716 ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@5 717 ///////////////////////////////// Other Handy Methods //////////////////////////////////////////
adamstark@5 718
adamstark@15 719 //=======================================================================
adamstark@22 720 double OnsetDetectionFunction :: princarg(double phaseVal)
adamstark@5 721 {
adamstark@5 722 // if phase value is less than or equal to -pi then add 2*pi
adamstark@22 723 while (phaseVal <= (-pi))
adamstark@5 724 {
adamstark@22 725 phaseVal = phaseVal + (2*pi);
adamstark@5 726 }
adamstark@5 727
adamstark@5 728 // if phase value is larger than pi, then subtract 2*pi
adamstark@22 729 while (phaseVal > pi)
adamstark@5 730 {
adamstark@22 731 phaseVal = phaseVal - (2*pi);
adamstark@5 732 }
adamstark@5 733
adamstark@22 734 return phaseVal;
adamstark@5 735 }
adamstark@5 736
adamstark@5 737
adamstark@5 738
adamstark@5 739
adamstark@5 740
adamstark@5 741
adamstark@5 742
adamstark@5 743
adamstark@5 744
adamstark@5 745
adamstark@5 746
adamstark@5 747
adamstark@5 748