annotate src/OnsetDetectionFunction.cpp @ 29:bddd59087c36 develop

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