annotate src/OnsetDetectionFunction.cpp @ 66:b387d8327729

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