source: src/onsetdetection.c @ 205da86

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 205da86 was 96fb8ad, checked in by Paul Brossier <piem@altern.org>, 20 years ago

import 0.1.7.1

  • Property mode set to 100644
File size: 7.7 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
43static aubio_onsetdetection_t * aubio_onsetdetection_alloc(aubio_onsetdetection_type type, uint_t size, uint_t channels);
44
45/* Energy based onset detection function */
46void aubio_onsetdetection_energy  (aubio_onsetdetection_t *o,
47                cvec_t * fftgrain, fvec_t * onset) {
48        uint_t i,j;
49        for (i=0;i<fftgrain->channels;i++) {
50                onset->data[i][0] = 0.;
51                for (j=0;j<fftgrain->length;j++) {
52                        onset->data[i][0] += SQR(fftgrain->norm[i][j]);
53                }
54        }
55}
56
57/* High Frequency Content onset detection function */
58void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o,        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 */
70/* moved to /2 032402 */
71void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
72        uint_t i, j;
73        uint_t nbins = fftgrain->length;
74        for (i=0;i<fftgrain->channels; i++)     {
75                onset->data[i][0] = 0.;
76                for (j=0;j<nbins; j++)  {
77                        o->dev1->data[i][j]      = unwrap2pi(
78                                        fftgrain->phas[i][j]
79                                        -2.0*o->theta1->data[i][j]+
80                                        o->theta2->data[i][j]);
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                        /* swap old phase data (need to remember 2 frames behind)*/
88                        o->theta2->data[i][j] = o->theta1->data[i][j];
89                        o->theta1->data[i][j] = fftgrain->phas[i][j];
90                        /* swap old magnitude data (1 frame is enough) */
91                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
92                }
93        }
94}
95
96
97/* Phase Based Method onset detection function */
98void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, 
99                cvec_t * fftgrain, fvec_t * onset){
100        uint_t i, j;
101        uint_t nbins = fftgrain->length;
102        for (i=0;i<fftgrain->channels; i++)     {
103                onset->data[i][0] = 0.0f;
104                o->dev1->data[i][0]=0.;
105                for ( j=0;j<nbins; j++ )        {
106                        o->dev1->data[i][j] = 
107                                unwrap2pi(
108                                                fftgrain->phas[i][j]
109                                                -2.0*o->theta1->data[i][j]
110                                                +o->theta2->data[i][j]);
111                        if ( o->threshold < fftgrain->norm[i][j] )
112                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
113                        else 
114                                o->dev1->data[i][j] = 0.0f;
115                        /* keep a track of the past frames */
116                        o->theta2->data[i][j] = o->theta1->data[i][j];
117                        o->theta1->data[i][j] = fftgrain->phas[i][j];
118                }
119                /* apply o->histogram */
120                aubio_hist_dyn_notnull(o->histog,o->dev1);
121                /* weight it */
122                aubio_hist_weigth(o->histog);
123                /* its mean is the result */
124                onset->data[i][0] = aubio_hist_mean(o->histog); 
125                //onset->data[i][0] = vec_mean(o->dev1);
126        }
127}
128
129/* Spectral difference method onset detection function */
130/* moved to /2 032402 */
131void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
132                cvec_t * fftgrain, fvec_t * onset){
133        uint_t i, j;
134        uint_t nbins = fftgrain->length;
135        for (i=0;i<fftgrain->channels; i++)     {
136                onset->data[i][0] = 0.0f;
137                for (j=0;j<nbins; j++)  {
138                        o->dev1->data[i][j] = SQRT(
139                                        ABS(SQR( fftgrain->norm[i][j])
140                                                - SQR(o->oldmag->data[i][j])));
141                        if (o->threshold < fftgrain->norm[i][j] )
142                                o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
143                        else 
144                                o->dev1->data[i][j] = 0.0f;
145                        o->oldmag->data[i][j] = fftgrain->norm[i][j];
146                }
147
148                /* apply o->histogram (act somewhat as a low pass on the
149                 * overall function)*/
150                aubio_hist_dyn_notnull(o->histog,o->dev1);
151                /* weight it */
152                aubio_hist_weigth(o->histog);
153                /* its mean is the result */
154                onset->data[i][0] = aubio_hist_mean(o->histog); 
155
156        }
157}
158
159/* Generic function pointing to the choosen one */
160void 
161aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain, 
162                fvec_t * onset) {
163        o->funcpointer(o,fftgrain,onset);
164}
165
166/* Allocate memory for an onset detection */
167aubio_onsetdetection_t * 
168new_aubio_onsetdetection (aubio_onsetdetection_type type, 
169                uint_t size, uint_t channels){
170        return aubio_onsetdetection_alloc(type,size,channels);
171}
172
173/* depending on the choosen type, allocate memory as needed */
174aubio_onsetdetection_t * 
175aubio_onsetdetection_alloc (aubio_onsetdetection_type type, 
176                uint_t size, uint_t channels){
177        aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
178        uint_t rsize = size/2+1;
179        switch(type) {
180                /* for both energy and hfc, only fftgrain->norm is required */
181                case energy: 
182                        break;
183                case hfc:
184                        break;
185                /* the other approaches will need some more memory spaces */
186                case complexdomain:
187                        o->oldmag = new_fvec(rsize,channels);
188                        /** bug: must be complex array */
189                        o->meas = AUBIO_ARRAY(fft_data_t,size);
190                        o->dev1  = new_fvec(rsize,channels);
191                        o->theta1 = new_fvec(rsize,channels);
192                        o->theta2 = new_fvec(rsize,channels);
193                        break;
194                case phase:
195                        o->dev1  = new_fvec(rsize,channels);
196                        o->theta1 = new_fvec(rsize,channels);
197                        o->theta2 = new_fvec(rsize,channels);
198                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
199                        o->threshold = 0.1;
200                        break;
201                case specdiff:
202                        o->oldmag = new_fvec(rsize,channels);
203                        o->dev1   = new_fvec(rsize,channels);
204                        o->histog = new_aubio_hist(0.0f, PI, 10, channels);
205                        o->threshold = 0.1;
206                        break;
207                default:
208                        break;
209        }
210       
211        /* this switch could be in its own function to change between
212         * detections on the fly. this would need getting rid of the switch
213         * above and always allocate all the structure */
214
215        switch(type) {
216                case energy:
217                        o->funcpointer = aubio_onsetdetection_energy;
218                        break;
219                case hfc:
220                        o->funcpointer = aubio_onsetdetection_hfc;
221                        break;
222                case complexdomain:
223                        o->funcpointer = aubio_onsetdetection_complex;
224                        break;
225                case phase:
226                        o->funcpointer = aubio_onsetdetection_phase;
227                        break;
228                case specdiff:
229                        o->funcpointer = aubio_onsetdetection_specdiff;
230                        break;
231                default:
232                        break;
233        }
234        o->type = type;
235        return o;
236}
237
238void aubio_onsetdetection_free (aubio_onsetdetection_t *o){
239
240        switch(o->type) {
241                /* for both energy and hfc, only fftgrain->norm is required */
242                case energy: 
243                        break;
244                case hfc:
245                        break;
246                /* the other approaches will need some more memory spaces */
247                case complexdomain:
248                        AUBIO_FREE(o->meas);
249                        del_fvec(o->oldmag);
250                        del_fvec(o->dev1);
251                        del_fvec(o->theta1);
252                        del_fvec(o->theta2);
253                        break;
254                case phase:
255                        del_fvec(o->dev1);
256                        del_fvec(o->theta1);
257                        del_fvec(o->theta2);
258                        del_aubio_hist(o->histog);
259                        break;
260                case specdiff:
261                        del_fvec(o->oldmag);
262                        del_fvec(o->dev1);
263                        del_aubio_hist(o->histog);
264                        break;
265                default:
266                        break;
267        }
268        AUBIO_FREE(o);
269       
270}
Note: See TracBrowser for help on using the repository browser.