annotate src/OnsetDetectionFunction.cpp @ 64:d3c52c6b3905

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