source: src/spectral/specdesc.c @ c7860af

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

src/spectral/: added statistics.c, containing some cuidado spectral shape descriptors

  • Property mode set to 100644
File size: 14.7 KB
Line 
1/*
2  Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
3
4  This file is part of aubio.
5
6  aubio is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10
11  aubio is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#include "aubio_priv.h"
22#include "fvec.h"
23#include "cvec.h"
24#include "spectral/fft.h"
25#include "spectral/specdesc.h"
26#include "mathutils.h"
27#include "utils/hist.h"
28
29void aubio_specdesc_energy(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
30void aubio_specdesc_hfc(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
31void aubio_specdesc_complex(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
32void aubio_specdesc_phase(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
33void aubio_specdesc_specdiff(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
34void aubio_specdesc_kl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
35void aubio_specdesc_mkl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
36void aubio_specdesc_specflux(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
37
38extern void aubio_specdesc_centroid (aubio_specdesc_t * o, cvec_t * spec,
39    fvec_t * desc);
40extern void aubio_specdesc_spread (aubio_specdesc_t * o, cvec_t * spec,
41    fvec_t * desc);
42extern void aubio_specdesc_skewness (aubio_specdesc_t * o, cvec_t * spec,
43    fvec_t * desc);
44extern void aubio_specdesc_kurtosis (aubio_specdesc_t * o, cvec_t * spec,
45    fvec_t * desc);
46extern void aubio_specdesc_slope (aubio_specdesc_t * o, cvec_t * spec,
47    fvec_t * desc);
48extern void aubio_specdesc_decrease (aubio_specdesc_t * o, cvec_t * spec,
49    fvec_t * desc);
50extern void aubio_specdesc_rolloff (aubio_specdesc_t * o, cvec_t * spec,
51    fvec_t * desc);
52
53/** onsetdetection types */
54typedef enum {
55        aubio_onset_energy,         /**< energy based */         
56        aubio_onset_specdiff,       /**< spectral diff */         
57        aubio_onset_hfc,            /**< high frequency content */
58        aubio_onset_complex,        /**< complex domain */       
59        aubio_onset_phase,          /**< phase fast */           
60        aubio_onset_kl,             /**< Kullback Liebler */
61        aubio_onset_mkl,            /**< modified Kullback Liebler */
62        aubio_onset_specflux,       /**< spectral flux */
63        aubio_specmethod_centroid,  /**< spectral centroid */
64        aubio_specmethod_spread,    /**< spectral spread */
65        aubio_specmethod_skewness,  /**< spectral skewness */
66        aubio_specmethod_kurtosis,  /**< spectral kurtosis */
67        aubio_specmethod_slope,     /**< spectral kurtosis */
68        aubio_specmethod_decrease,  /**< spectral decrease */
69        aubio_specmethod_rolloff,   /**< spectral rolloff */
70        aubio_onset_default = aubio_onset_hfc, /**< default mode, set to hfc */
71} aubio_specdesc_type;
72
73/** structure to store object state */
74struct _aubio_specdesc_t {
75  aubio_specdesc_type onset_type; /**< onset detection type */
76  /** Pointer to aubio_specdesc_<type> function */
77  void (*funcpointer)(aubio_specdesc_t *o,
78      cvec_t * fftgrain, fvec_t * onset);
79  smpl_t threshold;      /**< minimum norm threshold for phase and specdiff */
80  fvec_t *oldmag;        /**< previous norm vector */
81  fvec_t *dev1 ;         /**< current onset detection measure vector */
82  fvec_t *theta1;        /**< previous phase vector, one frame behind */
83  fvec_t *theta2;        /**< previous phase vector, two frames behind */
84  aubio_hist_t * histog; /**< histogram */
85};
86
87
88/* Energy based onset detection function */
89void aubio_specdesc_energy  (aubio_specdesc_t *o UNUSED,
90    cvec_t * fftgrain, fvec_t * onset) {
91  uint_t i,j;
92  for (i=0;i<fftgrain->channels;i++) {
93    onset->data[i][0] = 0.;
94    for (j=0;j<fftgrain->length;j++) {
95      onset->data[i][0] += SQR(fftgrain->norm[i][j]);
96    }
97  }
98}
99
100/* High Frequency Content onset detection function */
101void aubio_specdesc_hfc(aubio_specdesc_t *o UNUSED,
102    cvec_t * fftgrain, fvec_t * onset){
103  uint_t i,j;
104  for (i=0;i<fftgrain->channels;i++) {
105    onset->data[i][0] = 0.;
106    for (j=0;j<fftgrain->length;j++) {
107      onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
108    }
109  }
110}
111
112
113/* Complex Domain Method onset detection function */
114void aubio_specdesc_complex (aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset) {
115  uint_t i, j;
116  uint_t nbins = fftgrain->length;
117  for (i=0;i<fftgrain->channels; i++)  {
118    onset->data[i][0] = 0.;
119    for (j=0;j<nbins; j++)  {
120      // compute the predicted phase
121      o->dev1->data[i][j] = 2. * o->theta1->data[i][j] - o->theta2->data[i][j];
122      // compute the euclidean distance in the complex domain
123      // sqrt ( r_1^2 + r_2^2 - 2 * r_1 * r_2 * \cos ( \phi_1 - \phi_2 ) )
124      onset->data[i][0] +=
125        SQRT (ABS (SQR (o->oldmag->data[i][j]) + SQR (fftgrain->norm[i][j])
126              - 2. * o->oldmag->data[i][j] * fftgrain->norm[i][j]
127              * COS (o->dev1->data[i][j] - fftgrain->phas[i][j])));
128      /* swap old phase data (need to remember 2 frames behind)*/
129      o->theta2->data[i][j] = o->theta1->data[i][j];
130      o->theta1->data[i][j] = fftgrain->phas[i][j];
131      /* swap old magnitude data (1 frame is enough) */
132      o->oldmag->data[i][j] = fftgrain->norm[i][j];
133    }
134  }
135}
136
137
138/* Phase Based Method onset detection function */
139void aubio_specdesc_phase(aubio_specdesc_t *o, 
140    cvec_t * fftgrain, fvec_t * onset){
141  uint_t i, j;
142  uint_t nbins = fftgrain->length;
143  for (i=0;i<fftgrain->channels; i++)  {
144    onset->data[i][0] = 0.0;
145    o->dev1->data[i][0]=0.;
146    for ( j=0;j<nbins; j++ )  {
147      o->dev1->data[i][j] = 
148        aubio_unwrap2pi(
149            fftgrain->phas[i][j]
150            -2.0*o->theta1->data[i][j]
151            +o->theta2->data[i][j]);
152      if ( o->threshold < fftgrain->norm[i][j] )
153        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
154      else 
155        o->dev1->data[i][j] = 0.0;
156      /* keep a track of the past frames */
157      o->theta2->data[i][j] = o->theta1->data[i][j];
158      o->theta1->data[i][j] = fftgrain->phas[i][j];
159    }
160    /* apply o->histogram */
161    aubio_hist_dyn_notnull(o->histog,o->dev1);
162    /* weight it */
163    aubio_hist_weight(o->histog);
164    /* its mean is the result */
165    onset->data[i][0] = aubio_hist_mean(o->histog); 
166    //onset->data[i][0] = fvec_mean(o->dev1);
167  }
168}
169
170/* Spectral difference method onset detection function */
171void aubio_specdesc_specdiff(aubio_specdesc_t *o,
172    cvec_t * fftgrain, fvec_t * onset){
173  uint_t i, j;
174  uint_t nbins = fftgrain->length;
175  for (i=0;i<fftgrain->channels; i++)  {
176    onset->data[i][0] = 0.0;
177    for (j=0;j<nbins; j++)  {
178      o->dev1->data[i][j] = SQRT(
179          ABS(SQR( fftgrain->norm[i][j])
180            - SQR(o->oldmag->data[i][j])));
181      if (o->threshold < fftgrain->norm[i][j] )
182        o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
183      else 
184        o->dev1->data[i][j] = 0.0;
185      o->oldmag->data[i][j] = fftgrain->norm[i][j];
186    }
187
188    /* apply o->histogram (act somewhat as a low pass on the
189     * overall function)*/
190    aubio_hist_dyn_notnull(o->histog,o->dev1);
191    /* weight it */
192    aubio_hist_weight(o->histog);
193    /* its mean is the result */
194    onset->data[i][0] = aubio_hist_mean(o->histog); 
195
196  }
197}
198
199/* Kullback Liebler onset detection function
200 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
201 * negative (1.+) and infinite values (+1.e-10) */
202void aubio_specdesc_kl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){
203  uint_t i,j;
204  for (i=0;i<fftgrain->channels;i++) {
205    onset->data[i][0] = 0.;
206    for (j=0;j<fftgrain->length;j++) {
207      onset->data[i][0] += fftgrain->norm[i][j]
208        *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
209      o->oldmag->data[i][j] = fftgrain->norm[i][j];
210    }
211    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
212  }
213}
214
215/* Modified Kullback Liebler onset detection function
216 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
217 * negative (1.+) and infinite values (+1.e-10) */
218void aubio_specdesc_mkl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){
219  uint_t i,j;
220  for (i=0;i<fftgrain->channels;i++) {
221    onset->data[i][0] = 0.;
222    for (j=0;j<fftgrain->length;j++) {
223      onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
224      o->oldmag->data[i][j] = fftgrain->norm[i][j];
225    }
226    if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
227  }
228}
229
230/* Spectral flux */
231void aubio_specdesc_specflux(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset){ 
232  uint_t i, j;
233  for (i=0;i<fftgrain->channels;i++) {
234    onset->data[i][0] = 0.;
235    for (j=0;j<fftgrain->length;j++) {
236      if (fftgrain->norm[i][j] > o->oldmag->data[i][j])
237        onset->data[i][0] += fftgrain->norm[i][j] - o->oldmag->data[i][j];
238      o->oldmag->data[i][j] = fftgrain->norm[i][j];
239    }
240  }
241}
242
243/* Generic function pointing to the choosen one */
244void 
245aubio_specdesc_do (aubio_specdesc_t *o, cvec_t * fftgrain, 
246    fvec_t * onset) {
247  o->funcpointer(o,fftgrain,onset);
248}
249
250/* Allocate memory for an onset detection
251 * depending on the choosen type, allocate memory as needed
252 */
253aubio_specdesc_t * 
254new_aubio_specdesc (char_t * onset_mode, 
255    uint_t size, uint_t channels){
256  aubio_specdesc_t * o = AUBIO_NEW(aubio_specdesc_t);
257  uint_t rsize = size/2+1;
258  aubio_specdesc_type onset_type;
259  if (strcmp (onset_mode, "energy") == 0)
260      onset_type = aubio_onset_energy;
261  else if (strcmp (onset_mode, "specdiff") == 0)
262      onset_type = aubio_onset_specdiff;
263  else if (strcmp (onset_mode, "hfc") == 0)
264      onset_type = aubio_onset_hfc;
265  else if (strcmp (onset_mode, "complexdomain") == 0)
266      onset_type = aubio_onset_complex;
267  else if (strcmp (onset_mode, "complex") == 0)
268      onset_type = aubio_onset_complex;
269  else if (strcmp (onset_mode, "phase") == 0)
270      onset_type = aubio_onset_phase;
271  else if (strcmp (onset_mode, "mkl") == 0)
272      onset_type = aubio_onset_mkl;
273  else if (strcmp (onset_mode, "kl") == 0)
274      onset_type = aubio_onset_kl;
275  else if (strcmp (onset_mode, "specflux") == 0)
276      onset_type = aubio_onset_specflux;
277  else if (strcmp (onset_mode, "centroid") == 0)
278      onset_type = aubio_specmethod_centroid;
279  else if (strcmp (onset_mode, "spread") == 0)
280      onset_type = aubio_specmethod_spread;
281  else if (strcmp (onset_mode, "skewness") == 0)
282      onset_type = aubio_specmethod_skewness;
283  else if (strcmp (onset_mode, "kurtosis") == 0)
284      onset_type = aubio_specmethod_kurtosis;
285  else if (strcmp (onset_mode, "slope") == 0)
286      onset_type = aubio_specmethod_slope;
287  else if (strcmp (onset_mode, "decrease") == 0)
288      onset_type = aubio_specmethod_decrease;
289  else if (strcmp (onset_mode, "rolloff") == 0)
290      onset_type = aubio_specmethod_rolloff;
291  else if (strcmp (onset_mode, "default") == 0)
292      onset_type = aubio_onset_default;
293  else {
294      AUBIO_ERR("unknown spectral descriptor type %s.\n", onset_mode);
295      onset_type = aubio_onset_default;
296  }
297  switch(onset_type) {
298    /* for both energy and hfc, only fftgrain->norm is required */
299    case aubio_onset_energy: 
300      break;
301    case aubio_onset_hfc:
302      break;
303      /* the other approaches will need some more memory spaces */
304    case aubio_onset_complex:
305      o->oldmag = new_fvec(rsize,channels);
306      o->dev1   = new_fvec(rsize,channels);
307      o->theta1 = new_fvec(rsize,channels);
308      o->theta2 = new_fvec(rsize,channels);
309      break;
310    case aubio_onset_phase:
311      o->dev1   = new_fvec(rsize,channels);
312      o->theta1 = new_fvec(rsize,channels);
313      o->theta2 = new_fvec(rsize,channels);
314      o->histog = new_aubio_hist(0.0, PI, 10, channels);
315      o->threshold = 0.1;
316      break;
317    case aubio_onset_specdiff:
318      o->oldmag = new_fvec(rsize,channels);
319      o->dev1   = new_fvec(rsize,channels);
320      o->histog = new_aubio_hist(0.0, PI, 10, channels);
321      o->threshold = 0.1;
322      break;
323    case aubio_onset_kl:
324    case aubio_onset_mkl:
325    case aubio_onset_specflux:
326      o->oldmag = new_fvec(rsize,channels);
327      break;
328    default:
329      break;
330  }
331
332  /* this switch could be in its own function to change between
333   * detections on the fly. this would need getting rid of the switch
334   * above and always allocate all the structure */
335
336  switch(onset_type) {
337    case aubio_onset_energy:
338      o->funcpointer = aubio_specdesc_energy;
339      break;
340    case aubio_onset_hfc:
341      o->funcpointer = aubio_specdesc_hfc;
342      break;
343    case aubio_onset_complex:
344      o->funcpointer = aubio_specdesc_complex;
345      break;
346    case aubio_onset_phase:
347      o->funcpointer = aubio_specdesc_phase;
348      break;
349    case aubio_onset_specdiff:
350      o->funcpointer = aubio_specdesc_specdiff;
351      break;
352    case aubio_onset_kl:
353      o->funcpointer = aubio_specdesc_kl;
354      break;
355    case aubio_onset_mkl:
356      o->funcpointer = aubio_specdesc_mkl;
357      break;
358    case aubio_onset_specflux:
359      o->funcpointer = aubio_specdesc_specflux;
360      break;
361    // for for the additional descriptors. these don't need additional memory
362    case aubio_specmethod_centroid:
363      o->funcpointer = aubio_specdesc_centroid;
364      break;
365    case aubio_specmethod_spread:
366      o->funcpointer = aubio_specdesc_spread;
367      break;
368    case aubio_specmethod_skewness:
369      o->funcpointer = aubio_specdesc_skewness;
370      break;
371    case aubio_specmethod_kurtosis:
372      o->funcpointer = aubio_specdesc_kurtosis;
373      break;
374    case aubio_specmethod_slope:
375      o->funcpointer = aubio_specdesc_slope;
376      break;
377    case aubio_specmethod_decrease:
378      o->funcpointer = aubio_specdesc_decrease;
379      break;
380    case aubio_specmethod_rolloff:
381      o->funcpointer = aubio_specdesc_rolloff;
382      break;
383    default:
384      break;
385  }
386  o->onset_type = onset_type;
387  return o;
388}
389
390void del_aubio_specdesc (aubio_specdesc_t *o){
391  switch(o->onset_type) {
392    /* for both energy and hfc, only fftgrain->norm is required */
393    case aubio_onset_energy: 
394      break;
395    case aubio_onset_hfc:
396      break;
397      /* the other approaches will need some more memory spaces */
398    case aubio_onset_complex:
399      del_fvec(o->oldmag);
400      del_fvec(o->dev1);
401      del_fvec(o->theta1);
402      del_fvec(o->theta2);
403      break;
404    case aubio_onset_phase:
405      del_fvec(o->dev1);
406      del_fvec(o->theta1);
407      del_fvec(o->theta2);
408      del_aubio_hist(o->histog);
409      break;
410    case aubio_onset_specdiff:
411      del_fvec(o->oldmag);
412      del_fvec(o->dev1);
413      del_aubio_hist(o->histog);
414      break;
415    case aubio_onset_kl:
416    case aubio_onset_mkl:
417    case aubio_onset_specflux:
418      del_fvec(o->oldmag);
419      break;
420    default:
421      break;
422  }
423  AUBIO_FREE(o);
424}
Note: See TracBrowser for help on using the repository browser.