source: src/onset/onsetdetection.c @ b4f5967

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

src/onset: use a string to set onset mode, keeping onset types enum private, update everywhere onsets are used

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