#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 */
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;
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) {
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;
}
--- /dev/null
+/*
+ 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;
+ }
+ }
+}