Mercurial > hg > btrack
comparison src/OnsetDetectionFunction.cpp @ 96:c58f01834337
Merge branch 'release/1.0.4'
author | Adam Stark <adamstark.uk@gmail.com> |
---|---|
date | Sat, 18 Jun 2016 10:50:06 +0100 |
parents | 4aa362058011 |
children | 6aea5918992d |
comparison
equal
deleted
inserted
replaced
87:496d12635af8 | 96:c58f01834337 |
---|---|
20 //======================================================================= | 20 //======================================================================= |
21 | 21 |
22 #include <math.h> | 22 #include <math.h> |
23 #include "OnsetDetectionFunction.h" | 23 #include "OnsetDetectionFunction.h" |
24 | 24 |
25 | 25 //======================================================================= |
26 //======================================================================= | 26 OnsetDetectionFunction::OnsetDetectionFunction (int hopSize_,int frameSize_) |
27 OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_) : onsetDetectionFunctionType(ComplexSpectralDifferenceHWR), windowType(HanningWindow) | 27 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) |
28 { | 28 { |
29 // indicate that we have not initialised yet | 29 // indicate that we have not initialised yet |
30 initialised = false; | 30 initialised = false; |
31 | 31 |
32 // set pi | 32 // set pi |
33 pi = 3.14159265358979; | 33 pi = 3.14159265358979; |
34 | 34 |
35 // initialise with arguments to constructor | 35 // initialise with arguments to constructor |
36 initialise(hopSize_,frameSize_,ComplexSpectralDifferenceHWR,HanningWindow); | 36 initialise (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow); |
37 } | 37 } |
38 | 38 |
39 //======================================================================= | 39 //======================================================================= |
40 OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) : onsetDetectionFunctionType(ComplexSpectralDifferenceHWR), windowType(HanningWindow) | 40 OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) |
41 : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow) | |
41 { | 42 { |
42 // indicate that we have not initialised yet | 43 // indicate that we have not initialised yet |
43 initialised = false; | 44 initialised = false; |
44 | 45 |
45 // set pi | 46 // set pi |
46 pi = 3.14159265358979; | 47 pi = 3.14159265358979; |
47 | 48 |
48 // initialise with arguments to constructor | 49 // initialise with arguments to constructor |
49 initialise(hopSize_,frameSize_,onsetDetectionFunctionType_,windowType_); | 50 initialise (hopSize_, frameSize_, onsetDetectionFunctionType_, windowType_); |
50 } | 51 } |
51 | 52 |
52 | 53 |
53 //======================================================================= | 54 //======================================================================= |
54 OnsetDetectionFunction::~OnsetDetectionFunction() | 55 OnsetDetectionFunction::~OnsetDetectionFunction() |
55 { | 56 { |
56 if (initialised) | 57 if (initialised) |
57 { | 58 { |
58 // destroy fft plan | 59 freeFFT(); |
59 fftw_destroy_plan(p); | |
60 fftw_free(complexIn); | |
61 fftw_free(complexOut); | |
62 } | 60 } |
63 } | 61 } |
64 | 62 |
65 //======================================================================= | 63 //======================================================================= |
66 void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_) | 64 void OnsetDetectionFunction::initialise (int hopSize_, int frameSize_) |
67 { | 65 { |
68 // use the already initialised onset detection function and window type and | 66 // use the already initialised onset detection function and window type and |
69 // pass the new frame and hop size to the main initialisation function | 67 // pass the new frame and hop size to the main initialisation function |
70 initialise(hopSize_, frameSize_, onsetDetectionFunctionType, windowType); | 68 initialise (hopSize_, frameSize_, onsetDetectionFunctionType, windowType); |
71 } | 69 } |
72 | 70 |
73 //======================================================================= | 71 //======================================================================= |
74 void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) | 72 void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_) |
75 { | 73 { |
76 if (initialised) // if we have already initialised FFT plan | |
77 { | |
78 // destroy fft plan | |
79 fftw_destroy_plan(p); | |
80 fftw_free(complexIn); | |
81 fftw_free(complexOut); | |
82 | |
83 } | |
84 | |
85 hopSize = hopSize_; // set hopsize | 74 hopSize = hopSize_; // set hopsize |
86 frameSize = frameSize_; // set framesize | 75 frameSize = frameSize_; // set framesize |
87 | 76 |
88 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type | 77 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type |
89 windowType = windowType_; // set window type | 78 windowType = windowType_; // set window type |
90 | 79 |
91 // initialise buffers | 80 // initialise buffers |
92 frame.resize(frameSize); | 81 frame.resize (frameSize); |
93 window.resize(frameSize); | 82 window.resize (frameSize); |
94 magSpec.resize(frameSize); | 83 magSpec.resize (frameSize); |
95 prevMagSpec.resize(frameSize); | 84 prevMagSpec.resize (frameSize); |
96 phase.resize(frameSize); | 85 phase.resize (frameSize); |
97 prevPhase.resize(frameSize); | 86 prevPhase.resize (frameSize); |
98 prevPhase2.resize(frameSize); | 87 prevPhase2.resize (frameSize); |
99 | 88 |
100 | 89 |
101 // set the window to the specified type | 90 // set the window to the specified type |
102 switch (windowType){ | 91 switch (windowType) |
92 { | |
103 case RectangularWindow: | 93 case RectangularWindow: |
104 calculateRectangularWindow(); // Rectangular window | 94 calculateRectangularWindow(); // Rectangular window |
105 break; | 95 break; |
106 case HanningWindow: | 96 case HanningWindow: |
107 calculateHanningWindow(); // Hanning Window | 97 calculateHanningWindow(); // Hanning Window |
118 default: | 108 default: |
119 calculateHanningWindow(); // DEFAULT: Hanning Window | 109 calculateHanningWindow(); // DEFAULT: Hanning Window |
120 } | 110 } |
121 | 111 |
122 // initialise previous magnitude spectrum to zero | 112 // initialise previous magnitude spectrum to zero |
123 for (int i = 0;i < frameSize;i++) | 113 for (int i = 0; i < frameSize; i++) |
124 { | 114 { |
125 prevMagSpec[i] = 0.0; | 115 prevMagSpec[i] = 0.0; |
126 prevPhase[i] = 0.0; | 116 prevPhase[i] = 0.0; |
127 prevPhase2[i] = 0.0; | 117 prevPhase2[i] = 0.0; |
128 frame[i] = 0.0; | 118 frame[i] = 0.0; |
129 } | 119 } |
130 | 120 |
131 prevEnergySum = 0.0; // initialise previous energy sum value to zero | 121 prevEnergySum = 0.0; // initialise previous energy sum value to zero |
132 | 122 |
133 /* Init fft */ | 123 initialiseFFT(); |
134 complexIn = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * frameSize); // complex array to hold fft data | 124 } |
135 complexOut = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * frameSize); // complex array to hold fft data | 125 |
136 p = fftw_plan_dft_1d(frameSize, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation | 126 //======================================================================= |
137 | 127 void OnsetDetectionFunction::initialiseFFT() |
138 initialised = true; | 128 { |
139 } | 129 if (initialised) // if we have already initialised FFT plan |
140 | 130 { |
141 //======================================================================= | 131 freeFFT(); |
142 void OnsetDetectionFunction :: setOnsetDetectionFunctionType(int onsetDetectionFunctionType_) | 132 } |
133 | |
134 #ifdef USE_FFTW | |
135 complexIn = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * frameSize); // complex array to hold fft data | |
136 complexOut = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * frameSize); // complex array to hold fft data | |
137 p = fftw_plan_dft_1d (frameSize, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation | |
138 #endif | |
139 | |
140 #ifdef USE_KISS_FFT | |
141 complexOut.resize (frameSize); | |
142 | |
143 for (int i = 0; i < frameSize;i++) | |
144 { | |
145 complexOut[i].resize(2); | |
146 } | |
147 | |
148 fftIn = new kiss_fft_cpx[frameSize]; | |
149 fftOut = new kiss_fft_cpx[frameSize]; | |
150 cfg = kiss_fft_alloc (frameSize, 0, 0, 0); | |
151 #endif | |
152 | |
153 initialised = true; | |
154 } | |
155 | |
156 //======================================================================= | |
157 void OnsetDetectionFunction::freeFFT() | |
158 { | |
159 #ifdef USE_FFTW | |
160 fftw_destroy_plan (p); | |
161 fftw_free (complexIn); | |
162 fftw_free (complexOut); | |
163 #endif | |
164 | |
165 #ifdef USE_KISS_FFT | |
166 free (cfg); | |
167 delete [] fftIn; | |
168 delete [] fftOut; | |
169 #endif | |
170 } | |
171 | |
172 //======================================================================= | |
173 void OnsetDetectionFunction::setOnsetDetectionFunctionType (int onsetDetectionFunctionType_) | |
143 { | 174 { |
144 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type | 175 onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type |
145 } | 176 } |
146 | 177 |
147 //======================================================================= | 178 //======================================================================= |
148 double OnsetDetectionFunction :: calculateOnsetDetectionFunctionSample(double *buffer) | 179 double OnsetDetectionFunction::calculateOnsetDetectionFunctionSample (double* buffer) |
149 { | 180 { |
150 double odfSample; | 181 double odfSample; |
151 | 182 |
152 // shift audio samples back in frame by hop size | 183 // shift audio samples back in frame by hop size |
153 for (int i = 0; i < (frameSize-hopSize);i++) | 184 for (int i = 0; i < (frameSize-hopSize);i++) |
161 { | 192 { |
162 frame[i] = buffer[j]; | 193 frame[i] = buffer[j]; |
163 j++; | 194 j++; |
164 } | 195 } |
165 | 196 |
166 switch (onsetDetectionFunctionType){ | 197 switch (onsetDetectionFunctionType) |
198 { | |
167 case EnergyEnvelope: | 199 case EnergyEnvelope: |
168 { | 200 { |
169 // calculate energy envelope detection function sample | 201 // calculate energy envelope detection function sample |
170 odfSample = energyEnvelope(); | 202 odfSample = energyEnvelope(); |
171 break; | 203 break; |
233 return odfSample; | 265 return odfSample; |
234 } | 266 } |
235 | 267 |
236 | 268 |
237 //======================================================================= | 269 //======================================================================= |
238 void OnsetDetectionFunction :: performFFT() | 270 void OnsetDetectionFunction::performFFT() |
239 { | 271 { |
240 int fsize2 = (frameSize/2); | 272 int fsize2 = (frameSize/2); |
241 | 273 |
274 #ifdef USE_FFTW | |
242 // window frame and copy to complex array, swapping the first and second half of the signal | 275 // window frame and copy to complex array, swapping the first and second half of the signal |
243 for (int i = 0;i < fsize2;i++) | 276 for (int i = 0;i < fsize2;i++) |
244 { | 277 { |
245 complexIn[i][0] = frame[i+fsize2] * window[i+fsize2]; | 278 complexIn[i][0] = frame[i + fsize2] * window[i + fsize2]; |
246 complexIn[i][1] = 0.0; | 279 complexIn[i][1] = 0.0; |
247 complexIn[i+fsize2][0] = frame[i] * window[i]; | 280 complexIn[i+fsize2][0] = frame[i] * window[i]; |
248 complexIn[i+fsize2][1] = 0.0; | 281 complexIn[i+fsize2][1] = 0.0; |
249 } | 282 } |
250 | 283 |
251 // perform the fft | 284 // perform the fft |
252 fftw_execute(p); | 285 fftw_execute (p); |
286 #endif | |
287 | |
288 #ifdef USE_KISS_FFT | |
289 for (int i = 0; i < fsize2; i++) | |
290 { | |
291 fftIn[i].r = frame[i + fsize2] * window[i + fsize2]; | |
292 fftIn[i].i = 0.0; | |
293 fftIn[i + fsize2].r = frame[i] * window[i]; | |
294 fftIn[i + fsize2].i = 0.0; | |
295 } | |
296 | |
297 // execute kiss fft | |
298 kiss_fft (cfg, fftIn, fftOut); | |
299 | |
300 // store real and imaginary parts of FFT | |
301 for (int i = 0; i < frameSize; i++) | |
302 { | |
303 complexOut[i][0] = fftOut[i].r; | |
304 complexOut[i][1] = fftOut[i].i; | |
305 } | |
306 #endif | |
253 } | 307 } |
254 | 308 |
255 //////////////////////////////////////////////////////////////////////////////////////////////// | 309 //////////////////////////////////////////////////////////////////////////////////////////////// |
256 //////////////////////////////////////////////////////////////////////////////////////////////// | 310 //////////////////////////////////////////////////////////////////////////////////////////////// |
257 ////////////////////////////// Methods for Detection Functions ///////////////////////////////// | 311 ////////////////////////////// Methods for Detection Functions ///////////////////////////////// |
258 | 312 |
259 //======================================================================= | 313 //======================================================================= |
260 double OnsetDetectionFunction :: energyEnvelope() | 314 double OnsetDetectionFunction::energyEnvelope() |
261 { | 315 { |
262 double sum; | 316 double sum; |
263 | 317 |
264 sum = 0; // initialise sum | 318 sum = 0; // initialise sum |
265 | 319 |
266 // sum the squares of the samples | 320 // sum the squares of the samples |
267 for (int i = 0;i < frameSize;i++) | 321 for (int i = 0;i < frameSize;i++) |
268 { | 322 { |
269 sum = sum + (frame[i]*frame[i]); | 323 sum = sum + (frame[i] * frame[i]); |
270 } | 324 } |
271 | 325 |
272 return sum; // return sum | 326 return sum; // return sum |
273 } | 327 } |
274 | 328 |
275 //======================================================================= | 329 //======================================================================= |
276 double OnsetDetectionFunction :: energyDifference() | 330 double OnsetDetectionFunction::energyDifference() |
277 { | 331 { |
278 double sum; | 332 double sum; |
279 double sample; | 333 double sample; |
280 | 334 |
281 sum = 0; // initialise sum | 335 sum = 0; // initialise sum |
282 | 336 |
283 // sum the squares of the samples | 337 // sum the squares of the samples |
284 for (int i = 0;i < frameSize;i++) | 338 for (int i = 0; i < frameSize; i++) |
285 { | 339 { |
286 sum = sum + (frame[i]*frame[i]); | 340 sum = sum + (frame[i] * frame[i]); |
287 } | 341 } |
288 | 342 |
289 sample = sum - prevEnergySum; // sample is first order difference in energy | 343 sample = sum - prevEnergySum; // sample is first order difference in energy |
290 | 344 |
291 prevEnergySum = sum; // store energy value for next calculation | 345 prevEnergySum = sum; // store energy value for next calculation |
299 return 0; | 353 return 0; |
300 } | 354 } |
301 } | 355 } |
302 | 356 |
303 //======================================================================= | 357 //======================================================================= |
304 double OnsetDetectionFunction :: spectralDifference() | 358 double OnsetDetectionFunction::spectralDifference() |
305 { | 359 { |
306 double diff; | 360 double diff; |
307 double sum; | 361 double sum; |
308 | 362 |
309 // perform the FFT | 363 // perform the FFT |
310 performFFT(); | 364 performFFT(); |
311 | 365 |
312 // compute first (N/2)+1 mag values | 366 // compute first (N/2)+1 mag values |
313 for (int i = 0;i < (frameSize/2)+1;i++) | 367 for (int i = 0;i < (frameSize/2)+1;i++) |
314 { | 368 { |
315 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 369 magSpec[i] = sqrt (pow (complexOut[i][0], 2) + pow (complexOut[i][1], 2)); |
316 } | 370 } |
317 // mag spec symmetric above (N/2)+1 so copy previous values | 371 // mag spec symmetric above (N/2)+1 so copy previous values |
318 for (int i = (frameSize/2)+1;i < frameSize;i++) | 372 for (int i = (frameSize/2)+1; i < frameSize; i++) |
319 { | 373 { |
320 magSpec[i] = magSpec[frameSize-i]; | 374 magSpec[i] = magSpec[frameSize-i]; |
321 } | 375 } |
322 | 376 |
323 sum = 0; // initialise sum to zero | 377 sum = 0; // initialise sum to zero |
324 | 378 |
325 for (int i = 0;i < frameSize;i++) | 379 for (int i = 0; i < frameSize; i++) |
326 { | 380 { |
327 // calculate difference | 381 // calculate difference |
328 diff = magSpec[i] - prevMagSpec[i]; | 382 diff = magSpec[i] - prevMagSpec[i]; |
329 | 383 |
330 // ensure all difference values are positive | 384 // ensure all difference values are positive |
332 { | 386 { |
333 diff = diff*-1; | 387 diff = diff*-1; |
334 } | 388 } |
335 | 389 |
336 // add difference to sum | 390 // add difference to sum |
337 sum = sum+diff; | 391 sum = sum + diff; |
338 | 392 |
339 // store magnitude spectrum bin for next detection function sample calculation | 393 // store magnitude spectrum bin for next detection function sample calculation |
340 prevMagSpec[i] = magSpec[i]; | 394 prevMagSpec[i] = magSpec[i]; |
341 } | 395 } |
342 | 396 |
343 return sum; | 397 return sum; |
344 } | 398 } |
345 | 399 |
346 //======================================================================= | 400 //======================================================================= |
347 double OnsetDetectionFunction :: spectralDifferenceHWR() | 401 double OnsetDetectionFunction::spectralDifferenceHWR() |
348 { | 402 { |
349 double diff; | 403 double diff; |
350 double sum; | 404 double sum; |
351 | 405 |
352 // perform the FFT | 406 // perform the FFT |
353 performFFT(); | 407 performFFT(); |
354 | 408 |
355 // compute first (N/2)+1 mag values | 409 // compute first (N/2)+1 mag values |
356 for (int i = 0;i < (frameSize/2)+1;i++) | 410 for (int i = 0;i < (frameSize/2) + 1; i++) |
357 { | 411 { |
358 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 412 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
359 } | 413 } |
360 // mag spec symmetric above (N/2)+1 so copy previous values | 414 // mag spec symmetric above (N/2)+1 so copy previous values |
361 for (int i = (frameSize/2)+1;i < frameSize;i++) | 415 for (int i = (frameSize/2)+1;i < frameSize;i++) |
362 { | 416 { |
363 magSpec[i] = magSpec[frameSize-i]; | 417 magSpec[i] = magSpec[frameSize-i]; |
375 { | 429 { |
376 // add difference to sum | 430 // add difference to sum |
377 sum = sum+diff; | 431 sum = sum+diff; |
378 } | 432 } |
379 | 433 |
380 | |
381 | |
382 // store magnitude spectrum bin for next detection function sample calculation | 434 // store magnitude spectrum bin for next detection function sample calculation |
383 prevMagSpec[i] = magSpec[i]; | 435 prevMagSpec[i] = magSpec[i]; |
384 } | 436 } |
385 | 437 |
386 return sum; | 438 return sum; |
387 } | 439 } |
388 | 440 |
389 | 441 |
390 //======================================================================= | 442 //======================================================================= |
391 double OnsetDetectionFunction :: phaseDeviation() | 443 double OnsetDetectionFunction::phaseDeviation() |
392 { | 444 { |
393 double dev,pdev; | 445 double dev,pdev; |
394 double sum; | 446 double sum; |
395 | 447 |
396 // perform the FFT | 448 // perform the FFT |
400 | 452 |
401 // compute phase values from fft output and sum deviations | 453 // compute phase values from fft output and sum deviations |
402 for (int i = 0;i < frameSize;i++) | 454 for (int i = 0;i < frameSize;i++) |
403 { | 455 { |
404 // calculate phase value | 456 // calculate phase value |
405 phase[i] = atan2(complexOut[i][1],complexOut[i][0]); | 457 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
406 | 458 |
407 // calculate magnitude value | 459 // calculate magnitude value |
408 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 460 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
409 | 461 |
410 | 462 |
411 // if bin is not just a low energy bin then examine phase deviation | 463 // if bin is not just a low energy bin then examine phase deviation |
412 if (magSpec[i] > 0.1) | 464 if (magSpec[i] > 0.1) |
413 { | 465 { |
414 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; // phase deviation | 466 dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; // phase deviation |
415 pdev = princarg(dev); // wrap into [-pi,pi] range | 467 pdev = princarg (dev); // wrap into [-pi,pi] range |
416 | 468 |
417 // make all values positive | 469 // make all values positive |
418 if (pdev < 0) | 470 if (pdev < 0) |
419 { | 471 { |
420 pdev = pdev*-1; | 472 pdev = pdev*-1; |
431 | 483 |
432 return sum; | 484 return sum; |
433 } | 485 } |
434 | 486 |
435 //======================================================================= | 487 //======================================================================= |
436 double OnsetDetectionFunction :: complexSpectralDifference() | 488 double OnsetDetectionFunction::complexSpectralDifference() |
437 { | 489 { |
438 double phaseDeviation; | 490 double phaseDeviation; |
439 double sum; | 491 double sum; |
440 double csd; | 492 double csd; |
441 | 493 |
446 | 498 |
447 // compute phase values from fft output and sum deviations | 499 // compute phase values from fft output and sum deviations |
448 for (int i = 0;i < frameSize;i++) | 500 for (int i = 0;i < frameSize;i++) |
449 { | 501 { |
450 // calculate phase value | 502 // calculate phase value |
451 phase[i] = atan2(complexOut[i][1],complexOut[i][0]); | 503 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
452 | 504 |
453 // calculate magnitude value | 505 // calculate magnitude value |
454 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 506 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow(complexOut[i][1],2)); |
455 | 507 |
456 // phase deviation | 508 // phase deviation |
457 phaseDeviation = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; | 509 phaseDeviation = phase[i] - (2 * prevPhase[i]) + prevPhase2[i]; |
458 | 510 |
459 // calculate complex spectral difference for the current spectral bin | 511 // calculate complex spectral difference for the current spectral bin |
460 csd = sqrt(pow(magSpec[i], 2) + pow(prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos(phaseDeviation)); | 512 csd = sqrt (pow (magSpec[i], 2) + pow (prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos (phaseDeviation)); |
461 | 513 |
462 // add to sum | 514 // add to sum |
463 sum = sum + csd; | 515 sum = sum + csd; |
464 | 516 |
465 // store values for next calculation | 517 // store values for next calculation |
470 | 522 |
471 return sum; | 523 return sum; |
472 } | 524 } |
473 | 525 |
474 //======================================================================= | 526 //======================================================================= |
475 double OnsetDetectionFunction :: complexSpectralDifferenceHWR() | 527 double OnsetDetectionFunction::complexSpectralDifferenceHWR() |
476 { | 528 { |
477 double phaseDeviation; | 529 double phaseDeviation; |
478 double sum; | 530 double sum; |
479 double magnitudeDifference; | 531 double magnitudeDifference; |
480 double csd; | 532 double csd; |
486 | 538 |
487 // compute phase values from fft output and sum deviations | 539 // compute phase values from fft output and sum deviations |
488 for (int i = 0;i < frameSize;i++) | 540 for (int i = 0;i < frameSize;i++) |
489 { | 541 { |
490 // calculate phase value | 542 // calculate phase value |
491 phase[i] = atan2(complexOut[i][1],complexOut[i][0]); | 543 phase[i] = atan2 (complexOut[i][1], complexOut[i][0]); |
492 | 544 |
493 // calculate magnitude value | 545 // calculate magnitude value |
494 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 546 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow(complexOut[i][1],2)); |
495 | 547 |
496 // phase deviation | 548 // phase deviation |
497 phaseDeviation = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; | 549 phaseDeviation = phase[i] - (2 * prevPhase[i]) + prevPhase2[i]; |
498 | 550 |
499 // calculate magnitude difference (real part of Euclidean distance between complex frames) | 551 // calculate magnitude difference (real part of Euclidean distance between complex frames) |
500 magnitudeDifference = magSpec[i] - prevMagSpec[i]; | 552 magnitudeDifference = magSpec[i] - prevMagSpec[i]; |
501 | 553 |
502 // if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification) | 554 // if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification) |
503 if (magnitudeDifference > 0) | 555 if (magnitudeDifference > 0) |
504 { | 556 { |
505 // calculate complex spectral difference for the current spectral bin | 557 // calculate complex spectral difference for the current spectral bin |
506 csd = sqrt(pow(magSpec[i], 2) + pow(prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos(phaseDeviation)); | 558 csd = sqrt (pow (magSpec[i], 2) + pow (prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos (phaseDeviation)); |
507 | 559 |
508 // add to sum | 560 // add to sum |
509 sum = sum + csd; | 561 sum = sum + csd; |
510 } | 562 } |
511 | 563 |
518 return sum; | 570 return sum; |
519 } | 571 } |
520 | 572 |
521 | 573 |
522 //======================================================================= | 574 //======================================================================= |
523 double OnsetDetectionFunction :: highFrequencyContent() | 575 double OnsetDetectionFunction::highFrequencyContent() |
524 { | 576 { |
525 double sum; | 577 double sum; |
578 | |
579 // perform the FFT | |
580 performFFT(); | |
581 | |
582 sum = 0; // initialise sum to zero | |
583 | |
584 // compute phase values from fft output and sum deviations | |
585 for (int i = 0; i < frameSize; i++) | |
586 { | |
587 // calculate magnitude value | |
588 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); | |
589 | |
590 | |
591 sum = sum + (magSpec[i] * ((double) (i+1))); | |
592 | |
593 // store values for next calculation | |
594 prevMagSpec[i] = magSpec[i]; | |
595 } | |
596 | |
597 return sum; | |
598 } | |
599 | |
600 //======================================================================= | |
601 double OnsetDetectionFunction::highFrequencySpectralDifference() | |
602 { | |
603 double sum; | |
604 double mag_diff; | |
526 | 605 |
527 // perform the FFT | 606 // perform the FFT |
528 performFFT(); | 607 performFFT(); |
529 | 608 |
530 sum = 0; // initialise sum to zero | 609 sum = 0; // initialise sum to zero |
531 | 610 |
532 // compute phase values from fft output and sum deviations | 611 // compute phase values from fft output and sum deviations |
533 for (int i = 0;i < frameSize;i++) | 612 for (int i = 0;i < frameSize;i++) |
534 { | 613 { |
535 // calculate magnitude value | 614 // calculate magnitude value |
536 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 615 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
537 | 616 |
538 | 617 // calculate difference |
539 sum = sum + (magSpec[i]*((double) (i+1))); | 618 mag_diff = magSpec[i] - prevMagSpec[i]; |
619 | |
620 if (mag_diff < 0) | |
621 { | |
622 mag_diff = -mag_diff; | |
623 } | |
624 | |
625 sum = sum + (mag_diff * ((double) (i+1))); | |
540 | 626 |
541 // store values for next calculation | 627 // store values for next calculation |
542 prevMagSpec[i] = magSpec[i]; | 628 prevMagSpec[i] = magSpec[i]; |
543 } | 629 } |
544 | 630 |
545 return sum; | 631 return sum; |
546 } | 632 } |
547 | 633 |
548 //======================================================================= | 634 //======================================================================= |
549 double OnsetDetectionFunction :: highFrequencySpectralDifference() | 635 double OnsetDetectionFunction::highFrequencySpectralDifferenceHWR() |
550 { | 636 { |
551 double sum; | 637 double sum; |
552 double mag_diff; | 638 double mag_diff; |
553 | 639 |
554 // perform the FFT | 640 // perform the FFT |
558 | 644 |
559 // compute phase values from fft output and sum deviations | 645 // compute phase values from fft output and sum deviations |
560 for (int i = 0;i < frameSize;i++) | 646 for (int i = 0;i < frameSize;i++) |
561 { | 647 { |
562 // calculate magnitude value | 648 // calculate magnitude value |
563 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | 649 magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2)); |
564 | 650 |
565 // calculate difference | 651 // calculate difference |
566 mag_diff = magSpec[i] - prevMagSpec[i]; | 652 mag_diff = magSpec[i] - prevMagSpec[i]; |
567 | 653 |
568 if (mag_diff < 0) | |
569 { | |
570 mag_diff = -mag_diff; | |
571 } | |
572 | |
573 sum = sum + (mag_diff*((double) (i+1))); | |
574 | |
575 // store values for next calculation | |
576 prevMagSpec[i] = magSpec[i]; | |
577 } | |
578 | |
579 return sum; | |
580 } | |
581 | |
582 //======================================================================= | |
583 double OnsetDetectionFunction :: highFrequencySpectralDifferenceHWR() | |
584 { | |
585 double sum; | |
586 double mag_diff; | |
587 | |
588 // perform the FFT | |
589 performFFT(); | |
590 | |
591 sum = 0; // initialise sum to zero | |
592 | |
593 // compute phase values from fft output and sum deviations | |
594 for (int i = 0;i < frameSize;i++) | |
595 { | |
596 // calculate magnitude value | |
597 magSpec[i] = sqrt(pow(complexOut[i][0],2) + pow(complexOut[i][1],2)); | |
598 | |
599 // calculate difference | |
600 mag_diff = magSpec[i] - prevMagSpec[i]; | |
601 | |
602 if (mag_diff > 0) | 654 if (mag_diff > 0) |
603 { | 655 { |
604 sum = sum + (mag_diff*((double) (i+1))); | 656 sum = sum + (mag_diff * ((double) (i+1))); |
605 } | 657 } |
606 | 658 |
607 // store values for next calculation | 659 // store values for next calculation |
608 prevMagSpec[i] = magSpec[i]; | 660 prevMagSpec[i] = magSpec[i]; |
609 } | 661 } |
615 //////////////////////////////////////////////////////////////////////////////////////////////// | 667 //////////////////////////////////////////////////////////////////////////////////////////////// |
616 //////////////////////////////////////////////////////////////////////////////////////////////// | 668 //////////////////////////////////////////////////////////////////////////////////////////////// |
617 ////////////////////////////// Methods to Calculate Windows //////////////////////////////////// | 669 ////////////////////////////// Methods to Calculate Windows //////////////////////////////////// |
618 | 670 |
619 //======================================================================= | 671 //======================================================================= |
620 void OnsetDetectionFunction :: calculateHanningWindow() | 672 void OnsetDetectionFunction::calculateHanningWindow() |
621 { | 673 { |
622 double N; // variable to store framesize minus 1 | 674 double N; // variable to store framesize minus 1 |
623 | 675 |
624 N = (double) (frameSize-1); // framesize minus 1 | 676 N = (double) (frameSize-1); // framesize minus 1 |
625 | 677 |
626 // Hanning window calculation | 678 // Hanning window calculation |
627 for (int n = 0;n < frameSize;n++) | 679 for (int n = 0; n < frameSize; n++) |
628 { | 680 { |
629 window[n] = 0.5*(1-cos(2*pi*(n/N))); | 681 window[n] = 0.5 * (1 - cos (2 * pi * (n / N))); |
630 } | 682 } |
631 } | 683 } |
632 | 684 |
633 //======================================================================= | 685 //======================================================================= |
634 void OnsetDetectionFunction :: calclulateHammingWindow() | 686 void OnsetDetectionFunction::calclulateHammingWindow() |
635 { | 687 { |
636 double N; // variable to store framesize minus 1 | 688 double N; // variable to store framesize minus 1 |
637 double n_val; // double version of index 'n' | 689 double n_val; // double version of index 'n' |
638 | 690 |
639 N = (double) (frameSize-1); // framesize minus 1 | 691 N = (double) (frameSize-1); // framesize minus 1 |
640 n_val = 0; | 692 n_val = 0; |
641 | 693 |
642 // Hamming window calculation | 694 // Hamming window calculation |
643 for (int n = 0;n < frameSize;n++) | 695 for (int n = 0;n < frameSize;n++) |
644 { | 696 { |
645 window[n] = 0.54 - (0.46*cos(2*pi*(n_val/N))); | 697 window[n] = 0.54 - (0.46 * cos (2 * pi * (n_val/N))); |
646 n_val = n_val+1; | 698 n_val = n_val+1; |
647 } | 699 } |
648 } | 700 } |
649 | 701 |
650 //======================================================================= | 702 //======================================================================= |
651 void OnsetDetectionFunction :: calculateBlackmanWindow() | 703 void OnsetDetectionFunction::calculateBlackmanWindow() |
652 { | 704 { |
653 double N; // variable to store framesize minus 1 | 705 double N; // variable to store framesize minus 1 |
654 double n_val; // double version of index 'n' | 706 double n_val; // double version of index 'n' |
655 | 707 |
656 N = (double) (frameSize-1); // framesize minus 1 | 708 N = (double) (frameSize-1); // framesize minus 1 |
663 n_val = n_val+1; | 715 n_val = n_val+1; |
664 } | 716 } |
665 } | 717 } |
666 | 718 |
667 //======================================================================= | 719 //======================================================================= |
668 void OnsetDetectionFunction :: calculateTukeyWindow() | 720 void OnsetDetectionFunction::calculateTukeyWindow() |
669 { | 721 { |
670 double N; // variable to store framesize minus 1 | 722 double N; // variable to store framesize minus 1 |
671 double n_val; // double version of index 'n' | 723 double n_val; // double version of index 'n' |
672 double alpha; // alpha [default value = 0.5]; | 724 double alpha; // alpha [default value = 0.5]; |
673 | 725 |
698 } | 750 } |
699 | 751 |
700 } | 752 } |
701 | 753 |
702 //======================================================================= | 754 //======================================================================= |
703 void OnsetDetectionFunction :: calculateRectangularWindow() | 755 void OnsetDetectionFunction::calculateRectangularWindow() |
704 { | 756 { |
705 // Rectangular window calculation | 757 // Rectangular window calculation |
706 for (int n = 0;n < frameSize;n++) | 758 for (int n = 0;n < frameSize;n++) |
707 { | 759 { |
708 window[n] = 1.0; | 760 window[n] = 1.0; |
709 } | 761 } |
710 } | 762 } |
711 | |
712 | |
713 | 763 |
714 //////////////////////////////////////////////////////////////////////////////////////////////// | 764 //////////////////////////////////////////////////////////////////////////////////////////////// |
715 //////////////////////////////////////////////////////////////////////////////////////////////// | 765 //////////////////////////////////////////////////////////////////////////////////////////////// |
716 ///////////////////////////////// Other Handy Methods ////////////////////////////////////////// | 766 ///////////////////////////////// Other Handy Methods ////////////////////////////////////////// |
717 | 767 |
718 //======================================================================= | 768 //======================================================================= |
719 double OnsetDetectionFunction :: princarg(double phaseVal) | 769 double OnsetDetectionFunction::princarg(double phaseVal) |
720 { | 770 { |
721 // if phase value is less than or equal to -pi then add 2*pi | 771 // if phase value is less than or equal to -pi then add 2*pi |
722 while (phaseVal <= (-pi)) | 772 while (phaseVal <= (-pi)) |
723 { | 773 { |
724 phaseVal = phaseVal + (2*pi); | 774 phaseVal = phaseVal + (2 * pi); |
725 } | 775 } |
726 | 776 |
727 // if phase value is larger than pi, then subtract 2*pi | 777 // if phase value is larger than pi, then subtract 2*pi |
728 while (phaseVal > pi) | 778 while (phaseVal > pi) |
729 { | 779 { |
730 phaseVal = phaseVal - (2*pi); | 780 phaseVal = phaseVal - (2 * pi); |
731 } | 781 } |
732 | 782 |
733 return phaseVal; | 783 return phaseVal; |
734 } | 784 } |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | |
741 | |
742 | |
743 | |
744 | |
745 | |
746 | |
747 |