annotate src/OnsetDetectionFunction.cpp @ 20:baf35f208814 develop

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