source: src/onsetdetection.c @ 48b847b

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 48b847b was b377d04, checked in by Paul Brossier <piem@altern.org>, 18 years ago

remove unused parameter warnings with UNUSED
remove unused parameter warnings with UNUSED

  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2   Copyright (C) 2003 Paul Brossier
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18*/
19
20#include "aubio_priv.h"
21#include "sample.h"
22#include "fft.h"
23#include "mathutils.h"
24#include "hist.h"
25#include "onsetdetection.h"
26
27
28/** structure to store object state */
29struct _aubio_onsetdetection_t {
30  aubio_onsetdetection_type type; /**< onset detection type */
31  /** Pointer to aubio_onsetdetection_<type> function */
32  void (*funcpointer)(aubio_onsetdetection_t *o,
33    cvec_t * fftgrain, fvec_t * onset);
34  smpl_t threshold;      /**< minimum norm threshold for phase and specdiff */
35  fvec_t *oldmag;        /**< previous norm vector */
36  fft_data_t *meas;      /**< current onset detection measure complex vector */
37  fvec_t *dev1 ;         /**< current onset detection measure vector */
38  fvec_t *theta1;        /**< previous phase vector, one frame behind */
39  fvec_t *theta2;        /**< previous phase vector, two frames behind */
40  aubio_hist_t * histog; /**< histogram */
41};
42
43
44/* Energy based onset detection function */
45void aubio_onsetdetection_energy  (aubio_onsetdetection_t *o UNUSED,
46                cvec_t * fftgrain, fvec_t * onset) {
47        uint_t i,j;
48        for (i=0;i<fftgrain->channels;i++) {
49                onset->data[i][0] = 0.;
50                for (j=0;j<fftgrain->length;j++) {
51                        onset->data[i][0] += SQR(fftgrain->norm[i][j]);
52                }
53        }
54}
55
56/* High Frequency Content onset detection function */
57void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o UNUSED,
58    cvec_t * fftgrain, fvec_t * onset){
59        uint_t i,j;
60        for (i=0;i<fftgrain->channels;i++) {
61                onset->data[i][0] = 0.;
62                for (j=0;j<fftgrain->length;j++) {
63                        onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
64                }
65        }
66}
67
68
69/* Complex Domain Method onset detection function */
70void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
71        uint_t i, j;
72        uint_t nbins = fftgrain->length;
73        for (i=0;i<fftgrain->channels; i++)     {
74                onset->data[i][0] = 0.;
75                for (j=0;j<nbins; j++)  {
76                        o->dev1->data[i][j]      = aubio_unwrap2pi(
77                                        fftgrain->phas[i][j]
78                                        -2.0*o->theta1->data[i][j]+
79                                        o->theta2->data[i][j]);
80#ifdef HAVE_COMPLEX_H
81                        o->meas[j] = fftgrain->norm[i][j]*CEXPC(I*o->dev1->data[i][j]);
82                        /* sum on all bins */
83                        onset->data[i][0]                += //(fftgrain->norm[i][j]);
84                                        SQRT(SQR( REAL(o->oldmag->data[i][j]-o->meas[j]) )
85                                                +  SQR( IMAG(o->oldmag->data[i][j]-o->meas[j]) )
86                                                );
87#else
88                        o->meas[j]             = (fftgrain->norm[i][j])*COS(o->dev1->data[i][j]);
89                        o->meas[(nbins-1)*2-j] = (fftgrain->norm[i][j])*SIN(o->dev1->data[i][j]);
90                        /* sum on all bins */
91                        onset->data[i][0]                += //(fftgrain->norm[i][j]);
92                                        SQRT(SQR( (o->oldmag->data[i][j]-o->meas[j]) )
93                                                +  SQR( (-o->meas[(nbins-1)*2-j]) )
94                                                );
95#endif
96                        /* swap old phase data (need to remember 2 frames behind)*/
97                        o->theta2->data[i][j] = o->theta1->data[i][j];
98                        o->theta1->data[i][j] = fftgrain->phas[i][j];
99                        /* swap old magnitude data (1 frame is enough) */
100                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
101                }
102        }
103}
104
105
106/* Phase Based Method onset detection function */
107void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, 
108                cvec_t * fftgrain, fvec_t * onset){
109        uint_t i, j;
110        uint_t nbins = fftgrain->length;
111        for (i=0;i<fftgrain->channels; i++)     {
112                onset->data[i][0] = 0.0f;
113                o->dev1->data[i][0]=0.;
114                for ( j=0;j<nbins; j++ )        {
115                        o->dev1->data[i][j] = 
116                                aubio_unwrap2pi(
117                                                fftgrain->phas[i][j]
118                                                -2.0*o->theta1->data[i][j]
119                                                +o->theta2->data[i][j]);
120                        if ( o->threshold < fftgrain->norm[i][j] )
121                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
122                        else 
123                                o->dev1->data[i][j] = 0.0f;
124                        /* keep a track of the past frames */
125                        o->theta2->data[i][j] = o->theta1->data[i][j];
126                        o->theta1->data[i][j] = fftgrain->phas[i][j];
127                }
128                /* apply o->histogram */
129                aubio_hist_dyn_notnull(o->histog,o->dev1);
130                /* weight it */
131                aubio_hist_weigth(o->histog);
132                /* its mean is the result */
133                onset->data[i][0] = aubio_hist_mean(o->histog); 
134                //onset->data[i][0] = vec_mean(o->dev1);
135        }
136}
137
138/* Spectral difference method onset detection function */
139void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
140                cvec_t * fftgrain, fvec_t * onset){
141        uint_t i, j;
142        uint_t nbins = fftgrain->length;
143        for (i=0;i<fftgrain->channels; i++)     {
144                onset->data[i][0] = 0.0f;
145                for (j=0;j<nbins; j++)  {
146                        o->dev1->data[i][j] = SQRT(
147                                        ABS(SQR( fftgrain->norm[i][j])
148                                                - SQR(o->oldmag->data[i][j])));
149                        if (o->threshold < fftgrain->norm[i][j] )
150                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
151                        else 
152                                o->dev1->data[i][j] = 0.0f;
153                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
154                }
155
156                /* apply o->histogram (act somewhat as a low pass on the
157                 * overall function)*/
158                aubio_hist_dyn_notnull(o->histog,o->dev1);
159                /* weight it */
160                aubio_hist_weigth(o->histog);
161                /* its mean is the result */
162                onset->data[i][0] = aubio_hist_mean(o->histog); 
163
164        }
165}
166
167/* Kullback Liebler onset detection function
168 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
169 * negative (1.+) and infinite values (+1.e-10) */
170void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
171        uint_t i,j;
172        for (i=0;i<fftgrain->channels;i++) {
173                onset->data[i][0] = 0.;
174                for (j=0;j<fftgrain->length;j++) {
175                        onset->data[i][0] += fftgrain->norm[i][j]
176                                *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
177                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
178                }
179                if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
180        }
181}
182
183/* Modified Kullback Liebler onset detection function
184 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
185 * negative (1.+) and infinite values (+1.e-10) */
186void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
187        uint_t i,j;
188        for (i=0;i<fftgrain->channels;i++) {
189                onset->data[i][0] = 0.;
190                for (j=0;j<fftgrain->length;j++) {
191                        onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
192                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
193                }
194                if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
195        }
196}
197
198/* Generic function pointing to the choosen one */
199void 
200aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain, 
201                fvec_t * onset) {
202        o->funcpointer(o,fftgrain,onset);
203}
204
205/* Allocate memory for an onset detection
206 * depending on the choosen type, allocate memory as needed
207 */
208aubio_onsetdetection_t * 
209new_aubio_onsetdetection (aubio_onsetdetection_type type, 
210                uint_t size, uint_t channels){
211        aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
212        uint_t rsize = size/2+1;
213  uint_t i;
214        switch(type) {
215                /* for both energy and hfc, only fftgrain->norm is required */
216                case aubio_onset_energy: 
217                        break;
218                case aubio_onset_hfc:
219                        break;
220                /* the other approaches will need some more memory spaces */
221                case aubio_onset_complex:
222                        o->oldmag = new_fvec(rsize,channels);
223                        /** bug: must be complex array */
224                        o->meas = AUBIO_ARRAY(fft_data_t,size+1);
225                        for (i=0; i<size+1; i++) o->meas[i] = 0;
226                        o->dev1  = new_fvec(rsize,channels);
227                        o->theta1 = new_fvec(rsize,channels);
228                        o->theta2 = new_fvec(rsize,channels);
229                        break;
230                case aubio_onset_phase:
231                        o->dev1  = new_fvec(rsize,channels);
232                        o->theta1 = new_fvec(rsize,channels);
233                        o->theta2 = new_fvec(rsize,channels);
234                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
235                        o->threshold = 0.1;
236                        break;
237                case aubio_onset_specdiff:
238                        o->oldmag = new_fvec(rsize,channels);
239                        o->dev1   = new_fvec(rsize,channels);
240                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
241                        o->threshold = 0.1;
242                        break;
243                case aubio_onset_kl:
244                        o->oldmag = new_fvec(rsize,channels);
245                        break;
246                case aubio_onset_mkl:
247                        o->oldmag = new_fvec(rsize,channels);
248                        break;
249                default:
250                        break;
251        }
252       
253        /* this switch could be in its own function to change between
254         * detections on the fly. this would need getting rid of the switch
255         * above and always allocate all the structure */
256
257        switch(type) {
258                case aubio_onset_energy:
259                        o->funcpointer = aubio_onsetdetection_energy;
260                        break;
261                case aubio_onset_hfc:
262                        o->funcpointer = aubio_onsetdetection_hfc;
263                        break;
264                case aubio_onset_complex:
265                        o->funcpointer = aubio_onsetdetection_complex;
266                        break;
267                case aubio_onset_phase:
268                        o->funcpointer = aubio_onsetdetection_phase;
269                        break;
270                case aubio_onset_specdiff:
271                        o->funcpointer = aubio_onsetdetection_specdiff;
272                        break;
273                case aubio_onset_kl:
274                        o->funcpointer = aubio_onsetdetection_kl;
275                        break;
276                case aubio_onset_mkl:
277                        o->funcpointer = aubio_onsetdetection_mkl;
278                        break;
279                default:
280                        break;
281        }
282        o->type = type;
283        return o;
284}
285
286void aubio_onsetdetection_free (aubio_onsetdetection_t *o){
287  del_aubio_onsetdetection(o);
288}
289
290void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
291
292        switch(o->type) {
293                /* for both energy and hfc, only fftgrain->norm is required */
294                case aubio_onset_energy: 
295                        break;
296                case aubio_onset_hfc:
297                        break;
298                /* the other approaches will need some more memory spaces */
299                case aubio_onset_complex:
300                        AUBIO_FREE(o->meas);
301                        del_fvec(o->oldmag);
302                        del_fvec(o->dev1);
303                        del_fvec(o->theta1);
304                        del_fvec(o->theta2);
305                        break;
306                case aubio_onset_phase:
307                        del_fvec(o->dev1);
308                        del_fvec(o->theta1);
309                        del_fvec(o->theta2);
310                        del_aubio_hist(o->histog);
311                        break;
312                case aubio_onset_specdiff:
313                        del_fvec(o->oldmag);
314                        del_fvec(o->dev1);
315                        del_aubio_hist(o->histog);
316                        break;
317                case aubio_onset_kl:
318                        del_fvec(o->oldmag);
319                        break;
320                case aubio_onset_mkl:
321                        del_fvec(o->oldmag);
322                        break;
323                default:
324                        break;
325        }
326        AUBIO_FREE(o);
327       
328}
Note: See TracBrowser for help on using the repository browser.