annotate src/OnsetDetectionFunction.cpp @ 92:f6708e4c69f1

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