annotate src/OnsetDetectionFunction.cpp @ 5:bd2c405d4a06 develop

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