src/spectral/: added statistics.c, containing some cuidado spectral shape descriptors
authorPaul Brossier <piem@piem.org>
Wed, 4 Nov 2009 21:24:06 +0000 (22:24 +0100)
committerPaul Brossier <piem@piem.org>
Wed, 4 Nov 2009 21:24:06 +0000 (22:24 +0100)
src/Makefile.am
src/aubio.h
src/spectral/specdesc.c
src/spectral/spectral_centroid.c [deleted file]
src/spectral/spectral_centroid.h [deleted file]
src/spectral/statistics.c [new file with mode: 0644]

index 931557e59d36e9fb53b9f313741c5abde450cb86..7baa35dcf8b80dcee78c5ef56f71cdc7bd29ad4d 100644 (file)
@@ -23,7 +23,6 @@ nobase_pkginclude_HEADERS = \
        spectral/fft.h \
        spectral/tss.h \
        spectral/specdesc.h \
-       spectral/spectral_centroid.h \
        pitch/pitch.h \
        pitch/pitchmcomb.h \
        pitch/pitchyin.h \
@@ -57,7 +56,8 @@ libaubio_la_SOURCES = \
        spectral/phasevoc.c \
        spectral/fft.c \
        spectral/tss.c \
-       spectral/spectral_centroid.c \
+       spectral/specdesc.c \
+       spectral/statistics.c \
        pitch/pitch.c \
        pitch/pitchmcomb.c \
        pitch/pitchyin.c \
@@ -65,7 +65,6 @@ libaubio_la_SOURCES = \
        pitch/pitchfcomb.c \
        pitch/pitchyinfft.c \
        onset/onset.c \
-       onset/onsetdetection.c \
        onset/peakpick.c \
        tempo/tempo.c \
        tempo/beattracking.c
index 6008ad4e43efd4bb7dae07a131f5425c9b74fa93..15c2ad369b1b7cb8789949171e7e1890683e01ec 100644 (file)
@@ -183,7 +183,6 @@ extern "C"
 #include "pitch/pitchyinfft.h"
 #include "pitch/pitchschmitt.h"
 #include "pitch/pitchfcomb.h"
-#include "spectral/spectral_centroid.h"
 #include "onset/peakpick.h"
 #include "tempo/beattracking.h"
 #endif
index 684a16cd5eea181a5bc31977b2326d347b4399f8..838188e4a7dc97efabb7426e29ad7ea4bf5d4e78 100644 (file)
 #include "mathutils.h"
 #include "utils/hist.h"
 
-/** Energy based onset detection function 
-  This function calculates the local energy of the input spectral frame.
-  
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_energy(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** High Frequency Content onset detection function
-  This method computes the High Frequency Content (HFC) of the input spectral
-  frame. The resulting function is efficient at detecting percussive onsets.
-
-  Paul Masri. Computer modeling of Sound for Transformation and Synthesis of
-  Musical Signal. PhD dissertation, University of Bristol, UK, 1996.
-  
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_hfc(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Complex Domain Method onset detection function 
-  Christopher Duxbury, Mike E. Davies, and Mark B. Sandler. Complex domain
-  onset detection for musical signals. In Proceedings of the Digital Audio
-  Effects Conference, DAFx-03, pages 90-93, London, UK, 2003.
-
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_complex(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Phase Based Method onset detection function 
-
-  Juan-Pablo Bello, Mike P. Davies, and Mark B. Sandler. Phase-based note onset
-  detection for music signals. In Proceedings of the IEEE International
-  Conference on Acoustics Speech and Signal Processing, pages 441­444,
-  Hong-Kong, 2003.
-
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_phase(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Spectral difference method onset detection function 
-
-  Jonhatan Foote and Shingo Uchihashi. The beat spectrum: a new approach to
-  rhythm analysis. In IEEE International Conference on Multimedia and Expo
-  (ICME 2001), pages 881­884, Tokyo, Japan, August 2001.
-
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_specdiff(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Kullback-Liebler onset detection function 
-  
-  Stephen Hainsworth and Malcom Macleod. Onset detection in music audio
-  signals. In Proceedings of the International Computer Music Conference
-  (ICMC), Singapore, 2003.
-  
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_kl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Modified Kullback-Liebler onset detection function 
-
-  Paul Brossier, ``Automatic annotation of musical audio for interactive
-  systems'', Chapter 2, Temporal segmentation, PhD thesis, Centre for Digital
-  music, Queen Mary University of London, London, UK, 2006.
-
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_mkl(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** Spectral Flux 
-
-  Simon Dixon, Onset Detection Revisited, in ``Proceedings of the 9th
-  International Conference on Digital Audio Effects'' (DAFx-06), Montreal,
-  Canada, 2006. 
-
-  \param o onset detection object as returned by new_aubio_specdesc()
-  \param fftgrain input spectral frame
-  \param onset output onset detection function
-
-*/
 void aubio_specdesc_specflux(aubio_specdesc_t *o, cvec_t * fftgrain, fvec_t * onset);
 
+extern void aubio_specdesc_centroid (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_spread (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_skewness (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_kurtosis (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_slope (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_decrease (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+extern void aubio_specdesc_rolloff (aubio_specdesc_t * o, cvec_t * spec,
+    fvec_t * desc);
+
 /** onsetdetection types */
 typedef enum {
         aubio_onset_energy,         /**< energy based */          
@@ -134,6 +60,13 @@ typedef enum {
         aubio_onset_kl,             /**< Kullback Liebler */
         aubio_onset_mkl,            /**< modified Kullback Liebler */
         aubio_onset_specflux,       /**< spectral flux */
+        aubio_specmethod_centroid,  /**< spectral centroid */
+        aubio_specmethod_spread,    /**< spectral spread */
+        aubio_specmethod_skewness,  /**< spectral skewness */
+        aubio_specmethod_kurtosis,  /**< spectral kurtosis */
+        aubio_specmethod_slope,     /**< spectral kurtosis */
+        aubio_specmethod_decrease,  /**< spectral decrease */
+        aubio_specmethod_rolloff,   /**< spectral rolloff */
         aubio_onset_default = aubio_onset_hfc, /**< default mode, set to hfc */
 } aubio_specdesc_type;
 
@@ -341,10 +274,24 @@ new_aubio_specdesc (char_t * onset_mode,
       onset_type = aubio_onset_kl;
   else if (strcmp (onset_mode, "specflux") == 0)
       onset_type = aubio_onset_specflux;
+  else if (strcmp (onset_mode, "centroid") == 0)
+      onset_type = aubio_specmethod_centroid;
+  else if (strcmp (onset_mode, "spread") == 0)
+      onset_type = aubio_specmethod_spread;
+  else if (strcmp (onset_mode, "skewness") == 0)
+      onset_type = aubio_specmethod_skewness;
+  else if (strcmp (onset_mode, "kurtosis") == 0)
+      onset_type = aubio_specmethod_kurtosis;
+  else if (strcmp (onset_mode, "slope") == 0)
+      onset_type = aubio_specmethod_slope;
+  else if (strcmp (onset_mode, "decrease") == 0)
+      onset_type = aubio_specmethod_decrease;
+  else if (strcmp (onset_mode, "rolloff") == 0)
+      onset_type = aubio_specmethod_rolloff;
   else if (strcmp (onset_mode, "default") == 0)
       onset_type = aubio_onset_default;
   else {
-      AUBIO_ERR("unknown onset type.\n");
+      AUBIO_ERR("unknown spectral descriptor type %s.\n", onset_mode);
       onset_type = aubio_onset_default;
   }
   switch(onset_type) {
@@ -411,6 +358,28 @@ new_aubio_specdesc (char_t * onset_mode,
     case aubio_onset_specflux:
       o->funcpointer = aubio_specdesc_specflux;
       break;
+    // for for the additional descriptors. these don't need additional memory
+    case aubio_specmethod_centroid:
+      o->funcpointer = aubio_specdesc_centroid;
+      break;
+    case aubio_specmethod_spread:
+      o->funcpointer = aubio_specdesc_spread;
+      break;
+    case aubio_specmethod_skewness:
+      o->funcpointer = aubio_specdesc_skewness;
+      break;
+    case aubio_specmethod_kurtosis:
+      o->funcpointer = aubio_specdesc_kurtosis;
+      break;
+    case aubio_specmethod_slope:
+      o->funcpointer = aubio_specdesc_slope;
+      break;
+    case aubio_specmethod_decrease:
+      o->funcpointer = aubio_specdesc_decrease;
+      break;
+    case aubio_specmethod_rolloff:
+      o->funcpointer = aubio_specdesc_rolloff;
+      break;
     default:
       break;
   }
diff --git a/src/spectral/spectral_centroid.c b/src/spectral/spectral_centroid.c
deleted file mode 100644 (file)
index a9227c9..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  Copyright (C) 2007-2009 Paul Brossier <piem@aubio.org>
-
-  This file is part of aubio.
-
-  aubio is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  aubio is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "aubio_priv.h"
-#include "cvec.h"
-#include "spectral/spectral_centroid.h"
-
-smpl_t aubio_spectral_centroid(cvec_t * spectrum, smpl_t samplerate) {
-  uint_t i=0, j;
-  smpl_t sum = 0., sc = 0.;
-  for ( j = 0; j < spectrum->length; j++ ) {
-    sum += spectrum->norm[i][j];
-  }
-  if (sum == 0.) return 0.;
-  for ( j = 0; j < spectrum->length; j++ ) {
-    sc += (smpl_t)j * spectrum->norm[i][j];
-  }
-  return sc / sum * samplerate / (smpl_t)(spectrum->length);
-}
-
-
diff --git a/src/spectral/spectral_centroid.h b/src/spectral/spectral_centroid.h
deleted file mode 100644 (file)
index a841c1f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-  Copyright (C) 2007-2009 Paul Brossier <piem@aubio.org>
-
-  This file is part of aubio.
-
-  aubio is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  aubio is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-/** @file
- * compute spectrum centroid of a cvec object
- */
-
-#ifndef _SPECTRAL_CENTROID_H
-#define _SPECTRAL_CENTROID_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * spectrum centroid computed on a cvec
- */
-smpl_t aubio_spectral_centroid(cvec_t * input, smpl_t samplerate);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SPECTRAL_CENTROID_H */
diff --git a/src/spectral/statistics.c b/src/spectral/statistics.c
new file mode 100644 (file)
index 0000000..9315050
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+  Copyright (C) 2007-2009 Paul Brossier <piem@aubio.org>
+
+  This file is part of aubio.
+
+  aubio is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  aubio is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "aubio_priv.h"
+#include "cvec.h"
+#include "spectral/specdesc.h"
+
+smpl_t
+cvec_sum_channel (cvec_t * s, uint_t i)
+{
+  uint_t j;
+  smpl_t tmp = 0.0;
+  for (j = 0; j < s->length; j++)
+      tmp += s->norm[i][j];
+  return tmp;
+}
+
+smpl_t
+cvec_mean_channel (cvec_t * s, uint_t i)
+{
+  return cvec_sum_channel(s, i) / (smpl_t) (s->length);
+}
+
+smpl_t
+cvec_centroid_channel (cvec_t * spec, uint_t i)
+{
+  smpl_t sum = 0., sc = 0.;
+  uint_t j;
+  sum = cvec_sum_channel (spec, i); 
+  if (sum == 0.) {
+    return 0.;
+  } else {
+    for (j = 0; j < spec->length; j++) {
+      sc += (smpl_t) j *spec->norm[i][j];
+    }
+    return sc / sum;
+  }
+}
+
+smpl_t
+cvec_moment_channel (cvec_t * spec, uint_t i, uint_t order)
+{
+  smpl_t sum = 0., centroid = 0., sc = 0.;
+  uint_t j;
+  sum = cvec_sum_channel (spec, i); 
+  if (sum == 0.) {
+    return 0.;
+  } else {
+    centroid = cvec_centroid_channel (spec, i);
+    for (j = 0; j < spec->length; j++) {
+      sc += (smpl_t) POW(j - centroid, order) * spec->norm[i][j];
+    }
+    return sc / sum;
+  }
+}
+
+void
+aubio_specdesc_centroid (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i;
+  for (i = 0; i < spec->channels; i++) {
+    desc->data[i][0] = cvec_centroid_channel (spec, i); 
+  }
+}
+
+void
+aubio_specdesc_spread (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i;
+  for (i = 0; i < spec->channels; i++) {
+    desc->data[i][0] = cvec_moment_channel (spec, i, 2);
+  }
+}
+
+void
+aubio_specdesc_skewness (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i; smpl_t spread;
+  for (i = 0; i < spec->channels; i++) {
+    spread = cvec_moment_channel (spec, i, 2);
+    if (spread == 0) {
+      desc->data[i][0] = 0.;
+    } else {
+      desc->data[i][0] = cvec_moment_channel (spec, i, 3);
+      desc->data[i][0] /= POW ( SQRT (spread), 3);
+    }
+  }
+}
+
+void
+aubio_specdesc_kurtosis (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i; smpl_t spread;
+  for (i = 0; i < spec->channels; i++) {
+    spread = cvec_moment_channel (spec, i, 2);
+    if (spread == 0) {
+      desc->data[i][0] = 0.;
+    } else {
+      desc->data[i][0] = cvec_moment_channel (spec, i, 4);
+      desc->data[i][0] /= SQR (spread);
+    }
+  }
+}
+
+void
+aubio_specdesc_slope (aubio_specdesc_t * o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i, j;
+  smpl_t norm = 0, sum = 0.; 
+  // compute N * sum(j**2) - sum(j)**2
+  for (j = 0; j < spec->length; j++) {
+    norm += j*j;
+  }
+  norm *= spec->length;
+  // sum_0^N(j) = length * (length + 1) / 2
+  norm -= SQR( (spec->length) * (spec->length - 1.) / 2. );
+  for (i = 0; i < spec->channels; i++) {
+    sum = cvec_sum_channel (spec, i); 
+    desc->data[i][0] = 0.;
+    if (sum == 0.) {
+      break; 
+    } else {
+      for (j = 0; j < spec->length; j++) {
+        desc->data[i][0] += j * spec->norm[i][j]; 
+      }
+      desc->data[i][0] *= spec->length;
+      desc->data[i][0] -= sum * spec->length * (spec->length - 1) / 2.;
+      desc->data[i][0] /= norm;
+      desc->data[i][0] /= sum;
+    }
+  }
+}
+
+void
+aubio_specdesc_decrease (aubio_specdesc_t *o UNUSED, cvec_t * spec,
+    fvec_t * desc)
+{
+  uint_t i, j; smpl_t sum;
+  for (i = 0; i < spec->channels; i++) {
+    sum = cvec_sum_channel (spec, i); 
+    desc->data[i][0] = 0;
+    if (sum == 0.) {
+      break;
+    } else {
+      sum -= spec->norm[i][0];
+      for (j = 1; j < spec->length; j++) {
+        desc->data[i][0] += (spec->norm[i][j] - spec->norm[i][0]) / j;
+      }
+      desc->data[i][0] /= sum;
+    }
+  }
+}
+
+void
+aubio_specdesc_rolloff (aubio_specdesc_t *o UNUSED, cvec_t * spec,
+    fvec_t *desc)
+{
+  uint_t i, j; smpl_t cumsum, rollsum;
+  for (i = 0; i < spec->channels; i++) {
+    cumsum = 0.; rollsum = 0.;
+    for (j = 0; j < spec->length; j++) {
+      cumsum += SQR (spec->norm[i][j]);
+    }
+    if (cumsum == 0) {
+      desc->data[i][0] = 0.;
+    } else {
+      cumsum *= 0.95;
+      j = 0;
+      while (rollsum < cumsum) { 
+        rollsum += SQR (spec->norm[i][j]);
+        j++;
+      }
+      desc->data[i][0] = j;
+    }
+  }
+}