annotate src/OnsetDetectionFunction.cpp @ 21:ef4721e7466c develop

Did more renaming of obscurely named variables and added a couple of accessor methods
author Adam <adamstark.uk@gmail.com>
date Thu, 23 Jan 2014 18:00:53 +0000
parents baf35f208814
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