source: src/onset/onsetdetection.c @ 64c3658

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 64c3658 was 01b8fcc, checked in by Paul Brossier <piem@piem.org>, 15 years ago

src/onset: rename aubio_onsetdetection to aubio_onsetdetection_do

  • Property mode set to 100644
File size: 14.2 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 "fvec.h"
22#include "cvec.h"
23#include "spectral/fft.h"
24#include "mathutils.h"
25#include "utils/hist.h"
26#include "onset/onsetdetection.h"
27
28/** Energy based onset detection function
29 
30  This function calculates the local energy of the input spectral frame.
31 
32  \param o onset detection object as returned by new_aubio_onsetdetection()
33  \param fftgrain input spectral frame
34  \param onset output onset detection function
35
36*/
37void aubio_onsetdetection_energy(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
38/** High Frequency Content onset detection function
39 
40  This method computes the High Frequency Content (HFC) of the input spectral
41  frame. The resulting function is efficient at detecting percussive onsets.
42
43  Paul Masri. Computer modeling of Sound for Transformation and Synthesis of
44  Musical Signal. PhD dissertation, University of Bristol, UK, 1996.
45 
46  \param o onset detection object as returned by new_aubio_onsetdetection()
47  \param fftgrain input spectral frame
48  \param onset output onset detection function
49
50*/
51void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
52/** Complex Domain Method onset detection function
53 
54  Christopher Duxbury, Mike E. Davies, and Mark B. Sandler. Complex domain
55  onset detection for musical signals. In Proceedings of the Digital Audio
56  Effects Conference, DAFx-03, pages 90-93, London, UK, 2003.
57
58  \param o onset detection object as returned by new_aubio_onsetdetection()
59  \param fftgrain input spectral frame
60  \param onset output onset detection function
61
62*/
63void aubio_onsetdetection_complex(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
64/** Phase Based Method onset detection function
65
66  Juan-Pablo Bello, Mike P. Davies, and Mark B. Sandler. Phase-based note onset
67  detection for music signals. In Proceedings of the IEEE International
68  Conference on Acoustics Speech and Signal Processing, pages 441­444,
69  Hong-Kong, 2003.
70
71  \param o onset detection object as returned by new_aubio_onsetdetection()
72  \param fftgrain input spectral frame
73  \param onset output onset detection function
74
75*/
76void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
77/** Spectral difference method onset detection function
78
79  Jonhatan Foote and Shingo Uchihashi. The beat spectrum: a new approach to
80  rhythm analysis. In IEEE International Conference on Multimedia and Expo
81  (ICME 2001), pages 881­884, Tokyo, Japan, August 2001.
82
83  \param o onset detection object as returned by new_aubio_onsetdetection()
84  \param fftgrain input spectral frame
85  \param onset output onset detection function
86
87*/
88void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
89/** Kullback-Liebler onset detection function
90 
91  Stephen Hainsworth and Malcom Macleod. Onset detection in music audio
92  signals. In Proceedings of the International Computer Music Conference
93  (ICMC), Singapore, 2003.
94 
95  \param o onset detection object as returned by new_aubio_onsetdetection()
96  \param fftgrain input spectral frame
97  \param onset output onset detection function
98
99*/
100void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
101/** Modified Kullback-Liebler onset detection function
102
103  Paul Brossier, ``Automatic annotation of musical audio for interactive
104  systems'', Chapter 2, Temporal segmentation, PhD thesis, Centre for Digital
105  music, Queen Mary University of London, London, UK, 2006.
106
107  \param o onset detection object as returned by new_aubio_onsetdetection()
108  \param fftgrain input spectral frame
109  \param onset output onset detection function
110
111*/
112void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
113/** Spectral Flux
114
115  Simon Dixon, Onset Detection Revisited, in ``Proceedings of the 9th
116  International Conference on Digital Audio Effects'' (DAFx-06), Montreal,
117  Canada, 2006.
118
119  \param o onset detection object as returned by new_aubio_onsetdetection()
120  \param fftgrain input spectral frame
121  \param onset output onset detection function
122
123*/
124void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
125
126/** structure to store object state */
127struct _aubio_onsetdetection_t {
128  aubio_onsetdetection_type type; /**< onset detection type */
129  /** Pointer to aubio_onsetdetection_<type> function */
130  void (*funcpointer)(aubio_onsetdetection_t *o,
131      cvec_t * fftgrain, fvec_t * onset);
132  smpl_t threshold;      /**< minimum norm threshold for phase and specdiff */
133  fvec_t *oldmag;        /**< previous norm vector */
134  fvec_t *dev1 ;         /**< current onset detection measure vector */
135  fvec_t *theta1;        /**< previous phase vector, one frame behind */
136  fvec_t *theta2;        /**< previous phase vector, two frames behind */
137  aubio_hist_t * histog; /**< histogram */
138};
139
140
141/* Energy based onset detection function */
142void aubio_onsetdetection_energy  (aubio_onsetdetection_t *o UNUSED,
143    cvec_t * fftgrain, fvec_t * onset) {
144  uint_t i,j;
145  for (i=0;i<fftgrain->channels;i++) {
146    onset->data[i][0] = 0.;
147    for (j=0;j<fftgrain->length;j++) {
148      onset->data[i][0] += SQR(fftgrain->norm[i][j]);
149    }
150  }
151}
152
153/* High Frequency Content onset detection function */
154void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o UNUSED,
155    cvec_t * fftgrain, fvec_t * onset){
156  uint_t i,j;
157  for (i=0;i<fftgrain->channels;i++) {
158    onset->data[i][0] = 0.;
159    for (j=0;j<fftgrain->length;j++) {
160      onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
161    }
162  }
163}
164
165
166/* Complex Domain Method onset detection function */
167void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
168  uint_t i, j;
169  uint_t nbins = fftgrain->length;
170  for (i=0;i<fftgrain->channels; i++)  {
171    onset->data[i][0] = 0.;
172    for (j=0;j<nbins; j++)  {
173      // compute the predicted phase
174      o->dev1->data[i][j] = 2. * o->theta1->data[i][j] - o->theta2->data[i][j];
175      // compute the euclidean distance in the complex domain
176      // sqrt ( r_1^2 + r_2^2 - 2 * r_1 * r_2 * \cos ( \phi_1 - \phi_2 ) )
177      onset->data[i][0] +=
178        SQRT (ABS (SQR (o->oldmag->data[i][j]) + SQR (fftgrain->norm[i][j])
179              - 2. * o->oldmag->data[i][j] * fftgrain->norm[i][j]
180              * COS (o->dev1->data[i][j] - fftgrain->phas[i][j])));
181      /* swap old phase data (need to remember 2 frames behind)*/
182      o->theta2->data[i][j] = o->theta1->data[i][j];
183      o->theta1->data[i][j] = fftgrain->phas[i][j];
184      /* swap old magnitude data (1 frame is enough) */
185      o->oldmag->data[i][j] = fftgrain->norm[i][j];
186    }
187  }
188}
189
190
191/* Phase Based Method onset detection function */
192void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, 
193    cvec_t * fftgrain, fvec_t * onset){
194  uint_t i, j;
195  uint_t nbins = fftgrain->length;
196  for (i=0;i<fftgrain->channels; i++)  {
197    onset->data[i][0] = 0.0;
198    o->dev1->data[i][0]=0.;
199    for ( j=0;j<nbins; j++ )  {
200      o->dev1->data[i][j] = 
201        aubio_unwrap2pi(
202            fftgrain->phas[i][j]
203            -2.0*o->theta1->data[i][j]
204            +o->theta2->data[i][j]);
205      if ( o->threshold < fftgrain->norm[i][j] )
206        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
207      else 
208        o->dev1->data[i][j] = 0.0;
209      /* keep a track of the past frames */
210      o->theta2->data[i][j] = o->theta1->data[i][j];
211      o->theta1->data[i][j] = fftgrain->phas[i][j];
212    }
213    /* apply o->histogram */
214    aubio_hist_dyn_notnull(o->histog,o->dev1);
215    /* weight it */
216    aubio_hist_weight(o->histog);
217    /* its mean is the result */
218    onset->data[i][0] = aubio_hist_mean(o->histog); 
219    //onset->data[i][0] = fvec_mean(o->dev1);
220  }
221}
222
223/* Spectral difference method onset detection function */
224void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
225    cvec_t * fftgrain, fvec_t * onset){
226  uint_t i, j;
227  uint_t nbins = fftgrain->length;
228  for (i=0;i<fftgrain->channels; i++)  {
229    onset->data[i][0] = 0.0;
230    for (j=0;j<nbins; j++)  {
231      o->dev1->data[i][j] = SQRT(
232          ABS(SQR( fftgrain->norm[i][j])
233            - SQR(o->oldmag->data[i][j])));
234      if (o->threshold < fftgrain->norm[i][j] )
235        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
236      else 
237        o->dev1->data[i][j] = 0.0;
238      o->oldmag->data[i][j] = fftgrain->norm[i][j];
239    }
240
241    /* apply o->histogram (act somewhat as a low pass on the
242     * overall function)*/
243    aubio_hist_dyn_notnull(o->histog,o->dev1);
244    /* weight it */
245    aubio_hist_weight(o->histog);
246    /* its mean is the result */
247    onset->data[i][0] = aubio_hist_mean(o->histog); 
248
249  }
250}
251
252/* Kullback Liebler onset detection function
253 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
254 * negative (1.+) and infinite values (+1.e-10) */
255void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
256  uint_t i,j;
257  for (i=0;i<fftgrain->channels;i++) {
258    onset->data[i][0] = 0.;
259    for (j=0;j<fftgrain->length;j++) {
260      onset->data[i][0] += fftgrain->norm[i][j]
261        *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
262      o->oldmag->data[i][j] = fftgrain->norm[i][j];
263    }
264    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
265  }
266}
267
268/* Modified Kullback Liebler onset detection function
269 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
270 * negative (1.+) and infinite values (+1.e-10) */
271void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
272  uint_t i,j;
273  for (i=0;i<fftgrain->channels;i++) {
274    onset->data[i][0] = 0.;
275    for (j=0;j<fftgrain->length;j++) {
276      onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
277      o->oldmag->data[i][j] = fftgrain->norm[i][j];
278    }
279    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
280  }
281}
282
283/* Spectral flux */
284void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){ 
285  uint_t i, j;
286  for (i=0;i<fftgrain->channels;i++) {
287    onset->data[i][0] = 0.;
288    for (j=0;j<fftgrain->length;j++) {
289      if (fftgrain->norm[i][j] > o->oldmag->data[i][j])
290        onset->data[i][0] += fftgrain->norm[i][j] - o->oldmag->data[i][j];
291      o->oldmag->data[i][j] = fftgrain->norm[i][j];
292    }
293  }
294}
295
296/* Generic function pointing to the choosen one */
297void 
298aubio_onsetdetection_do (aubio_onsetdetection_t *o, cvec_t * fftgrain, 
299    fvec_t * onset) {
300  o->funcpointer(o,fftgrain,onset);
301}
302
303/* Allocate memory for an onset detection
304 * depending on the choosen type, allocate memory as needed
305 */
306aubio_onsetdetection_t * 
307new_aubio_onsetdetection (aubio_onsetdetection_type type, 
308    uint_t size, uint_t channels){
309  aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
310  uint_t rsize = size/2+1;
311  switch(type) {
312    /* for both energy and hfc, only fftgrain->norm is required */
313    case aubio_onset_energy: 
314      break;
315    case aubio_onset_hfc:
316      break;
317      /* the other approaches will need some more memory spaces */
318    case aubio_onset_complex:
319      o->oldmag = new_fvec(rsize,channels);
320      o->dev1   = new_fvec(rsize,channels);
321      o->theta1 = new_fvec(rsize,channels);
322      o->theta2 = new_fvec(rsize,channels);
323      break;
324    case aubio_onset_phase:
325      o->dev1   = new_fvec(rsize,channels);
326      o->theta1 = new_fvec(rsize,channels);
327      o->theta2 = new_fvec(rsize,channels);
328      o->histog = new_aubio_hist(0.0, PI, 10, channels);
329      o->threshold = 0.1;
330      break;
331    case aubio_onset_specdiff:
332      o->oldmag = new_fvec(rsize,channels);
333      o->dev1   = new_fvec(rsize,channels);
334      o->histog = new_aubio_hist(0.0, PI, 10, channels);
335      o->threshold = 0.1;
336      break;
337    case aubio_onset_kl:
338    case aubio_onset_mkl:
339    case aubio_onset_specflux:
340      o->oldmag = new_fvec(rsize,channels);
341      break;
342    default:
343      break;
344  }
345
346  /* this switch could be in its own function to change between
347   * detections on the fly. this would need getting rid of the switch
348   * above and always allocate all the structure */
349
350  switch(type) {
351    case aubio_onset_energy:
352      o->funcpointer = aubio_onsetdetection_energy;
353      break;
354    case aubio_onset_hfc:
355      o->funcpointer = aubio_onsetdetection_hfc;
356      break;
357    case aubio_onset_complex:
358      o->funcpointer = aubio_onsetdetection_complex;
359      break;
360    case aubio_onset_phase:
361      o->funcpointer = aubio_onsetdetection_phase;
362      break;
363    case aubio_onset_specdiff:
364      o->funcpointer = aubio_onsetdetection_specdiff;
365      break;
366    case aubio_onset_kl:
367      o->funcpointer = aubio_onsetdetection_kl;
368      break;
369    case aubio_onset_mkl:
370      o->funcpointer = aubio_onsetdetection_mkl;
371      break;
372    case aubio_onset_specflux:
373      o->funcpointer = aubio_onsetdetection_specflux;
374      break;
375    default:
376      break;
377  }
378  o->type = type;
379  return o;
380}
381
382void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
383  switch(o->type) {
384    /* for both energy and hfc, only fftgrain->norm is required */
385    case aubio_onset_energy: 
386      break;
387    case aubio_onset_hfc:
388      break;
389      /* the other approaches will need some more memory spaces */
390    case aubio_onset_complex:
391      del_fvec(o->oldmag);
392      del_fvec(o->dev1);
393      del_fvec(o->theta1);
394      del_fvec(o->theta2);
395      break;
396    case aubio_onset_phase:
397      del_fvec(o->dev1);
398      del_fvec(o->theta1);
399      del_fvec(o->theta2);
400      del_aubio_hist(o->histog);
401      break;
402    case aubio_onset_specdiff:
403      del_fvec(o->oldmag);
404      del_fvec(o->dev1);
405      del_aubio_hist(o->histog);
406      break;
407    case aubio_onset_kl:
408    case aubio_onset_mkl:
409    case aubio_onset_specflux:
410      del_fvec(o->oldmag);
411      break;
412    default:
413      break;
414  }
415  AUBIO_FREE(o);
416}
Note: See TracBrowser for help on using the repository browser.