annotate src/OnsetDetectionFunction.cpp @ 93:4aa362058011

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