source: src/spectral/specdesc.c @ 2763582

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 2763582 was 2763582, checked in by Paul Brossier <piem@piem.org>, 3 years ago

src/spectral/specdesc.c: return NULL if wrong mode asked

  • Property mode set to 100644
File size: 13.7 KB
RevLine 
[96fb8ad]1/*
[e6a78ea]2  Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
[96fb8ad]3
[e6a78ea]4  This file is part of aubio.
[96fb8ad]5
[e6a78ea]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.
[96fb8ad]10
[e6a78ea]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/>.
[96fb8ad]18
19*/
20
21#include "aubio_priv.h"
[6c7d49b]22#include "fvec.h"
23#include "cvec.h"
[32d6958]24#include "spectral/fft.h"
[31907fd]25#include "spectral/specdesc.h"
[96fb8ad]26#include "mathutils.h"
[32d6958]27#include "utils/hist.h"
[96fb8ad]28
[feb694b]29void aubio_specdesc_energy(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
30void aubio_specdesc_hfc(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
31void aubio_specdesc_complex(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
32void aubio_specdesc_phase(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
33void aubio_specdesc_specdiff(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
34void aubio_specdesc_kl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
35void aubio_specdesc_mkl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
36void aubio_specdesc_specflux(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset);
[96fb8ad]37
[feb694b]38extern void aubio_specdesc_centroid (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]39    fvec_t * desc);
[feb694b]40extern void aubio_specdesc_spread (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]41    fvec_t * desc);
[feb694b]42extern void aubio_specdesc_skewness (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]43    fvec_t * desc);
[feb694b]44extern void aubio_specdesc_kurtosis (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]45    fvec_t * desc);
[feb694b]46extern void aubio_specdesc_slope (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]47    fvec_t * desc);
[feb694b]48extern void aubio_specdesc_decrease (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]49    fvec_t * desc);
[feb694b]50extern void aubio_specdesc_rolloff (aubio_specdesc_t * o, const cvec_t * spec,
[1651b58]51    fvec_t * desc);
52
[b4f5967]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 */
[1651b58]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 */
[cd77c15]70        aubio_onset_default = aubio_onset_hfc, /**< default mode, set to hfc */
[31907fd]71} aubio_specdesc_type;
[b4f5967]72
[b740b96]73/** structure to store object state */
[31907fd]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,
[feb694b]78      const cvec_t * fftgrain, fvec_t * onset);
[b740b96]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 */
[96fb8ad]85};
86
87
88/* Energy based onset detection function */
[31907fd]89void aubio_specdesc_energy  (aubio_specdesc_t *o UNUSED,
[feb694b]90    const cvec_t * fftgrain, fvec_t * onset) {
[d95ff38]91  uint_t j;
92  onset->data[0] = 0.;
93  for (j=0;j<fftgrain->length;j++) {
94    onset->data[0] += SQR(fftgrain->norm[j]);
[ec2fa2a]95  }
[96fb8ad]96}
97
98/* High Frequency Content onset detection function */
[31907fd]99void aubio_specdesc_hfc(aubio_specdesc_t *o UNUSED,
[feb694b]100    const cvec_t * fftgrain, fvec_t * onset){
[d95ff38]101  uint_t j;
102  onset->data[0] = 0.;
103  for (j=0;j<fftgrain->length;j++) {
104    onset->data[0] += (j+1)*fftgrain->norm[j];
[ec2fa2a]105  }
[96fb8ad]106}
107
108
109/* Complex Domain Method onset detection function */
[feb694b]110void aubio_specdesc_complex (aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset) {
[d95ff38]111  uint_t j;
[ec2fa2a]112  uint_t nbins = fftgrain->length;
[d95ff38]113  onset->data[0] = 0.;
114  for (j=0;j<nbins; j++)  {
115    // compute the predicted phase
116    o->dev1->data[j] = 2. * o->theta1->data[j] - o->theta2->data[j];
117    // compute the euclidean distance in the complex domain
118    // sqrt ( r_1^2 + r_2^2 - 2 * r_1 * r_2 * \cos ( \phi_1 - \phi_2 ) )
119    onset->data[0] +=
120      SQRT (ABS (SQR (o->oldmag->data[j]) + SQR (fftgrain->norm[j])
[053495b]121            - 2 * o->oldmag->data[j] * fftgrain->norm[j]
[d95ff38]122            * COS (o->dev1->data[j] - fftgrain->phas[j])));
123    /* swap old phase data (need to remember 2 frames behind)*/
124    o->theta2->data[j] = o->theta1->data[j];
125    o->theta1->data[j] = fftgrain->phas[j];
126    /* swap old magnitude data (1 frame is enough) */
127    o->oldmag->data[j] = fftgrain->norm[j];
[ec2fa2a]128  }
[96fb8ad]129}
130
131
132/* Phase Based Method onset detection function */
[31907fd]133void aubio_specdesc_phase(aubio_specdesc_t *o, 
[feb694b]134    const cvec_t * fftgrain, fvec_t * onset){
[d95ff38]135  uint_t j;
[ec2fa2a]136  uint_t nbins = fftgrain->length;
[d95ff38]137  onset->data[0] = 0.0;
138  o->dev1->data[0]=0.;
139  for ( j=0;j<nbins; j++ )  {
140    o->dev1->data[j] = 
141      aubio_unwrap2pi(
142          fftgrain->phas[j]
143          -2.0*o->theta1->data[j]
144          +o->theta2->data[j]);
145    if ( o->threshold < fftgrain->norm[j] )
146      o->dev1->data[j] = ABS(o->dev1->data[j]);
147    else 
148      o->dev1->data[j] = 0.0;
149    /* keep a track of the past frames */
150    o->theta2->data[j] = o->theta1->data[j];
151    o->theta1->data[j] = fftgrain->phas[j];
[ec2fa2a]152  }
[d95ff38]153  /* apply o->histogram */
154  aubio_hist_dyn_notnull(o->histog,o->dev1);
155  /* weight it */
156  aubio_hist_weight(o->histog);
157  /* its mean is the result */
158  onset->data[0] = aubio_hist_mean(o->histog); 
159  //onset->data[0] = fvec_mean(o->dev1);
[96fb8ad]160}
161
162/* Spectral difference method onset detection function */
[31907fd]163void aubio_specdesc_specdiff(aubio_specdesc_t *o,
[feb694b]164    const cvec_t * fftgrain, fvec_t * onset){
[d95ff38]165  uint_t j;
[ec2fa2a]166  uint_t nbins = fftgrain->length;
[d95ff38]167    onset->data[0] = 0.0;
[ec2fa2a]168    for (j=0;j<nbins; j++)  {
[d95ff38]169      o->dev1->data[j] = SQRT(
170          ABS(SQR( fftgrain->norm[j])
171            - SQR(o->oldmag->data[j])));
172      if (o->threshold < fftgrain->norm[j] )
173        o->dev1->data[j] = ABS(o->dev1->data[j]);
[ec2fa2a]174      else 
[d95ff38]175        o->dev1->data[j] = 0.0;
176      o->oldmag->data[j] = fftgrain->norm[j];
[ec2fa2a]177    }
[96fb8ad]178
[ec2fa2a]179    /* apply o->histogram (act somewhat as a low pass on the
180     * overall function)*/
181    aubio_hist_dyn_notnull(o->histog,o->dev1);
182    /* weight it */
183    aubio_hist_weight(o->histog);
184    /* its mean is the result */
[d95ff38]185    onset->data[0] = aubio_hist_mean(o->histog); 
[96fb8ad]186}
187
[b31f262]188/* Kullback Liebler onset detection function
189 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
190 * negative (1.+) and infinite values (+1.e-10) */
[feb694b]191void aubio_specdesc_kl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){
[d95ff38]192  uint_t j;
193    onset->data[0] = 0.;
[ec2fa2a]194    for (j=0;j<fftgrain->length;j++) {
[d95ff38]195      onset->data[0] += fftgrain->norm[j]
[4f872d7]196        *LOG(1.+fftgrain->norm[j]/(o->oldmag->data[j]+1.e-1));
[d95ff38]197      o->oldmag->data[j] = fftgrain->norm[j];
[ec2fa2a]198    }
[d95ff38]199    if (isnan(onset->data[0])) onset->data[0] = 0.;
[b31f262]200}
201
202/* Modified Kullback Liebler onset detection function
203 * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
204 * negative (1.+) and infinite values (+1.e-10) */
[feb694b]205void aubio_specdesc_mkl(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){
[d95ff38]206  uint_t j;
207    onset->data[0] = 0.;
[ec2fa2a]208    for (j=0;j<fftgrain->length;j++) {
[4f872d7]209      onset->data[0] += LOG(1.+fftgrain->norm[j]/(o->oldmag->data[j]+1.e-1));
[d95ff38]210      o->oldmag->data[j] = fftgrain->norm[j];
[ec2fa2a]211    }
[d95ff38]212    if (isnan(onset->data[0])) onset->data[0] = 0.;
[b31f262]213}
214
[fabb7cd]215/* Spectral flux */
[feb694b]216void aubio_specdesc_specflux(aubio_specdesc_t *o, const cvec_t * fftgrain, fvec_t * onset){ 
[d95ff38]217  uint_t j;
218  onset->data[0] = 0.;
219  for (j=0;j<fftgrain->length;j++) {
220    if (fftgrain->norm[j] > o->oldmag->data[j])
221      onset->data[0] += fftgrain->norm[j] - o->oldmag->data[j];
222    o->oldmag->data[j] = fftgrain->norm[j];
[fabb7cd]223  }
224}
225
[96fb8ad]226/* Generic function pointing to the choosen one */
227void 
[feb694b]228aubio_specdesc_do (aubio_specdesc_t *o, const cvec_t * fftgrain, 
[ec2fa2a]229    fvec_t * onset) {
230  o->funcpointer(o,fftgrain,onset);
[96fb8ad]231}
232
[c621415]233/* Allocate memory for an onset detection
234 * depending on the choosen type, allocate memory as needed
235 */
[31907fd]236aubio_specdesc_t * 
[feb694b]237new_aubio_specdesc (const char_t * onset_mode, uint_t size){
[31907fd]238  aubio_specdesc_t * o = AUBIO_NEW(aubio_specdesc_t);
[ec2fa2a]239  uint_t rsize = size/2+1;
[31907fd]240  aubio_specdesc_type onset_type;
[b4f5967]241  if (strcmp (onset_mode, "energy") == 0)
242      onset_type = aubio_onset_energy;
243  else if (strcmp (onset_mode, "specdiff") == 0)
244      onset_type = aubio_onset_specdiff;
245  else if (strcmp (onset_mode, "hfc") == 0)
246      onset_type = aubio_onset_hfc;
247  else if (strcmp (onset_mode, "complexdomain") == 0)
248      onset_type = aubio_onset_complex;
249  else if (strcmp (onset_mode, "complex") == 0)
250      onset_type = aubio_onset_complex;
251  else if (strcmp (onset_mode, "phase") == 0)
252      onset_type = aubio_onset_phase;
253  else if (strcmp (onset_mode, "mkl") == 0)
254      onset_type = aubio_onset_mkl;
255  else if (strcmp (onset_mode, "kl") == 0)
256      onset_type = aubio_onset_kl;
257  else if (strcmp (onset_mode, "specflux") == 0)
258      onset_type = aubio_onset_specflux;
[1651b58]259  else if (strcmp (onset_mode, "centroid") == 0)
260      onset_type = aubio_specmethod_centroid;
261  else if (strcmp (onset_mode, "spread") == 0)
262      onset_type = aubio_specmethod_spread;
263  else if (strcmp (onset_mode, "skewness") == 0)
264      onset_type = aubio_specmethod_skewness;
265  else if (strcmp (onset_mode, "kurtosis") == 0)
266      onset_type = aubio_specmethod_kurtosis;
267  else if (strcmp (onset_mode, "slope") == 0)
268      onset_type = aubio_specmethod_slope;
269  else if (strcmp (onset_mode, "decrease") == 0)
270      onset_type = aubio_specmethod_decrease;
271  else if (strcmp (onset_mode, "rolloff") == 0)
272      onset_type = aubio_specmethod_rolloff;
[cd77c15]273  else if (strcmp (onset_mode, "default") == 0)
274      onset_type = aubio_onset_default;
[b4f5967]275  else {
[2763582]276      AUBIO_ERR("unknown spectral descriptor type %s\n", onset_mode);
277      AUBIO_FREE(o);
278      return NULL;
[b4f5967]279  }
280  switch(onset_type) {
[ec2fa2a]281    /* for both energy and hfc, only fftgrain->norm is required */
[bf1c0e43]282    case aubio_onset_energy:
[ec2fa2a]283      break;
284    case aubio_onset_hfc:
285      break;
286      /* the other approaches will need some more memory spaces */
287    case aubio_onset_complex:
[d95ff38]288      o->oldmag = new_fvec(rsize);
289      o->dev1   = new_fvec(rsize);
290      o->theta1 = new_fvec(rsize);
291      o->theta2 = new_fvec(rsize);
[ec2fa2a]292      break;
293    case aubio_onset_phase:
[d95ff38]294      o->dev1   = new_fvec(rsize);
295      o->theta1 = new_fvec(rsize);
296      o->theta2 = new_fvec(rsize);
297      o->histog = new_aubio_hist(0.0, PI, 10);
[ec2fa2a]298      o->threshold = 0.1;
299      break;
300    case aubio_onset_specdiff:
[d95ff38]301      o->oldmag = new_fvec(rsize);
302      o->dev1   = new_fvec(rsize);
303      o->histog = new_aubio_hist(0.0, PI, 10);
[ec2fa2a]304      o->threshold = 0.1;
305      break;
306    case aubio_onset_kl:
307    case aubio_onset_mkl:
[fabb7cd]308    case aubio_onset_specflux:
[d95ff38]309      o->oldmag = new_fvec(rsize);
[ec2fa2a]310      break;
311    default:
312      break;
313  }
[96fb8ad]314
[b4f5967]315  switch(onset_type) {
[ec2fa2a]316    case aubio_onset_energy:
[31907fd]317      o->funcpointer = aubio_specdesc_energy;
[ec2fa2a]318      break;
319    case aubio_onset_hfc:
[31907fd]320      o->funcpointer = aubio_specdesc_hfc;
[ec2fa2a]321      break;
322    case aubio_onset_complex:
[31907fd]323      o->funcpointer = aubio_specdesc_complex;
[ec2fa2a]324      break;
325    case aubio_onset_phase:
[31907fd]326      o->funcpointer = aubio_specdesc_phase;
[ec2fa2a]327      break;
328    case aubio_onset_specdiff:
[31907fd]329      o->funcpointer = aubio_specdesc_specdiff;
[ec2fa2a]330      break;
331    case aubio_onset_kl:
[31907fd]332      o->funcpointer = aubio_specdesc_kl;
[ec2fa2a]333      break;
334    case aubio_onset_mkl:
[31907fd]335      o->funcpointer = aubio_specdesc_mkl;
[ec2fa2a]336      break;
[fabb7cd]337    case aubio_onset_specflux:
[31907fd]338      o->funcpointer = aubio_specdesc_specflux;
[fabb7cd]339      break;
[1651b58]340    case aubio_specmethod_centroid:
341      o->funcpointer = aubio_specdesc_centroid;
342      break;
343    case aubio_specmethod_spread:
344      o->funcpointer = aubio_specdesc_spread;
345      break;
346    case aubio_specmethod_skewness:
347      o->funcpointer = aubio_specdesc_skewness;
348      break;
349    case aubio_specmethod_kurtosis:
350      o->funcpointer = aubio_specdesc_kurtosis;
351      break;
352    case aubio_specmethod_slope:
353      o->funcpointer = aubio_specdesc_slope;
354      break;
355    case aubio_specmethod_decrease:
356      o->funcpointer = aubio_specdesc_decrease;
357      break;
358    case aubio_specmethod_rolloff:
359      o->funcpointer = aubio_specdesc_rolloff;
360      break;
[ec2fa2a]361    default:
362      break;
363  }
[b4f5967]364  o->onset_type = onset_type;
[ec2fa2a]365  return o;
[96fb8ad]366}
367
[31907fd]368void del_aubio_specdesc (aubio_specdesc_t *o){
[b4f5967]369  switch(o->onset_type) {
[bf1c0e43]370    case aubio_onset_energy:
[ec2fa2a]371      break;
372    case aubio_onset_hfc:
373      break;
374    case aubio_onset_complex:
375      del_fvec(o->oldmag);
376      del_fvec(o->dev1);
377      del_fvec(o->theta1);
378      del_fvec(o->theta2);
379      break;
380    case aubio_onset_phase:
381      del_fvec(o->dev1);
382      del_fvec(o->theta1);
383      del_fvec(o->theta2);
384      del_aubio_hist(o->histog);
385      break;
386    case aubio_onset_specdiff:
387      del_fvec(o->oldmag);
388      del_fvec(o->dev1);
389      del_aubio_hist(o->histog);
390      break;
391    case aubio_onset_kl:
392    case aubio_onset_mkl:
[e2da295]393    case aubio_onset_specflux:
[ec2fa2a]394      del_fvec(o->oldmag);
395      break;
396    default:
397      break;
398  }
399  AUBIO_FREE(o);
[96fb8ad]400}
Note: See TracBrowser for help on using the repository browser.