annotate src/OnsetDetectionFunction.cpp @ 22:a8e3e95d14e4 develop

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