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