source: src/onsetdetection.c @ 32c0133

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

use replacement if complex.h not found
use replacement if complex.h not found

  • 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,
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,        cvec_t * fftgrain, fvec_t * onset){
58        uint_t i,j;
59        for (i=0;i<fftgrain->channels;i++) {
60                onset->data[i][0] = 0.;
61                for (j=0;j<fftgrain->length;j++) {
62                        onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
63                }
64        }
65}
66
67
68/* Complex Domain Method onset detection function */
69void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
70        uint_t i, j;
71        uint_t nbins = fftgrain->length;
72        for (i=0;i<fftgrain->channels; i++)     {
73                onset->data[i][0] = 0.;
74                for (j=0;j<nbins; j++)  {
75                        o->dev1->data[i][j]      = aubio_unwrap2pi(
76                                        fftgrain->phas[i][j]
77                                        -2.0*o->theta1->data[i][j]+
78                                        o->theta2->data[i][j]);
79#ifdef HAVE_COMPLEX_H
80                        o->meas[j] = fftgrain->norm[i][j]*CEXPC(I*o->dev1->data[i][j]);
81                        /* sum on all bins */
82                        onset->data[i][0]                += //(fftgrain->norm[i][j]);
83                                        SQRT(SQR( REAL(o->oldmag->data[i][j]-o->meas[j]) )
84                                                +  SQR( IMAG(o->oldmag->data[i][j]-o->meas[j]) )
85                                                );
86#else
87                        o->meas[j]             = (fftgrain->norm[i][j])*COS(o->dev1->data[i][j]);
88                        o->meas[(nbins-1)*2-j] = (fftgrain->norm[i][j])*SIN(o->dev1->data[i][j]);
89                        /* sum on all bins */
90                        onset->data[i][0]                += //(fftgrain->norm[i][j]);
91                                        SQRT(SQR( (o->oldmag->data[i][j]-o->meas[j]) )
92                                                +  SQR( (-o->meas[(nbins-1)*2-j]) )
93                                                );
94#endif
95                        /* swap old phase data (need to remember 2 frames behind)*/
96                        o->theta2->data[i][j] = o->theta1->data[i][j];
97                        o->theta1->data[i][j] = fftgrain->phas[i][j];
98                        /* swap old magnitude data (1 frame is enough) */
99                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
100                }
101        }
102}
103
104
105/* Phase Based Method onset detection function */
106void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, 
107                cvec_t * fftgrain, fvec_t * onset){
108        uint_t i, j;
109        uint_t nbins = fftgrain->length;
110        for (i=0;i<fftgrain->channels; i++)     {
111                onset->data[i][0] = 0.0f;
112                o->dev1->data[i][0]=0.;
113                for ( j=0;j<nbins; j++ )        {
114                        o->dev1->data[i][j] = 
115                                aubio_unwrap2pi(
116                                                fftgrain->phas[i][j]
117                                                -2.0*o->theta1->data[i][j]
118                                                +o->theta2->data[i][j]);
119                        if ( o->threshold < fftgrain->norm[i][j] )
120                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
121                        else 
122                                o->dev1->data[i][j] = 0.0f;
123                        /* keep a track of the past frames */
124                        o->theta2->data[i][j] = o->theta1->data[i][j];
125                        o->theta1->data[i][j] = fftgrain->phas[i][j];
126                }
127                /* apply o->histogram */
128                aubio_hist_dyn_notnull(o->histog,o->dev1);
129                /* weight it */
130                aubio_hist_weigth(o->histog);
131                /* its mean is the result */
132                onset->data[i][0] = aubio_hist_mean(o->histog); 
133                //onset->data[i][0] = vec_mean(o->dev1);
134        }
135}
136
137/* Spectral difference method onset detection function */
138void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
139                cvec_t * fftgrain, fvec_t * onset){
140        uint_t i, j;
141        uint_t nbins = fftgrain->length;
142        for (i=0;i<fftgrain->channels; i++)     {
143                onset->data[i][0] = 0.0f;
144                for (j=0;j<nbins; j++)  {
145                        o->dev1->data[i][j] = SQRT(
146                                        ABS(SQR( fftgrain->norm[i][j])
147                                                - SQR(o->oldmag->data[i][j])));
148                        if (o->threshold < fftgrain->norm[i][j] )
149                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
150                        else 
151                                o->dev1->data[i][j] = 0.0f;
152                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
153                }
154
155                /* apply o->histogram (act somewhat as a low pass on the
156                 * overall function)*/
157                aubio_hist_dyn_notnull(o->histog,o->dev1);
158                /* weight it */
159                aubio_hist_weigth(o->histog);
160                /* its mean is the result */
161                onset->data[i][0] = aubio_hist_mean(o->histog); 
162
163        }
164}
165
166/* Kullback Liebler onset detection function
167 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
168 * negative (1.+) and infinite values (+1.e-10) */
169void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
170        uint_t i,j;
171        for (i=0;i<fftgrain->channels;i++) {
172                onset->data[i][0] = 0.;
173                for (j=0;j<fftgrain->length;j++) {
174                        onset->data[i][0] += fftgrain->norm[i][j]
175                                *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
176                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
177                }
178                if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
179        }
180}
181
182/* Modified Kullback Liebler onset detection function
183 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
184 * negative (1.+) and infinite values (+1.e-10) */
185void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
186        uint_t i,j;
187        for (i=0;i<fftgrain->channels;i++) {
188                onset->data[i][0] = 0.;
189                for (j=0;j<fftgrain->length;j++) {
190                        onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
191                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
192                }
193                if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
194        }
195}
196
197/* Generic function pointing to the choosen one */
198void 
199aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain, 
200                fvec_t * onset) {
201        o->funcpointer(o,fftgrain,onset);
202}
203
204/* Allocate memory for an onset detection
205 * depending on the choosen type, allocate memory as needed
206 */
207aubio_onsetdetection_t * 
208new_aubio_onsetdetection (aubio_onsetdetection_type type, 
209                uint_t size, uint_t channels){
210        aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
211        uint_t rsize = size/2+1;
212  uint_t i;
213        switch(type) {
214                /* for both energy and hfc, only fftgrain->norm is required */
215                case aubio_onset_energy: 
216                        break;
217                case aubio_onset_hfc:
218                        break;
219                /* the other approaches will need some more memory spaces */
220                case aubio_onset_complex:
221                        o->oldmag = new_fvec(rsize,channels);
222                        /** bug: must be complex array */
223                        o->meas = AUBIO_ARRAY(fft_data_t,size+1);
224                        for (i=0; i<size+1; i++) o->meas[i] = 0;
225                        o->dev1  = new_fvec(rsize,channels);
226                        o->theta1 = new_fvec(rsize,channels);
227                        o->theta2 = new_fvec(rsize,channels);
228                        break;
229                case aubio_onset_phase:
230                        o->dev1  = new_fvec(rsize,channels);
231                        o->theta1 = new_fvec(rsize,channels);
232                        o->theta2 = new_fvec(rsize,channels);
233                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
234                        o->threshold = 0.1;
235                        break;
236                case aubio_onset_specdiff:
237                        o->oldmag = new_fvec(rsize,channels);
238                        o->dev1   = new_fvec(rsize,channels);
239                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
240                        o->threshold = 0.1;
241                        break;
242                case aubio_onset_kl:
243                        o->oldmag = new_fvec(rsize,channels);
244                        break;
245                case aubio_onset_mkl:
246                        o->oldmag = new_fvec(rsize,channels);
247                        break;
248                default:
249                        break;
250        }
251       
252        /* this switch could be in its own function to change between
253         * detections on the fly. this would need getting rid of the switch
254         * above and always allocate all the structure */
255
256        switch(type) {
257                case aubio_onset_energy:
258                        o->funcpointer = aubio_onsetdetection_energy;
259                        break;
260                case aubio_onset_hfc:
261                        o->funcpointer = aubio_onsetdetection_hfc;
262                        break;
263                case aubio_onset_complex:
264                        o->funcpointer = aubio_onsetdetection_complex;
265                        break;
266                case aubio_onset_phase:
267                        o->funcpointer = aubio_onsetdetection_phase;
268                        break;
269                case aubio_onset_specdiff:
270                        o->funcpointer = aubio_onsetdetection_specdiff;
271                        break;
272                case aubio_onset_kl:
273                        o->funcpointer = aubio_onsetdetection_kl;
274                        break;
275                case aubio_onset_mkl:
276                        o->funcpointer = aubio_onsetdetection_mkl;
277                        break;
278                default:
279                        break;
280        }
281        o->type = type;
282        return o;
283}
284
285void aubio_onsetdetection_free (aubio_onsetdetection_t *o){
286  del_aubio_onsetdetection(o);
287}
288
289void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
290
291        switch(o->type) {
292                /* for both energy and hfc, only fftgrain->norm is required */
293                case aubio_onset_energy: 
294                        break;
295                case aubio_onset_hfc:
296                        break;
297                /* the other approaches will need some more memory spaces */
298                case aubio_onset_complex:
299                        AUBIO_FREE(o->meas);
300                        del_fvec(o->oldmag);
301                        del_fvec(o->dev1);
302                        del_fvec(o->theta1);
303                        del_fvec(o->theta2);
304                        break;
305                case aubio_onset_phase:
306                        del_fvec(o->dev1);
307                        del_fvec(o->theta1);
308                        del_fvec(o->theta2);
309                        del_aubio_hist(o->histog);
310                        break;
311                case aubio_onset_specdiff:
312                        del_fvec(o->oldmag);
313                        del_fvec(o->dev1);
314                        del_aubio_hist(o->histog);
315                        break;
316                case aubio_onset_kl:
317                        del_fvec(o->oldmag);
318                        break;
319                case aubio_onset_mkl:
320                        del_fvec(o->oldmag);
321                        break;
322                default:
323                        break;
324        }
325        AUBIO_FREE(o);
326       
327}
Note: See TracBrowser for help on using the repository browser.