annotate src/btrack_plus/OnsetDetectionFunction.cpp @ 8:184a7c232049 tip

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