ref: 1651b58b304306342c74fbf5e60e994f5b17f27b
parent: 95d3f164d2d2601a18df0c474456c9fb921d821b
author: Paul Brossier <piem@piem.org>
date: Wed Nov 4 17:24:06 EST 2009
src/spectral/: added statistics.c, containing some cuidado spectral shape descriptors
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,6 @@
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 @@
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 @@
pitch/pitchfcomb.c \
pitch/pitchyinfft.c \
onset/onset.c \
- onset/onsetdetection.c \
onset/peakpick.c \
tempo/tempo.c \
tempo/beattracking.c
--- a/src/aubio.h
+++ b/src/aubio.h
@@ -183,7 +183,6 @@
#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
--- a/src/spectral/specdesc.c
+++ b/src/spectral/specdesc.c
@@ -26,104 +26,30 @@
#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 441444,
- 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 881884, 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 @@
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 @@
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) {
@@ -410,6 +357,28 @@
break;
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;
--- a/src/spectral/spectral_centroid.c
+++ /dev/null
@@ -1,38 +1,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);
-}
-
-
--- a/src/spectral/spectral_centroid.h
+++ /dev/null
@@ -1,41 +1,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 */
--- /dev/null
+++ b/src/spectral/statistics.c
@@ -1,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;
+ }
+ }
+}