annotate src/OnsetDetectionFunction.cpp @ 38:b7e3ed593fb0

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