annotate src/OnsetDetectionFunction.cpp @ 59:ba3fc238ccad

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