wscript: With --enable-$x, the existence of $x should be mandatory
[aubio.git] / src / mathutils.c
1 /*
2   Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
3
4   This file is part of aubio.
5
6   aubio is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   aubio is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 /* see in mathutils.h for doc */
22
23 #include "aubio_priv.h"
24 #include "fvec.h"
25 #include "mathutils.h"
26 #include "musicutils.h"
27 #include "config.h"
28
29
30 /** Window types */
31 typedef enum
32 {
33   aubio_win_rectangle,
34   aubio_win_hamming,
35   aubio_win_hanning,
36   aubio_win_hanningz,
37   aubio_win_blackman,
38   aubio_win_blackman_harris,
39   aubio_win_gaussian,
40   aubio_win_welch,
41   aubio_win_parzen,
42   aubio_win_default = aubio_win_hanningz,
43 } aubio_window_type;
44
45 fvec_t *
46 new_aubio_window (char_t * window_type, uint_t length)
47 {
48   fvec_t * win = new_fvec (length);
49   fvec_set_window (win, window_type);
50   return win;
51 }
52
53 uint_t fvec_set_window (fvec_t *win, char_t *window_type) {
54   smpl_t * w = win->data;
55   uint_t i, size = win->length;
56   aubio_window_type wintype;
57   if (window_type == NULL) {
58       AUBIO_ERR ("window type can not be null.\n");
59       return 1;
60   } else if (strcmp (window_type, "rectangle") == 0)
61       wintype = aubio_win_rectangle;
62   else if (strcmp (window_type, "hamming") == 0)
63       wintype = aubio_win_hamming;
64   else if (strcmp (window_type, "hanning") == 0)
65       wintype = aubio_win_hanning;
66   else if (strcmp (window_type, "hanningz") == 0)
67       wintype = aubio_win_hanningz;
68   else if (strcmp (window_type, "blackman") == 0)
69       wintype = aubio_win_blackman;
70   else if (strcmp (window_type, "blackman_harris") == 0)
71       wintype = aubio_win_blackman_harris;
72   else if (strcmp (window_type, "gaussian") == 0)
73       wintype = aubio_win_gaussian;
74   else if (strcmp (window_type, "welch") == 0)
75       wintype = aubio_win_welch;
76   else if (strcmp (window_type, "parzen") == 0)
77       wintype = aubio_win_parzen;
78   else if (strcmp (window_type, "default") == 0)
79       wintype = aubio_win_default;
80   else {
81       AUBIO_ERR ("unknown window type `%s`.\n", window_type);
82       return 1;
83   }
84   switch(wintype) {
85     case aubio_win_rectangle:
86       for (i=0;i<size;i++)
87         w[i] = 0.5;
88       break;
89     case aubio_win_hamming:
90       for (i=0;i<size;i++)
91         w[i] = 0.54 - 0.46 * COS(TWO_PI * i / (size));
92       break;
93     case aubio_win_hanning:
94       for (i=0;i<size;i++)
95         w[i] = 0.5 - (0.5 * COS(TWO_PI * i / (size)));
96       break;
97     case aubio_win_hanningz:
98       for (i=0;i<size;i++)
99         w[i] = 0.5 * (1.0 - COS(TWO_PI * i / (size)));
100       break;
101     case aubio_win_blackman:
102       for (i=0;i<size;i++)
103         w[i] = 0.42
104           - 0.50 * COS(    TWO_PI*i/(size-1.0))
105           + 0.08 * COS(2.0*TWO_PI*i/(size-1.0));
106       break;
107     case aubio_win_blackman_harris:
108       for (i=0;i<size;i++)
109         w[i] = 0.35875
110           - 0.48829 * COS(    TWO_PI*i/(size-1.0))
111           + 0.14128 * COS(2.0*TWO_PI*i/(size-1.0))
112           - 0.01168 * COS(3.0*TWO_PI*i/(size-1.0));
113       break;
114     case aubio_win_gaussian:
115       {
116         lsmp_t a, b, c = 0.5;
117         uint_t n;
118         for (n = 0; n < size; n++)
119         {
120           a = (n-c*(size-1))/(SQR(c)*(size-1));
121           b = -c*SQR(a);
122           w[n] = EXP(b);
123         }
124       }
125       break;
126     case aubio_win_welch:
127       for (i=0;i<size;i++)
128         w[i] = 1.0 - SQR((2.*i-size)/(size+1.0));
129       break;
130     case aubio_win_parzen:
131       for (i=0;i<size;i++)
132         w[i] = 1.0 - ABS((2.*i-size)/(size+1.0));
133       break;
134     default:
135       break;
136   }
137   return 0;
138 }
139
140 smpl_t
141 aubio_unwrap2pi (smpl_t phase)
142 {
143   /* mod(phase+pi,-2pi)+pi */
144   return phase + TWO_PI * (1. + FLOOR (-(phase + PI) / TWO_PI));
145 }
146
147 smpl_t
148 fvec_mean (fvec_t * s)
149 {
150   uint_t j;
151   smpl_t tmp = 0.0;
152   for (j = 0; j < s->length; j++) {
153     tmp += s->data[j];
154   }
155   return tmp / (smpl_t) (s->length);
156 }
157
158 smpl_t
159 fvec_sum (fvec_t * s)
160 {
161   uint_t j;
162   smpl_t tmp = 0.0;
163   for (j = 0; j < s->length; j++) {
164     tmp += s->data[j];
165   }
166   return tmp;
167 }
168
169 smpl_t
170 fvec_max (fvec_t * s)
171 {
172   uint_t j;
173   smpl_t tmp = 0.0;
174   for (j = 0; j < s->length; j++) {
175     tmp = (tmp > s->data[j]) ? tmp : s->data[j];
176   }
177   return tmp;
178 }
179
180 smpl_t
181 fvec_min (fvec_t * s)
182 {
183   uint_t j;
184   smpl_t tmp = s->data[0];
185   for (j = 0; j < s->length; j++) {
186     tmp = (tmp < s->data[j]) ? tmp : s->data[j];
187   }
188   return tmp;
189 }
190
191 uint_t
192 fvec_min_elem (fvec_t * s)
193 {
194   uint_t j, pos = 0.;
195   smpl_t tmp = s->data[0];
196   for (j = 0; j < s->length; j++) {
197     pos = (tmp < s->data[j]) ? pos : j;
198     tmp = (tmp < s->data[j]) ? tmp : s->data[j];
199   }
200   return pos;
201 }
202
203 uint_t
204 fvec_max_elem (fvec_t * s)
205 {
206   uint_t j, pos = 0;
207   smpl_t tmp = 0.0;
208   for (j = 0; j < s->length; j++) {
209     pos = (tmp > s->data[j]) ? pos : j;
210     tmp = (tmp > s->data[j]) ? tmp : s->data[j];
211   }
212   return pos;
213 }
214
215 void
216 fvec_shift (fvec_t * s)
217 {
218   uint_t j;
219   for (j = 0; j < s->length / 2; j++) {
220     ELEM_SWAP (s->data[j], s->data[j + s->length / 2]);
221   }
222 }
223
224 smpl_t
225 fvec_local_energy (fvec_t * f)
226 {
227   smpl_t energy = 0.;
228   uint_t j;
229   for (j = 0; j < f->length; j++) {
230     energy += SQR (f->data[j]);
231   }
232   return energy / f->length;
233 }
234
235 smpl_t
236 fvec_local_hfc (fvec_t * v)
237 {
238   smpl_t hfc = 0.;
239   uint_t j;
240   for (j = 0; j < v->length; j++) {
241     hfc += (j + 1) * v->data[j];
242   }
243   return hfc;
244 }
245
246 void
247 fvec_min_removal (fvec_t * v)
248 {
249   smpl_t v_min = fvec_min (v);
250   fvec_add (v,  - v_min );
251 }
252
253 smpl_t
254 fvec_alpha_norm (fvec_t * o, smpl_t alpha)
255 {
256   uint_t j;
257   smpl_t tmp = 0.;
258   for (j = 0; j < o->length; j++) {
259     tmp += POW (ABS (o->data[j]), alpha);
260   }
261   return POW (tmp / o->length, 1. / alpha);
262 }
263
264 void
265 fvec_alpha_normalise (fvec_t * o, smpl_t alpha)
266 {
267   uint_t j;
268   smpl_t norm = fvec_alpha_norm (o, alpha);
269   for (j = 0; j < o->length; j++) {
270     o->data[j] /= norm;
271   }
272 }
273
274 void
275 fvec_add (fvec_t * o, smpl_t val)
276 {
277   uint_t j;
278   for (j = 0; j < o->length; j++) {
279     o->data[j] += val;
280   }
281 }
282
283 void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp,
284     uint_t post, uint_t pre) {
285   uint_t length = vec->length, j;
286   for (j=0;j<length;j++) {
287     vec->data[j] -= fvec_moving_thres(vec, tmp, post, pre, j);
288   }
289 }
290
291 smpl_t
292 fvec_moving_thres (fvec_t * vec, fvec_t * tmpvec,
293     uint_t post, uint_t pre, uint_t pos)
294 {
295   uint_t k;
296   smpl_t *medar = (smpl_t *) tmpvec->data;
297   uint_t win_length = post + pre + 1;
298   uint_t length = vec->length;
299   /* post part of the buffer does not exist */
300   if (pos < post + 1) {
301     for (k = 0; k < post + 1 - pos; k++)
302       medar[k] = 0.;            /* 0-padding at the beginning */
303     for (k = post + 1 - pos; k < win_length; k++)
304       medar[k] = vec->data[k + pos - post];
305     /* the buffer is fully defined */
306   } else if (pos + pre < length) {
307     for (k = 0; k < win_length; k++)
308       medar[k] = vec->data[k + pos - post];
309     /* pre part of the buffer does not exist */
310   } else {
311     for (k = 0; k < length - pos + post; k++)
312       medar[k] = vec->data[k + pos - post];
313     for (k = length - pos + post; k < win_length; k++)
314       medar[k] = 0.;            /* 0-padding at the end */
315   }
316   return fvec_median (tmpvec);
317 }
318
319 smpl_t fvec_median (fvec_t * input) {
320   uint_t n = input->length;
321   smpl_t * arr = (smpl_t *) input->data;
322   uint_t low, high ;
323   uint_t median;
324   uint_t middle, ll, hh;
325
326   low = 0 ; high = n-1 ; median = (low + high) / 2;
327   for (;;) {
328     if (high <= low) /* One element only */
329       return arr[median] ;
330
331     if (high == low + 1) {  /* Two elements only */
332       if (arr[low] > arr[high])
333         ELEM_SWAP(arr[low], arr[high]) ;
334       return arr[median] ;
335     }
336
337     /* Find median of low, middle and high items; swap into position low */
338     middle = (low + high) / 2;
339     if (arr[middle] > arr[high])    ELEM_SWAP(arr[middle], arr[high]);
340     if (arr[low]    > arr[high])    ELEM_SWAP(arr[low],    arr[high]);
341     if (arr[middle] > arr[low])     ELEM_SWAP(arr[middle], arr[low]) ;
342
343     /* Swap low item (now in position middle) into position (low+1) */
344     ELEM_SWAP(arr[middle], arr[low+1]) ;
345
346     /* Nibble from each end towards middle, swapping items when stuck */
347     ll = low + 1;
348     hh = high;
349     for (;;) {
350       do ll++; while (arr[low] > arr[ll]) ;
351       do hh--; while (arr[hh]  > arr[low]) ;
352
353       if (hh < ll)
354         break;
355
356       ELEM_SWAP(arr[ll], arr[hh]) ;
357     }
358
359     /* Swap middle item (in position low) back into correct position */
360     ELEM_SWAP(arr[low], arr[hh]) ;
361
362     /* Re-set active partition */
363     if (hh <= median)
364       low = ll;
365     if (hh >= median)
366       high = hh - 1;
367   }
368 }
369
370 smpl_t fvec_quadint (fvec_t * x, uint_t pos) {
371   smpl_t s0, s1, s2;
372   uint_t x0 = (pos < 1) ? pos : pos - 1;
373   uint_t x2 = (pos + 1 < x->length) ? pos + 1 : pos;
374   if (x0 == pos) return (x->data[pos] <= x->data[x2]) ? pos : x2;
375   if (x2 == pos) return (x->data[pos] <= x->data[x0]) ? pos : x0;
376   s0 = x->data[x0];
377   s1 = x->data[pos];
378   s2 = x->data[x2];
379   return pos + 0.5 * (s2 - s0 ) / (s2 - 2.* s1 + s0);
380 }
381
382 smpl_t fvec_quadratic_peak_pos (fvec_t * x, uint_t pos) {
383   smpl_t s0, s1, s2;
384   uint_t x0 = (pos < 1) ? pos : pos - 1;
385   uint_t x2 = (pos + 1 < x->length) ? pos + 1 : pos;
386   if (x0 == pos) return (x->data[pos] <= x->data[x2]) ? pos : x2;
387   if (x2 == pos) return (x->data[pos] <= x->data[x0]) ? pos : x0;
388   s0 = x->data[x0];
389   s1 = x->data[pos];
390   s2 = x->data[x2];
391   return pos + 0.5 * (s0 - s2 ) / (s0 - 2.* s1 + s2);
392 }
393
394 uint_t fvec_peakpick(fvec_t * onset, uint_t pos) {
395   uint_t tmp=0;
396   tmp = (onset->data[pos] > onset->data[pos-1]
397       &&  onset->data[pos] > onset->data[pos+1]
398       &&  onset->data[pos] > 0.);
399   return tmp;
400 }
401
402 smpl_t
403 aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf)
404 {
405   smpl_t tmp =
406       s0 + (pf / 2.) * (pf * (s0 - 2. * s1 + s2) - 3. * s0 + 4. * s1 - s2);
407   return tmp;
408 }
409
410 smpl_t
411 aubio_freqtomidi (smpl_t freq)
412 {
413   if (freq < 2. || freq > 100000.) return 0.; // avoid nans and infs
414   /* log(freq/A-2)/log(2) */
415   smpl_t midi = freq / 6.875;
416   midi = LOG (midi) / 0.69314718055995;
417   midi *= 12;
418   midi -= 3;
419   return midi;
420 }
421
422 smpl_t
423 aubio_miditofreq (smpl_t midi)
424 {
425   if (midi > 140.) return 0.; // avoid infs
426   smpl_t freq = (midi + 3.) / 12.;
427   freq = EXP (freq * 0.69314718055995);
428   freq *= 6.875;
429   return freq;
430 }
431
432 smpl_t
433 aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize)
434 {
435   smpl_t freq = samplerate / fftsize;
436   return freq * MAX(bin, 0);
437 }
438
439 smpl_t
440 aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize)
441 {
442   smpl_t midi = aubio_bintofreq (bin, samplerate, fftsize);
443   return aubio_freqtomidi (midi);
444 }
445
446 smpl_t
447 aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize)
448 {
449   smpl_t bin = fftsize / samplerate;
450   return MAX(freq, 0) * bin;
451 }
452
453 smpl_t
454 aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize)
455 {
456   smpl_t freq = aubio_miditofreq (midi);
457   return aubio_freqtobin (freq, samplerate, fftsize);
458 }
459
460 uint_t
461 aubio_is_power_of_two (uint_t a)
462 {
463   if ((a & (a - 1)) == 0) {
464     return 1;
465   } else {
466     return 0;
467   }
468 }
469
470 uint_t
471 aubio_next_power_of_two (uint_t a)
472 {
473   uint_t i = 1;
474   while (i < a) i <<= 1;
475   return i;
476 }
477
478 smpl_t
479 aubio_db_spl (fvec_t * o)
480 {
481   return 10. * LOG10 (fvec_local_energy (o));
482 }
483
484 uint_t
485 aubio_silence_detection (fvec_t * o, smpl_t threshold)
486 {
487   return (aubio_db_spl (o) < threshold);
488 }
489
490 smpl_t
491 aubio_level_detection (fvec_t * o, smpl_t threshold)
492 {
493   smpl_t db_spl = aubio_db_spl (o);
494   if (db_spl < threshold) {
495     return 1.;
496   } else {
497     return db_spl;
498   }
499 }
500
501 smpl_t
502 aubio_zero_crossing_rate (fvec_t * input)
503 {
504   uint_t j;
505   uint_t zcr = 0;
506   for (j = 1; j < input->length; j++) {
507     // previous was strictly negative
508     if (input->data[j - 1] < 0.) {
509       // current is positive or null
510       if (input->data[j] >= 0.) {
511         zcr += 1;
512       }
513       // previous was positive or null
514     } else {
515       // current is strictly negative
516       if (input->data[j] < 0.) {
517         zcr += 1;
518       }
519     }
520   }
521   return zcr / (smpl_t) input->length;
522 }
523
524 void
525 aubio_autocorr (fvec_t * input, fvec_t * output)
526 {
527   uint_t i, j, length = input->length;
528   smpl_t *data, *acf;
529   smpl_t tmp = 0;
530   data = input->data;
531   acf = output->data;
532   for (i = 0; i < length; i++) {
533     tmp = 0.;
534     for (j = i; j < length; j++) {
535       tmp += data[j - i] * data[j];
536     }
537     acf[i] = tmp / (smpl_t) (length - i);
538   }
539 }
540
541 void
542 aubio_cleanup (void)
543 {
544 #ifdef HAVE_FFTW3F
545   fftwf_cleanup ();
546 #else
547 #ifdef HAVE_FFTW3
548   fftw_cleanup ();
549 #endif
550 #endif
551 }