[awhitening] use shortest length available (closes gh-216)
[aubio.git] / src / spectral / awhitening.c
1 /*
2  * Copyright (C) 2003-2015 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 it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * aubio is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * aubio.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "aubio_priv.h"
22 #include "fvec.h"
23 #include "cvec.h"
24 #include "mathutils.h"
25 #include "spectral/awhitening.h"
26
27 #define aubio_spectral_whitening_default_relax_time   250   // in seconds, between 22 and 446
28 #define aubio_spectral_whitening_default_decay        0.001 // -60dB attenuation
29 #define aubio_spectral_whitening_default_floor        1.e-4 // from 1.e-6 to .2
30
31 /** structure to store object state */
32 struct _aubio_spectral_whitening_t {
33   uint_t buf_size;
34   uint_t hop_size;
35   uint_t samplerate;
36   smpl_t relax_time;
37   smpl_t r_decay;
38   smpl_t floor;
39   fvec_t *peak_values;
40 };
41
42 void
43 aubio_spectral_whitening_do (aubio_spectral_whitening_t * o, cvec_t * fftgrain)
44 {
45   uint_t i = 0;
46   uint_t length = MIN(fftgrain->length, o->peak_values->length);
47   for (i = 0; i < length; i++) {
48     smpl_t tmp = MAX(o->r_decay * o->peak_values->data[i], o->floor);
49     o->peak_values->data[i] = MAX(fftgrain->norm[i], tmp);
50     fftgrain->norm[i] /= o->peak_values->data[i];
51   }
52 }
53
54 aubio_spectral_whitening_t *
55 new_aubio_spectral_whitening (uint_t buf_size, uint_t hop_size, uint_t samplerate)
56 {
57   aubio_spectral_whitening_t *o = AUBIO_NEW (aubio_spectral_whitening_t);
58   if ((sint_t)buf_size < 1) {
59     AUBIO_ERR("spectral_whitening: got buffer_size %d, but can not be < 1\n", buf_size);
60     goto beach;
61   } else if ((sint_t)hop_size < 1) {
62     AUBIO_ERR("spectral_whitening: got hop_size %d, but can not be < 1\n", hop_size);
63     goto beach;
64   } else if ((sint_t)samplerate < 1) {
65     AUBIO_ERR("spectral_whitening: got samplerate %d, but can not be < 1\n", samplerate);
66     goto beach;
67   }
68   o->peak_values = new_fvec (buf_size / 2 + 1);
69   o->buf_size = buf_size;
70   o->hop_size = hop_size;
71   o->samplerate = samplerate;
72   o->floor = aubio_spectral_whitening_default_floor;
73   aubio_spectral_whitening_set_relax_time (o, aubio_spectral_whitening_default_relax_time);
74   aubio_spectral_whitening_reset (o);
75   return o;
76
77 beach:
78   AUBIO_FREE(o);
79   return NULL;
80 }
81
82 uint_t
83 aubio_spectral_whitening_set_relax_time (aubio_spectral_whitening_t * o, smpl_t relax_time)
84 {
85   o->relax_time = relax_time;
86   o->r_decay = POW (aubio_spectral_whitening_default_decay,
87       (o->hop_size / (float) o->samplerate) / o->relax_time);
88   return AUBIO_OK;
89 }
90
91 smpl_t
92 aubio_spectral_whitening_get_relax_time (aubio_spectral_whitening_t * o)
93 {
94   return o->relax_time;
95 }
96
97 uint_t
98 aubio_spectral_whitening_set_floor (aubio_spectral_whitening_t *o, smpl_t floor)
99 {
100   o->floor = floor;
101   return AUBIO_OK;
102 }
103
104 smpl_t aubio_spectral_whitening_get_floor (aubio_spectral_whitening_t *o)
105 {
106   return o->floor;
107 }
108
109 void
110 aubio_spectral_whitening_reset (aubio_spectral_whitening_t * o)
111 {
112   /* cover the case n == 0. */
113   fvec_set_all (o->peak_values, o->floor);
114 }
115
116 void
117 del_aubio_spectral_whitening (aubio_spectral_whitening_t * o)
118 {
119   del_fvec (o->peak_values);
120   AUBIO_FREE (o);
121 }