source: src/onset/onsetdetection.c @ 8b19e1c

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

src/onset/onsetdetection.c: add 'default' method, set it to hfc, set method to default when parsing the string fails

  • Property mode set to 100644
File size: 15.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 "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/** onsetdetection types */
127typedef enum {
128        aubio_onset_energy,         /**< energy based */         
129        aubio_onset_specdiff,       /**< spectral diff */         
130        aubio_onset_hfc,            /**< high frequency content */
131        aubio_onset_complex,        /**< complex domain */       
132        aubio_onset_phase,          /**< phase fast */           
133        aubio_onset_kl,             /**< Kullback Liebler */
134        aubio_onset_mkl,            /**< modified Kullback Liebler */
135        aubio_onset_specflux,       /**< spectral flux */
136        aubio_onset_default = aubio_onset_hfc, /**< default mode, set to hfc */
137} aubio_onsetdetection_type;
138
139/** structure to store object state */
140struct _aubio_onsetdetection_t {
141  aubio_onsetdetection_type onset_type; /**< onset detection type */
142  /** Pointer to aubio_onsetdetection_<type> function */
143  void (*funcpointer)(aubio_onsetdetection_t *o,
144      cvec_t * fftgrain, fvec_t * onset);
145  smpl_t threshold;      /**< minimum norm threshold for phase and specdiff */
146  fvec_t *oldmag;        /**< previous norm vector */
147  fvec_t *dev1 ;         /**< current onset detection measure vector */
148  fvec_t *theta1;        /**< previous phase vector, one frame behind */
149  fvec_t *theta2;        /**< previous phase vector, two frames behind */
150  aubio_hist_t * histog; /**< histogram */
151};
152
153
154/* Energy based onset detection function */
155void aubio_onsetdetection_energy  (aubio_onsetdetection_t *o UNUSED,
156    cvec_t * fftgrain, fvec_t * onset) {
157  uint_t i,j;
158  for (i=0;i<fftgrain->channels;i++) {
159    onset->data[i][0] = 0.;
160    for (j=0;j<fftgrain->length;j++) {
161      onset->data[i][0] += SQR(fftgrain->norm[i][j]);
162    }
163  }
164}
165
166/* High Frequency Content onset detection function */
167void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o UNUSED,
168    cvec_t * fftgrain, fvec_t * onset){
169  uint_t i,j;
170  for (i=0;i<fftgrain->channels;i++) {
171    onset->data[i][0] = 0.;
172    for (j=0;j<fftgrain->length;j++) {
173      onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
174    }
175  }
176}
177
178
179/* Complex Domain Method onset detection function */
180void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
181  uint_t i, j;
182  uint_t nbins = fftgrain->length;
183  for (i=0;i<fftgrain->channels; i++)  {
184    onset->data[i][0] = 0.;
185    for (j=0;j<nbins; j++)  {
186      // compute the predicted phase
187      o->dev1->data[i][j] = 2. * o->theta1->data[i][j] - o->theta2->data[i][j];
188      // compute the euclidean distance in the complex domain
189      // sqrt ( r_1^2 + r_2^2 - 2 * r_1 * r_2 * \cos ( \phi_1 - \phi_2 ) )
190      onset->data[i][0] +=
191        SQRT (ABS (SQR (o->oldmag->data[i][j]) + SQR (fftgrain->norm[i][j])
192              - 2. * o->oldmag->data[i][j] * fftgrain->norm[i][j]
193              * COS (o->dev1->data[i][j] - fftgrain->phas[i][j])));
194      /* swap old phase data (need to remember 2 frames behind)*/
195      o->theta2->data[i][j] = o->theta1->data[i][j];
196      o->theta1->data[i][j] = fftgrain->phas[i][j];
197      /* swap old magnitude data (1 frame is enough) */
198      o->oldmag->data[i][j] = fftgrain->norm[i][j];
199    }
200  }
201}
202
203
204/* Phase Based Method onset detection function */
205void aubio_onsetdetection_phase(aubio_onsetdetection_t *o, 
206    cvec_t * fftgrain, fvec_t * onset){
207  uint_t i, j;
208  uint_t nbins = fftgrain->length;
209  for (i=0;i<fftgrain->channels; i++)  {
210    onset->data[i][0] = 0.0;
211    o->dev1->data[i][0]=0.;
212    for ( j=0;j<nbins; j++ )  {
213      o->dev1->data[i][j] = 
214        aubio_unwrap2pi(
215            fftgrain->phas[i][j]
216            -2.0*o->theta1->data[i][j]
217            +o->theta2->data[i][j]);
218      if ( o->threshold < fftgrain->norm[i][j] )
219        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
220      else 
221        o->dev1->data[i][j] = 0.0;
222      /* keep a track of the past frames */
223      o->theta2->data[i][j] = o->theta1->data[i][j];
224      o->theta1->data[i][j] = fftgrain->phas[i][j];
225    }
226    /* apply o->histogram */
227    aubio_hist_dyn_notnull(o->histog,o->dev1);
228    /* weight it */
229    aubio_hist_weight(o->histog);
230    /* its mean is the result */
231    onset->data[i][0] = aubio_hist_mean(o->histog); 
232    //onset->data[i][0] = fvec_mean(o->dev1);
233  }
234}
235
236/* Spectral difference method onset detection function */
237void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
238    cvec_t * fftgrain, fvec_t * onset){
239  uint_t i, j;
240  uint_t nbins = fftgrain->length;
241  for (i=0;i<fftgrain->channels; i++)  {
242    onset->data[i][0] = 0.0;
243    for (j=0;j<nbins; j++)  {
244      o->dev1->data[i][j] = SQRT(
245          ABS(SQR( fftgrain->norm[i][j])
246            - SQR(o->oldmag->data[i][j])));
247      if (o->threshold < fftgrain->norm[i][j] )
248        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
249      else 
250        o->dev1->data[i][j] = 0.0;
251      o->oldmag->data[i][j] = fftgrain->norm[i][j];
252    }
253
254    /* apply o->histogram (act somewhat as a low pass on the
255     * overall function)*/
256    aubio_hist_dyn_notnull(o->histog,o->dev1);
257    /* weight it */
258    aubio_hist_weight(o->histog);
259    /* its mean is the result */
260    onset->data[i][0] = aubio_hist_mean(o->histog); 
261
262  }
263}
264
265/* Kullback Liebler onset detection function
266 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
267 * negative (1.+) and infinite values (+1.e-10) */
268void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
269  uint_t i,j;
270  for (i=0;i<fftgrain->channels;i++) {
271    onset->data[i][0] = 0.;
272    for (j=0;j<fftgrain->length;j++) {
273      onset->data[i][0] += fftgrain->norm[i][j]
274        *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
275      o->oldmag->data[i][j] = fftgrain->norm[i][j];
276    }
277    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
278  }
279}
280
281/* Modified Kullback Liebler onset detection function
282 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
283 * negative (1.+) and infinite values (+1.e-10) */
284void aubio_onsetdetection_mkl(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      onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
290      o->oldmag->data[i][j] = fftgrain->norm[i][j];
291    }
292    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
293  }
294}
295
296/* Spectral flux */
297void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){ 
298  uint_t i, j;
299  for (i=0;i<fftgrain->channels;i++) {
300    onset->data[i][0] = 0.;
301    for (j=0;j<fftgrain->length;j++) {
302      if (fftgrain->norm[i][j] > o->oldmag->data[i][j])
303        onset->data[i][0] += fftgrain->norm[i][j] - o->oldmag->data[i][j];
304      o->oldmag->data[i][j] = fftgrain->norm[i][j];
305    }
306  }
307}
308
309/* Generic function pointing to the choosen one */
310void 
311aubio_onsetdetection_do (aubio_onsetdetection_t *o, cvec_t * fftgrain, 
312    fvec_t * onset) {
313  o->funcpointer(o,fftgrain,onset);
314}
315
316/* Allocate memory for an onset detection
317 * depending on the choosen type, allocate memory as needed
318 */
319aubio_onsetdetection_t * 
320new_aubio_onsetdetection (char_t * onset_mode, 
321    uint_t size, uint_t channels){
322  aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
323  uint_t rsize = size/2+1;
324  aubio_onsetdetection_type onset_type;
325  if (strcmp (onset_mode, "energy") == 0)
326      onset_type = aubio_onset_energy;
327  else if (strcmp (onset_mode, "specdiff") == 0)
328      onset_type = aubio_onset_specdiff;
329  else if (strcmp (onset_mode, "hfc") == 0)
330      onset_type = aubio_onset_hfc;
331  else if (strcmp (onset_mode, "complexdomain") == 0)
332      onset_type = aubio_onset_complex;
333  else if (strcmp (onset_mode, "complex") == 0)
334      onset_type = aubio_onset_complex;
335  else if (strcmp (onset_mode, "phase") == 0)
336      onset_type = aubio_onset_phase;
337  else if (strcmp (onset_mode, "mkl") == 0)
338      onset_type = aubio_onset_mkl;
339  else if (strcmp (onset_mode, "kl") == 0)
340      onset_type = aubio_onset_kl;
341  else if (strcmp (onset_mode, "specflux") == 0)
342      onset_type = aubio_onset_specflux;
343  else if (strcmp (onset_mode, "default") == 0)
344      onset_type = aubio_onset_default;
345  else {
346      AUBIO_ERR("unknown onset type.\n");
347      onset_type = aubio_onset_default;
348  }
349  switch(onset_type) {
350    /* for both energy and hfc, only fftgrain->norm is required */
351    case aubio_onset_energy: 
352      break;
353    case aubio_onset_hfc:
354      break;
355      /* the other approaches will need some more memory spaces */
356    case aubio_onset_complex:
357      o->oldmag = new_fvec(rsize,channels);
358      o->dev1   = new_fvec(rsize,channels);
359      o->theta1 = new_fvec(rsize,channels);
360      o->theta2 = new_fvec(rsize,channels);
361      break;
362    case aubio_onset_phase:
363      o->dev1   = new_fvec(rsize,channels);
364      o->theta1 = new_fvec(rsize,channels);
365      o->theta2 = new_fvec(rsize,channels);
366      o->histog = new_aubio_hist(0.0, PI, 10, channels);
367      o->threshold = 0.1;
368      break;
369    case aubio_onset_specdiff:
370      o->oldmag = new_fvec(rsize,channels);
371      o->dev1   = new_fvec(rsize,channels);
372      o->histog = new_aubio_hist(0.0, PI, 10, channels);
373      o->threshold = 0.1;
374      break;
375    case aubio_onset_kl:
376    case aubio_onset_mkl:
377    case aubio_onset_specflux:
378      o->oldmag = new_fvec(rsize,channels);
379      break;
380    default:
381      break;
382  }
383
384  /* this switch could be in its own function to change between
385   * detections on the fly. this would need getting rid of the switch
386   * above and always allocate all the structure */
387
388  switch(onset_type) {
389    case aubio_onset_energy:
390      o->funcpointer = aubio_onsetdetection_energy;
391      break;
392    case aubio_onset_hfc:
393      o->funcpointer = aubio_onsetdetection_hfc;
394      break;
395    case aubio_onset_complex:
396      o->funcpointer = aubio_onsetdetection_complex;
397      break;
398    case aubio_onset_phase:
399      o->funcpointer = aubio_onsetdetection_phase;
400      break;
401    case aubio_onset_specdiff:
402      o->funcpointer = aubio_onsetdetection_specdiff;
403      break;
404    case aubio_onset_kl:
405      o->funcpointer = aubio_onsetdetection_kl;
406      break;
407    case aubio_onset_mkl:
408      o->funcpointer = aubio_onsetdetection_mkl;
409      break;
410    case aubio_onset_specflux:
411      o->funcpointer = aubio_onsetdetection_specflux;
412      break;
413    default:
414      break;
415  }
416  o->onset_type = onset_type;
417  return o;
418}
419
420void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
421  switch(o->onset_type) {
422    /* for both energy and hfc, only fftgrain->norm is required */
423    case aubio_onset_energy: 
424      break;
425    case aubio_onset_hfc:
426      break;
427      /* the other approaches will need some more memory spaces */
428    case aubio_onset_complex:
429      del_fvec(o->oldmag);
430      del_fvec(o->dev1);
431      del_fvec(o->theta1);
432      del_fvec(o->theta2);
433      break;
434    case aubio_onset_phase:
435      del_fvec(o->dev1);
436      del_fvec(o->theta1);
437      del_fvec(o->theta2);
438      del_aubio_hist(o->histog);
439      break;
440    case aubio_onset_specdiff:
441      del_fvec(o->oldmag);
442      del_fvec(o->dev1);
443      del_aubio_hist(o->histog);
444      break;
445    case aubio_onset_kl:
446    case aubio_onset_mkl:
447    case aubio_onset_specflux:
448      del_fvec(o->oldmag);
449      break;
450    default:
451      break;
452  }
453  AUBIO_FREE(o);
454}
Note: See TracBrowser for help on using the repository browser.