source: src/onsetdetection.c @ 4e9101e

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

fix memory freeing in onsetdetection, remove useless _alloc
fix memory freeing in onsetdetection, remove useless _alloc

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