annotate src/OnsetDetectionFunction.cpp @ 46:af7739411685

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