source: src/onsetdetection.c @ 9bb8151

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

add documentation for _aubio_onset_detection_t
add documentation for _aubio_onset_detection_t

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