ref: 2d8cffabb484b5bee7d4d44c8f753d95ca841d03
parent: 5dd22a923ed25c385223231be4bb48d4acce9c2b
author: Paul Brossier <piem@piem.org>
date: Sat Nov 24 15:47:55 EST 2007
move pitch methods to pitch/, onset detection functions to onset/
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,16 +10,16 @@
hist.h \
scale.h \
resample.h \
- onsetdetection.h \
+ onset/onsetdetection.h \
tss.h \
peakpick.h \
biquad.h \
pitchdetection.h \
- pitchmcomb.h \
- pitchyin.h \
- pitchschmitt.h \
- pitchfcomb.h \
- pitchyinfft.h \
+ pitch/pitchmcomb.h \
+ pitch/pitchyin.h \
+ pitch/pitchschmitt.h \
+ pitch/pitchfcomb.h \
+ pitch/pitchyinfft.h \
beattracking.h \
onset.h \
tempo.h \
@@ -48,8 +48,8 @@
scale.h \
resample.c \
resample.h \
- onsetdetection.c \
- onsetdetection.h \
+ onset/onsetdetection.c \
+ onset/onsetdetection.h \
tss.c \
tss.h \
peakpick.c \
@@ -58,16 +58,16 @@
biquad.h \
pitchdetection.c \
pitchdetection.h \
- pitchmcomb.c \
- pitchmcomb.h \
- pitchyin.c \
- pitchyin.h \
- pitchschmitt.c \
- pitchschmitt.h \
- pitchfcomb.c \
- pitchfcomb.h \
- pitchyinfft.c \
- pitchyinfft.h \
+ pitch/pitchmcomb.c \
+ pitch/pitchmcomb.h \
+ pitch/pitchyin.c \
+ pitch/pitchyin.h \
+ pitch/pitchschmitt.c \
+ pitch/pitchschmitt.h \
+ pitch/pitchfcomb.c \
+ pitch/pitchfcomb.h \
+ pitch/pitchyinfft.c \
+ pitch/pitchyinfft.h \
beattracking.c \
beattracking.h \
onset.c \
--- a/src/aubio.h
+++ b/src/aubio.h
@@ -64,7 +64,6 @@
#include "mathutils.h"
#include "scale.h"
#include "hist.h"
-#include "onsetdetection.h"
#include "tss.h"
#include "resample.h"
#include "peakpick.h"
@@ -71,12 +70,13 @@
#include "biquad.h"
#include "filter.h"
#include "pitchdetection.h"
-#include "pitchmcomb.h"
-#include "pitchyin.h"
-#include "pitchyinfft.h"
-#include "pitchschmitt.h"
-#include "pitchfcomb.h"
+#include "pitch/pitchmcomb.h"
+#include "pitch/pitchyin.h"
+#include "pitch/pitchyinfft.h"
+#include "pitch/pitchschmitt.h"
+#include "pitch/pitchfcomb.h"
#include "beattracking.h"
+#include "onset/detection.h"
#include "onset.h"
#include "tempo.h"
#include "filterbank.h"
--- a/src/filterbank.h
+++ b/src/filterbank.h
@@ -32,6 +32,7 @@
extern "C" {
#endif
+/** filterbank object */
typedef struct aubio_filterbank_t_ aubio_filterbank_t;
/** create filterbank object
--- a/src/onset.c
+++ b/src/onset.c
@@ -19,7 +19,7 @@
#include "aubio_priv.h"
#include "sample.h"
-#include "onsetdetection.h"
+#include "onset/detection.h"
#include "phasevoc.h"
#include "peakpick.h"
#include "mathutils.h"
--- /dev/null
+++ b/src/onset/onsetdetection.c
@@ -1,0 +1,337 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "fft.h"
+#include "mathutils.h"
+#include "hist.h"
+#include "onset/onsetdetection.h"
+
+
+/** structure to store object state */
+struct _aubio_onsetdetection_t {
+ aubio_onsetdetection_type type; /**< onset detection type */
+ /** Pointer to aubio_onsetdetection_<type> function */
+ void (*funcpointer)(aubio_onsetdetection_t *o,
+ cvec_t * fftgrain, fvec_t * onset);
+ smpl_t threshold; /**< minimum norm threshold for phase and specdiff */
+ fvec_t *oldmag; /**< previous norm vector */
+ fft_data_t *meas; /**< current onset detection measure complex vector */
+ fvec_t *dev1 ; /**< current onset detection measure vector */
+ fvec_t *theta1; /**< previous phase vector, one frame behind */
+ fvec_t *theta2; /**< previous phase vector, two frames behind */
+ aubio_hist_t * histog; /**< histogram */
+};
+
+
+/* Energy based onset detection function */
+void aubio_onsetdetection_energy (aubio_onsetdetection_t *o UNUSED,
+ cvec_t * fftgrain, fvec_t * onset) {
+ uint_t i,j;
+ for (i=0;i<fftgrain->channels;i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<fftgrain->length;j++) {
+ onset->data[i][0] += SQR(fftgrain->norm[i][j]);
+ }
+ }
+}
+
+/* High Frequency Content onset detection function */
+void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o UNUSED,
+ cvec_t * fftgrain, fvec_t * onset){
+ uint_t i,j;
+ for (i=0;i<fftgrain->channels;i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<fftgrain->length;j++) {
+ onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
+ }
+ }
+}
+
+
+/* Complex Domain Method onset detection function */
+void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
+ uint_t i, j;
+ uint_t nbins = fftgrain->length;
+ for (i=0;i<fftgrain->channels; i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<nbins; j++) {
+ o->dev1->data[i][j] = aubio_unwrap2pi(
+ fftgrain->phas[i][j]
+ -2.0*o->theta1->data[i][j]+
+ o->theta2->data[i][j]);
+#ifdef HAVE_COMPLEX_H
+ o->meas[j] = fftgrain->norm[i][j]*CEXPC(I*o->dev1->data[i][j]);
+ /* sum on all bins */
+ onset->data[i][0] += //(fftgrain->norm[i][j]);
+ SQRT(SQR( REAL(o->oldmag->data[i][j]-o->meas[j]) )
+ + SQR( IMAG(o->oldmag->data[i][j]-o->meas[j]) )
+ );
+#else
+ o->meas[j] = (fftgrain->norm[i][j])*COS(o->dev1->data[i][j]);
+ o->meas[(nbins-1)*2-j] = (fftgrain->norm[i][j])*SIN(o->dev1->data[i][j]);
+ /* sum on all bins */
+ onset->data[i][0] += //(fftgrain->norm[i][j]);
+ SQRT(SQR( (o->oldmag->data[i][j]-o->meas[j]) )
+ + SQR( (-o->meas[(nbins-1)*2-j]) )
+ );
+#endif
+ /* swap old phase data (need to remember 2 frames behind)*/
+ o->theta2->data[i][j] = o->theta1->data[i][j];
+ o->theta1->data[i][j] = fftgrain->phas[i][j];
+ /* swap old magnitude data (1 frame is enough) */
+ o->oldmag->data[i][j] = fftgrain->norm[i][j];
+ }
+ }
+}
+
+
+/* Phase Based Method onset detection function */
+void aubio_onsetdetection_phase(aubio_onsetdetection_t *o,
+ cvec_t * fftgrain, fvec_t * onset){
+ uint_t i, j;
+ uint_t nbins = fftgrain->length;
+ for (i=0;i<fftgrain->channels; i++) {
+ onset->data[i][0] = 0.0f;
+ o->dev1->data[i][0]=0.;
+ for ( j=0;j<nbins; j++ ) {
+ o->dev1->data[i][j] =
+ aubio_unwrap2pi(
+ fftgrain->phas[i][j]
+ -2.0*o->theta1->data[i][j]
+ +o->theta2->data[i][j]);
+ if ( o->threshold < fftgrain->norm[i][j] )
+ o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
+ else
+ o->dev1->data[i][j] = 0.0f;
+ /* keep a track of the past frames */
+ o->theta2->data[i][j] = o->theta1->data[i][j];
+ o->theta1->data[i][j] = fftgrain->phas[i][j];
+ }
+ /* apply o->histogram */
+ aubio_hist_dyn_notnull(o->histog,o->dev1);
+ /* weight it */
+ aubio_hist_weight(o->histog);
+ /* its mean is the result */
+ onset->data[i][0] = aubio_hist_mean(o->histog);
+ //onset->data[i][0] = vec_mean(o->dev1);
+ }
+}
+
+/* Spectral difference method onset detection function */
+void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
+ cvec_t * fftgrain, fvec_t * onset){
+ uint_t i, j;
+ uint_t nbins = fftgrain->length;
+ for (i=0;i<fftgrain->channels; i++) {
+ onset->data[i][0] = 0.0f;
+ for (j=0;j<nbins; j++) {
+ o->dev1->data[i][j] = SQRT(
+ ABS(SQR( fftgrain->norm[i][j])
+ - SQR(o->oldmag->data[i][j])));
+ if (o->threshold < fftgrain->norm[i][j] )
+ o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
+ else
+ o->dev1->data[i][j] = 0.0f;
+ o->oldmag->data[i][j] = fftgrain->norm[i][j];
+ }
+
+ /* apply o->histogram (act somewhat as a low pass on the
+ * overall function)*/
+ aubio_hist_dyn_notnull(o->histog,o->dev1);
+ /* weight it */
+ aubio_hist_weight(o->histog);
+ /* its mean is the result */
+ onset->data[i][0] = aubio_hist_mean(o->histog);
+
+ }
+}
+
+/* Kullback Liebler onset detection function
+ * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
+ * negative (1.+) and infinite values (+1.e-10) */
+void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
+ uint_t i,j;
+ for (i=0;i<fftgrain->channels;i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<fftgrain->length;j++) {
+ onset->data[i][0] += fftgrain->norm[i][j]
+ *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
+ o->oldmag->data[i][j] = fftgrain->norm[i][j];
+ }
+ if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
+ }
+}
+
+/* Modified Kullback Liebler onset detection function
+ * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
+ * negative (1.+) and infinite values (+1.e-10) */
+void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
+ uint_t i,j;
+ for (i=0;i<fftgrain->channels;i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<fftgrain->length;j++) {
+ onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
+ o->oldmag->data[i][j] = fftgrain->norm[i][j];
+ }
+ if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
+ }
+}
+
+/* Spectral flux */
+void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
+ uint_t i, j;
+ for (i=0;i<fftgrain->channels;i++) {
+ onset->data[i][0] = 0.;
+ for (j=0;j<fftgrain->length;j++) {
+ if (fftgrain->norm[i][j] > o->oldmag->data[i][j])
+ onset->data[i][0] += fftgrain->norm[i][j] - o->oldmag->data[i][j];
+ o->oldmag->data[i][j] = fftgrain->norm[i][j];
+ }
+ }
+}
+
+/* Generic function pointing to the choosen one */
+void
+aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain,
+ fvec_t * onset) {
+ o->funcpointer(o,fftgrain,onset);
+}
+
+/* Allocate memory for an onset detection
+ * depending on the choosen type, allocate memory as needed
+ */
+aubio_onsetdetection_t *
+new_aubio_onsetdetection (aubio_onsetdetection_type type,
+ uint_t size, uint_t channels){
+ aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
+ uint_t rsize = size/2+1;
+ uint_t i;
+ switch(type) {
+ /* for both energy and hfc, only fftgrain->norm is required */
+ case aubio_onset_energy:
+ break;
+ case aubio_onset_hfc:
+ break;
+ /* the other approaches will need some more memory spaces */
+ case aubio_onset_complex:
+ o->oldmag = new_fvec(rsize,channels);
+ /** bug: must be complex array */
+ o->meas = AUBIO_ARRAY(fft_data_t,size+1);
+ for (i=0; i<size+1; i++) o->meas[i] = 0;
+ o->dev1 = new_fvec(rsize,channels);
+ o->theta1 = new_fvec(rsize,channels);
+ o->theta2 = new_fvec(rsize,channels);
+ break;
+ case aubio_onset_phase:
+ o->dev1 = new_fvec(rsize,channels);
+ o->theta1 = new_fvec(rsize,channels);
+ o->theta2 = new_fvec(rsize,channels);
+ o->histog = new_aubio_hist(0.0f, PI, 10, channels);
+ o->threshold = 0.1;
+ break;
+ case aubio_onset_specdiff:
+ o->oldmag = new_fvec(rsize,channels);
+ o->dev1 = new_fvec(rsize,channels);
+ o->histog = new_aubio_hist(0.0f, PI, 10, channels);
+ o->threshold = 0.1;
+ break;
+ case aubio_onset_kl:
+ case aubio_onset_mkl:
+ case aubio_onset_specflux:
+ o->oldmag = new_fvec(rsize,channels);
+ break;
+ default:
+ break;
+ }
+
+ /* this switch could be in its own function to change between
+ * detections on the fly. this would need getting rid of the switch
+ * above and always allocate all the structure */
+
+ switch(type) {
+ case aubio_onset_energy:
+ o->funcpointer = aubio_onsetdetection_energy;
+ break;
+ case aubio_onset_hfc:
+ o->funcpointer = aubio_onsetdetection_hfc;
+ break;
+ case aubio_onset_complex:
+ o->funcpointer = aubio_onsetdetection_complex;
+ break;
+ case aubio_onset_phase:
+ o->funcpointer = aubio_onsetdetection_phase;
+ break;
+ case aubio_onset_specdiff:
+ o->funcpointer = aubio_onsetdetection_specdiff;
+ break;
+ case aubio_onset_kl:
+ o->funcpointer = aubio_onsetdetection_kl;
+ break;
+ case aubio_onset_mkl:
+ o->funcpointer = aubio_onsetdetection_mkl;
+ break;
+ case aubio_onset_specflux:
+ o->funcpointer = aubio_onsetdetection_specflux;
+ break;
+ default:
+ break;
+ }
+ o->type = type;
+ return o;
+}
+
+void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
+ switch(o->type) {
+ /* for both energy and hfc, only fftgrain->norm is required */
+ case aubio_onset_energy:
+ break;
+ case aubio_onset_hfc:
+ break;
+ /* the other approaches will need some more memory spaces */
+ case aubio_onset_complex:
+ AUBIO_FREE(o->meas);
+ del_fvec(o->oldmag);
+ del_fvec(o->dev1);
+ del_fvec(o->theta1);
+ del_fvec(o->theta2);
+ break;
+ case aubio_onset_phase:
+ del_fvec(o->dev1);
+ del_fvec(o->theta1);
+ del_fvec(o->theta2);
+ del_aubio_hist(o->histog);
+ break;
+ case aubio_onset_specdiff:
+ del_fvec(o->oldmag);
+ del_fvec(o->dev1);
+ del_aubio_hist(o->histog);
+ break;
+ case aubio_onset_kl:
+ del_fvec(o->oldmag);
+ break;
+ case aubio_onset_mkl:
+ del_fvec(o->oldmag);
+ break;
+ default:
+ break;
+ }
+ AUBIO_FREE(o);
+}
--- /dev/null
+++ b/src/onset/onsetdetection.h
@@ -1,0 +1,181 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** \file
+
+ Onset detection functions
+
+ All of the following onset detection function take as arguments the FFT of a
+ windowed signal (as created with aubio_pvoc). They output one smpl_t per
+ buffer and per channel (stored in a vector of size [channels]x[1]).
+
+ These functions were first adapted from Juan Pablo Bello's code, and now
+ include further improvements and modifications made within aubio.
+
+*/
+
+
+#ifndef ONSETDETECTION_H
+#define ONSETDETECTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** onsetdetection types */
+typedef enum {
+ aubio_onset_energy, /**< energy based */
+ aubio_onset_specdiff, /**< spectral diff */
+ aubio_onset_hfc, /**< high frequency content */
+ aubio_onset_complex, /**< complex domain */
+ aubio_onset_phase, /**< phase fast */
+ aubio_onset_kl, /**< Kullback Liebler */
+ aubio_onset_mkl, /**< modified Kullback Liebler */
+ aubio_onset_specflux, /**< spectral flux */
+} aubio_onsetdetection_type;
+
+/** onsetdetection structure */
+typedef struct _aubio_onsetdetection_t aubio_onsetdetection_t;
+/** 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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_energy(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_hfc(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_complex(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_phase(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_specdiff(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_kl(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_mkl(aubio_onsetdetection_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_onsetdetection()
+ \param fftgrain input spectral frame
+ \param onset output onset detection function
+
+*/
+void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
+/** execute onset detection function on a spectral frame
+
+ Generic function to compute onset detection.
+
+ \param o onset detection object as returned by new_aubio_onsetdetection()
+ \param fftgrain input signal spectrum as computed by aubio_pvoc_do
+ \param onset output vector (one sample long, to send to the peak picking)
+
+*/
+void aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
+/** creation of an onset detection object
+
+ \param type onset detection mode
+ \param size length of the input spectrum frame
+ \param channels number of input channels
+
+*/
+aubio_onsetdetection_t * new_aubio_onsetdetection(aubio_onsetdetection_type type, uint_t size, uint_t channels);
+/** deletion of an onset detection object
+
+ \param o onset detection object as returned by new_aubio_onsetdetection()
+
+*/
+void del_aubio_onsetdetection(aubio_onsetdetection_t *o);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ONSETDETECTION_H */
--- a/src/onsetdetection.c
+++ /dev/null
@@ -1,337 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "fft.h"
-#include "mathutils.h"
-#include "hist.h"
-#include "onsetdetection.h"
-
-
-/** structure to store object state */
-struct _aubio_onsetdetection_t {
- aubio_onsetdetection_type type; /**< onset detection type */
- /** Pointer to aubio_onsetdetection_<type> function */
- void (*funcpointer)(aubio_onsetdetection_t *o,
- cvec_t * fftgrain, fvec_t * onset);
- smpl_t threshold; /**< minimum norm threshold for phase and specdiff */
- fvec_t *oldmag; /**< previous norm vector */
- fft_data_t *meas; /**< current onset detection measure complex vector */
- fvec_t *dev1 ; /**< current onset detection measure vector */
- fvec_t *theta1; /**< previous phase vector, one frame behind */
- fvec_t *theta2; /**< previous phase vector, two frames behind */
- aubio_hist_t * histog; /**< histogram */
-};
-
-
-/* Energy based onset detection function */
-void aubio_onsetdetection_energy (aubio_onsetdetection_t *o UNUSED,
- cvec_t * fftgrain, fvec_t * onset) {
- uint_t i,j;
- for (i=0;i<fftgrain->channels;i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<fftgrain->length;j++) {
- onset->data[i][0] += SQR(fftgrain->norm[i][j]);
- }
- }
-}
-
-/* High Frequency Content onset detection function */
-void aubio_onsetdetection_hfc(aubio_onsetdetection_t *o UNUSED,
- cvec_t * fftgrain, fvec_t * onset){
- uint_t i,j;
- for (i=0;i<fftgrain->channels;i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<fftgrain->length;j++) {
- onset->data[i][0] += (j+1)*fftgrain->norm[i][j];
- }
- }
-}
-
-
-/* Complex Domain Method onset detection function */
-void aubio_onsetdetection_complex (aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset) {
- uint_t i, j;
- uint_t nbins = fftgrain->length;
- for (i=0;i<fftgrain->channels; i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<nbins; j++) {
- o->dev1->data[i][j] = aubio_unwrap2pi(
- fftgrain->phas[i][j]
- -2.0*o->theta1->data[i][j]+
- o->theta2->data[i][j]);
-#ifdef HAVE_COMPLEX_H
- o->meas[j] = fftgrain->norm[i][j]*CEXPC(I*o->dev1->data[i][j]);
- /* sum on all bins */
- onset->data[i][0] += //(fftgrain->norm[i][j]);
- SQRT(SQR( REAL(o->oldmag->data[i][j]-o->meas[j]) )
- + SQR( IMAG(o->oldmag->data[i][j]-o->meas[j]) )
- );
-#else
- o->meas[j] = (fftgrain->norm[i][j])*COS(o->dev1->data[i][j]);
- o->meas[(nbins-1)*2-j] = (fftgrain->norm[i][j])*SIN(o->dev1->data[i][j]);
- /* sum on all bins */
- onset->data[i][0] += //(fftgrain->norm[i][j]);
- SQRT(SQR( (o->oldmag->data[i][j]-o->meas[j]) )
- + SQR( (-o->meas[(nbins-1)*2-j]) )
- );
-#endif
- /* swap old phase data (need to remember 2 frames behind)*/
- o->theta2->data[i][j] = o->theta1->data[i][j];
- o->theta1->data[i][j] = fftgrain->phas[i][j];
- /* swap old magnitude data (1 frame is enough) */
- o->oldmag->data[i][j] = fftgrain->norm[i][j];
- }
- }
-}
-
-
-/* Phase Based Method onset detection function */
-void aubio_onsetdetection_phase(aubio_onsetdetection_t *o,
- cvec_t * fftgrain, fvec_t * onset){
- uint_t i, j;
- uint_t nbins = fftgrain->length;
- for (i=0;i<fftgrain->channels; i++) {
- onset->data[i][0] = 0.0f;
- o->dev1->data[i][0]=0.;
- for ( j=0;j<nbins; j++ ) {
- o->dev1->data[i][j] =
- aubio_unwrap2pi(
- fftgrain->phas[i][j]
- -2.0*o->theta1->data[i][j]
- +o->theta2->data[i][j]);
- if ( o->threshold < fftgrain->norm[i][j] )
- o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
- else
- o->dev1->data[i][j] = 0.0f;
- /* keep a track of the past frames */
- o->theta2->data[i][j] = o->theta1->data[i][j];
- o->theta1->data[i][j] = fftgrain->phas[i][j];
- }
- /* apply o->histogram */
- aubio_hist_dyn_notnull(o->histog,o->dev1);
- /* weight it */
- aubio_hist_weight(o->histog);
- /* its mean is the result */
- onset->data[i][0] = aubio_hist_mean(o->histog);
- //onset->data[i][0] = vec_mean(o->dev1);
- }
-}
-
-/* Spectral difference method onset detection function */
-void aubio_onsetdetection_specdiff(aubio_onsetdetection_t *o,
- cvec_t * fftgrain, fvec_t * onset){
- uint_t i, j;
- uint_t nbins = fftgrain->length;
- for (i=0;i<fftgrain->channels; i++) {
- onset->data[i][0] = 0.0f;
- for (j=0;j<nbins; j++) {
- o->dev1->data[i][j] = SQRT(
- ABS(SQR( fftgrain->norm[i][j])
- - SQR(o->oldmag->data[i][j])));
- if (o->threshold < fftgrain->norm[i][j] )
- o->dev1->data[i][j] = ABS(o->dev1->data[i][j]);
- else
- o->dev1->data[i][j] = 0.0f;
- o->oldmag->data[i][j] = fftgrain->norm[i][j];
- }
-
- /* apply o->histogram (act somewhat as a low pass on the
- * overall function)*/
- aubio_hist_dyn_notnull(o->histog,o->dev1);
- /* weight it */
- aubio_hist_weight(o->histog);
- /* its mean is the result */
- onset->data[i][0] = aubio_hist_mean(o->histog);
-
- }
-}
-
-/* Kullback Liebler onset detection function
- * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
- * negative (1.+) and infinite values (+1.e-10) */
-void aubio_onsetdetection_kl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
- uint_t i,j;
- for (i=0;i<fftgrain->channels;i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<fftgrain->length;j++) {
- onset->data[i][0] += fftgrain->norm[i][j]
- *LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
- o->oldmag->data[i][j] = fftgrain->norm[i][j];
- }
- if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
- }
-}
-
-/* Modified Kullback Liebler onset detection function
- * note we use ln(1+Xn/(Xn-1+0.0001)) to avoid
- * negative (1.+) and infinite values (+1.e-10) */
-void aubio_onsetdetection_mkl(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
- uint_t i,j;
- for (i=0;i<fftgrain->channels;i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<fftgrain->length;j++) {
- onset->data[i][0] += LOG(1.+fftgrain->norm[i][j]/(o->oldmag->data[i][j]+1.e-10));
- o->oldmag->data[i][j] = fftgrain->norm[i][j];
- }
- if (isnan(onset->data[i][0])) onset->data[i][0] = 0.;
- }
-}
-
-/* Spectral flux */
-void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset){
- uint_t i, j;
- for (i=0;i<fftgrain->channels;i++) {
- onset->data[i][0] = 0.;
- for (j=0;j<fftgrain->length;j++) {
- if (fftgrain->norm[i][j] > o->oldmag->data[i][j])
- onset->data[i][0] += fftgrain->norm[i][j] - o->oldmag->data[i][j];
- o->oldmag->data[i][j] = fftgrain->norm[i][j];
- }
- }
-}
-
-/* Generic function pointing to the choosen one */
-void
-aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain,
- fvec_t * onset) {
- o->funcpointer(o,fftgrain,onset);
-}
-
-/* Allocate memory for an onset detection
- * depending on the choosen type, allocate memory as needed
- */
-aubio_onsetdetection_t *
-new_aubio_onsetdetection (aubio_onsetdetection_type type,
- uint_t size, uint_t channels){
- aubio_onsetdetection_t * o = AUBIO_NEW(aubio_onsetdetection_t);
- uint_t rsize = size/2+1;
- uint_t i;
- switch(type) {
- /* for both energy and hfc, only fftgrain->norm is required */
- case aubio_onset_energy:
- break;
- case aubio_onset_hfc:
- break;
- /* the other approaches will need some more memory spaces */
- case aubio_onset_complex:
- o->oldmag = new_fvec(rsize,channels);
- /** bug: must be complex array */
- o->meas = AUBIO_ARRAY(fft_data_t,size+1);
- for (i=0; i<size+1; i++) o->meas[i] = 0;
- o->dev1 = new_fvec(rsize,channels);
- o->theta1 = new_fvec(rsize,channels);
- o->theta2 = new_fvec(rsize,channels);
- break;
- case aubio_onset_phase:
- o->dev1 = new_fvec(rsize,channels);
- o->theta1 = new_fvec(rsize,channels);
- o->theta2 = new_fvec(rsize,channels);
- o->histog = new_aubio_hist(0.0f, PI, 10, channels);
- o->threshold = 0.1;
- break;
- case aubio_onset_specdiff:
- o->oldmag = new_fvec(rsize,channels);
- o->dev1 = new_fvec(rsize,channels);
- o->histog = new_aubio_hist(0.0f, PI, 10, channels);
- o->threshold = 0.1;
- break;
- case aubio_onset_kl:
- case aubio_onset_mkl:
- case aubio_onset_specflux:
- o->oldmag = new_fvec(rsize,channels);
- break;
- default:
- break;
- }
-
- /* this switch could be in its own function to change between
- * detections on the fly. this would need getting rid of the switch
- * above and always allocate all the structure */
-
- switch(type) {
- case aubio_onset_energy:
- o->funcpointer = aubio_onsetdetection_energy;
- break;
- case aubio_onset_hfc:
- o->funcpointer = aubio_onsetdetection_hfc;
- break;
- case aubio_onset_complex:
- o->funcpointer = aubio_onsetdetection_complex;
- break;
- case aubio_onset_phase:
- o->funcpointer = aubio_onsetdetection_phase;
- break;
- case aubio_onset_specdiff:
- o->funcpointer = aubio_onsetdetection_specdiff;
- break;
- case aubio_onset_kl:
- o->funcpointer = aubio_onsetdetection_kl;
- break;
- case aubio_onset_mkl:
- o->funcpointer = aubio_onsetdetection_mkl;
- break;
- case aubio_onset_specflux:
- o->funcpointer = aubio_onsetdetection_specflux;
- break;
- default:
- break;
- }
- o->type = type;
- return o;
-}
-
-void del_aubio_onsetdetection (aubio_onsetdetection_t *o){
- switch(o->type) {
- /* for both energy and hfc, only fftgrain->norm is required */
- case aubio_onset_energy:
- break;
- case aubio_onset_hfc:
- break;
- /* the other approaches will need some more memory spaces */
- case aubio_onset_complex:
- AUBIO_FREE(o->meas);
- del_fvec(o->oldmag);
- del_fvec(o->dev1);
- del_fvec(o->theta1);
- del_fvec(o->theta2);
- break;
- case aubio_onset_phase:
- del_fvec(o->dev1);
- del_fvec(o->theta1);
- del_fvec(o->theta2);
- del_aubio_hist(o->histog);
- break;
- case aubio_onset_specdiff:
- del_fvec(o->oldmag);
- del_fvec(o->dev1);
- del_aubio_hist(o->histog);
- break;
- case aubio_onset_kl:
- del_fvec(o->oldmag);
- break;
- case aubio_onset_mkl:
- del_fvec(o->oldmag);
- break;
- default:
- break;
- }
- AUBIO_FREE(o);
-}
--- a/src/onsetdetection.h
+++ /dev/null
@@ -1,181 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** \file
-
- Onset detection functions
-
- All of the following onset detection function take as arguments the FFT of a
- windowed signal (as created with aubio_pvoc). They output one smpl_t per
- buffer and per channel (stored in a vector of size [channels]x[1]).
-
- These functions were first adapted from Juan Pablo Bello's code, and now
- include further improvements and modifications made within aubio.
-
-*/
-
-
-#ifndef ONSETDETECTION_H
-#define ONSETDETECTION_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** onsetdetection types */
-typedef enum {
- aubio_onset_energy, /**< energy based */
- aubio_onset_specdiff, /**< spectral diff */
- aubio_onset_hfc, /**< high frequency content */
- aubio_onset_complex, /**< complex domain */
- aubio_onset_phase, /**< phase fast */
- aubio_onset_kl, /**< Kullback Liebler */
- aubio_onset_mkl, /**< modified Kullback Liebler */
- aubio_onset_specflux, /**< spectral flux */
-} aubio_onsetdetection_type;
-
-/** onsetdetection structure */
-typedef struct _aubio_onsetdetection_t aubio_onsetdetection_t;
-/** 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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_energy(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_hfc(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_complex(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_phase(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_specdiff(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_kl(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_mkl(aubio_onsetdetection_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_onsetdetection()
- \param fftgrain input spectral frame
- \param onset output onset detection function
-
-*/
-void aubio_onsetdetection_specflux(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** execute onset detection function on a spectral frame
-
- Generic function to compute onset detection.
-
- \param o onset detection object as returned by new_aubio_onsetdetection()
- \param fftgrain input signal spectrum as computed by aubio_pvoc_do
- \param onset output vector (one sample long, to send to the peak picking)
-
-*/
-void aubio_onsetdetection(aubio_onsetdetection_t *o, cvec_t * fftgrain, fvec_t * onset);
-/** creation of an onset detection object
-
- \param type onset detection mode
- \param size length of the input spectrum frame
- \param channels number of input channels
-
-*/
-aubio_onsetdetection_t * new_aubio_onsetdetection(aubio_onsetdetection_type type, uint_t size, uint_t channels);
-/** deletion of an onset detection object
-
- \param o onset detection object as returned by new_aubio_onsetdetection()
-
-*/
-void del_aubio_onsetdetection(aubio_onsetdetection_t *o);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ONSETDETECTION_H */
--- /dev/null
+++ b/src/pitch/pitchfcomb.c
@@ -1,0 +1,135 @@
+/*
+ Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "mathutils.h"
+#include "fft.h"
+#include "pitch/pitchfcomb.h"
+
+#define MAX_PEAKS 8
+
+typedef struct {
+ smpl_t freq;
+ smpl_t db;
+} aubio_fpeak_t;
+
+struct _aubio_pitchfcomb_t {
+ uint_t fftSize;
+ uint_t stepSize;
+ uint_t rate;
+ fvec_t * winput;
+ fvec_t * win;
+ cvec_t * fftOut;
+ fvec_t * fftLastPhase;
+ aubio_fft_t * fft;
+ //aubio_pvoc_t * pvoc;
+};
+
+aubio_pitchfcomb_t * new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize, uint_t samplerate)
+{
+ aubio_pitchfcomb_t * p = AUBIO_NEW(aubio_pitchfcomb_t);
+ p->rate = samplerate;
+ p->fftSize = bufsize;
+ p->stepSize = hopsize;
+ p->winput = new_fvec(bufsize,1);
+ p->fftOut = new_cvec(bufsize,1);
+ p->fftLastPhase = new_fvec(bufsize,1);
+ p->fft = new_aubio_fft(bufsize, 1);
+ p->win = new_fvec(bufsize,1);
+ aubio_window(p->win->data[0], bufsize, aubio_win_hanning);
+ return p;
+}
+
+/* input must be stepsize long */
+smpl_t aubio_pitchfcomb_detect (aubio_pitchfcomb_t * p, fvec_t * input)
+{
+ uint_t k, l, maxharm = 0;
+ smpl_t freqPerBin = p->rate/(smpl_t)p->fftSize,
+ phaseDifference = TWO_PI*(smpl_t)p->stepSize/(smpl_t)p->fftSize;
+ aubio_fpeak_t peaks[MAX_PEAKS];
+
+ for (k=0; k<MAX_PEAKS; k++) {
+ peaks[k].db = -200.;
+ peaks[k].freq = 0.;
+ }
+
+ for (k=0; k < input->length; k++){
+ p->winput->data[0][k] = p->win->data[0][k] * input->data[0][k];
+ }
+ aubio_fft_do(p->fft,p->winput,p->fftOut);
+
+ for (k=0; k<=p->fftSize/2; k++) {
+ smpl_t
+ magnitude = 20.*LOG10(2.*p->fftOut->norm[0][k]/(smpl_t)p->fftSize),
+ phase = p->fftOut->phas[0][k],
+ tmp, freq;
+
+ /* compute phase difference */
+ tmp = phase - p->fftLastPhase->data[0][k];
+ p->fftLastPhase->data[0][k] = phase;
+
+ /* subtract expected phase difference */
+ tmp -= (smpl_t)k*phaseDifference;
+
+ /* map delta phase into +/- Pi interval */
+ tmp = aubio_unwrap2pi(tmp);
+
+ /* get deviation from bin frequency from the +/- Pi interval */
+ tmp = p->fftSize/(smpl_t)p->stepSize*tmp/(TWO_PI);
+
+ /* compute the k-th partials' true frequency */
+ freq = (smpl_t)k*freqPerBin + tmp*freqPerBin;
+
+ if (freq > 0.0 && magnitude > peaks[0].db) { // && magnitude < 0) {
+ memmove(peaks+1, peaks, sizeof(aubio_fpeak_t)*(MAX_PEAKS-1));
+ peaks[0].freq = freq;
+ peaks[0].db = magnitude;
+ }
+ }
+
+ k = 0;
+ for (l=1; l<MAX_PEAKS && peaks[l].freq > 0.0; l++) {
+ sint_t harmonic;
+ for (harmonic=5; harmonic>1; harmonic--) {
+ if (peaks[0].freq / peaks[l].freq < harmonic+.02 &&
+ peaks[0].freq / peaks[l].freq > harmonic-.02) {
+ if (harmonic > (sint_t)maxharm &&
+ peaks[0].db < peaks[l].db/2) {
+ maxharm = harmonic;
+ k = l;
+ }
+ }
+ }
+ }
+ /* quick hack to clean output a bit */
+ if (peaks[k].freq > 5000.) return 0.;
+ return peaks[k].freq;
+}
+
+void del_aubio_pitchfcomb (aubio_pitchfcomb_t * p)
+{
+ del_cvec(p->fftOut);
+ del_fvec(p->fftLastPhase);
+ del_fvec(p->win);
+ del_fvec(p->winput);
+ del_aubio_fft(p->fft);
+ AUBIO_FREE(p);
+}
+
--- /dev/null
+++ b/src/pitch/pitchfcomb.h
@@ -1,0 +1,73 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** \file
+
+ Pitch detection using a fast harmonic comb filter
+
+ This pitch extraction method implements a fast harmonic comb filter to
+ determine the fundamental frequency of a harmonic sound.
+
+ This file was derived from the tuneit project, written by Mario Lang to
+ detect the fundamental frequency of a sound.
+
+ see http://delysid.org/tuneit.html
+
+*/
+
+#ifndef _PITCHFCOMB_H
+#define _PITCHFCOMB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** pitch detection object */
+typedef struct _aubio_pitchfcomb_t aubio_pitchfcomb_t;
+
+/** execute pitch detection on an input buffer
+
+ \param p pitch detection object as returned by new_aubio_pitchfcomb
+ \param input input signal window (length as specified at creation time)
+
+*/
+smpl_t aubio_pitchfcomb_detect (aubio_pitchfcomb_t *p, fvec_t * input);
+/** creation of the pitch detection object
+
+ \param bufsize size of the input buffer to analyse
+ \param hopsize step size between two consecutive analysis instant
+ \param samplerate sampling rate of the signal
+
+*/
+aubio_pitchfcomb_t * new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize, uint_t samplerate);
+/** deletion of the pitch detection object
+
+ \param p pitch detection object as returned by new_aubio_pitchfcomb
+
+*/
+void del_aubio_pitchfcomb (aubio_pitchfcomb_t *p);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PITCHFCOMB_H */
+
+
--- /dev/null
+++ b/src/pitch/pitchmcomb.c
@@ -1,0 +1,390 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "mathutils.h"
+#include "pitch/pitchmcomb.h"
+
+#define CAND_SWAP(a,b) { register aubio_spectralcandidate_t *t=(a);(a)=(b);(b)=t; }
+
+typedef struct _aubio_spectralpeak_t aubio_spectralpeak_t;
+typedef struct _aubio_spectralcandidate_t aubio_spectralcandidate_t;
+uint_t aubio_pitchmcomb_get_root_peak(aubio_spectralpeak_t * peaks, uint_t length);
+uint_t aubio_pitchmcomb_quadpick(aubio_spectralpeak_t * spectral_peaks, fvec_t * X);
+void aubio_pitchmcomb_spectral_pp(aubio_pitchmcomb_t * p, fvec_t * oldmag);
+void aubio_pitchmcomb_combdet(aubio_pitchmcomb_t * p, fvec_t * newmag);
+/* not used but useful : sort by amplitudes (or anything else)
+ * sort_pitchpeak(peaks, length);
+ */
+/** spectral_peak comparison function (must return signed int) */
+static sint_t aubio_pitchmcomb_sort_peak_comp(const void *x, const void *y);
+/** sort spectral_peak against their mag */
+void aubio_pitchmcomb_sort_peak(aubio_spectralpeak_t * peaks, uint_t nbins);
+
+/** sort spectral_candidate against their comb ene */
+void aubio_pitchmcomb_sort_cand_ene(aubio_spectralcandidate_t ** candidates, uint_t nbins);
+/** sort spectral_candidate against their frequency */
+void aubio_pitchmcomb_sort_cand_freq(aubio_spectralcandidate_t ** candidates, uint_t nbins);
+
+struct _aubio_pitchmcomb_t {
+ smpl_t threshold; /**< offset threshold [0.033 or 0.01] */
+ smpl_t alpha; /**< normalisation exponent [9] */
+ smpl_t cutoff; /**< low-pass filter cutoff [0.34, 1] */
+ smpl_t tol; /**< tolerance [0.05] */
+ smpl_t tau; /**< frequency precision [44100/4096] */
+ uint_t win_post; /**< median filter window length */
+ uint_t win_pre; /**< median filter window */
+ uint_t ncand; /**< maximum number of candidates (combs) */
+ uint_t npartials; /**< maximum number of partials per combs */
+ uint_t count; /**< picked picks */
+ uint_t goodcandidate; /**< best candidate */
+ uint_t spec_partition; /**< spectrum partition to consider */
+ aubio_spectralpeak_t * peaks; /**< up to length win/spec_partition */
+ aubio_spectralcandidate_t ** candidates; /** up to five candidates */
+ /* some scratch pads */
+ /** \bug (unnecessary copied from fftgrain?) */
+ fvec_t * newmag; /**< vec to store mag */
+ fvec_t * scratch; /**< vec to store modified mag */
+ fvec_t * scratch2; /**< vec to compute moving median */
+ fvec_t * theta; /**< vec to store phase */
+ smpl_t phasediff;
+ smpl_t phasefreq;
+ /** threshfn: name or handle of fn for computing adaptive threshold [median] */
+ /** aubio_thresholdfn_t thresholdfn; */
+ /** picker: name or handle of fn for picking event times [quadpick] */
+ /** aubio_pickerfn_t pickerfn; */
+};
+
+/** spectral peak object */
+struct _aubio_spectralpeak_t {
+ uint_t bin; /**< bin [0-(length-1)] */
+ smpl_t ebin; /**< estimated bin */
+ smpl_t mag; /**< peak magnitude */
+};
+
+/** spectral candidates array object */
+struct _aubio_spectralcandidate_t {
+ smpl_t ebin; /**< interpolated bin */
+ smpl_t * ecomb; /**< comb */
+ smpl_t ene; /**< candidate energy */
+ smpl_t len; /**< length */
+};
+
+
+smpl_t aubio_pitchmcomb_detect(aubio_pitchmcomb_t * p, cvec_t * fftgrain) {
+ uint_t i=0,j;
+ smpl_t instfreq;
+ fvec_t * newmag = (fvec_t *)p->newmag;
+ //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta;
+ /* copy incoming grain to newmag */
+ for (j=0; j< newmag->length; j++)
+ newmag->data[i][j]=fftgrain->norm[i][j];
+ /* detect only if local energy > 10. */
+ //if (vec_local_energy(newmag)>10.) {
+ //hfc = vec_local_hfc(newmag); //not used
+ aubio_pitchmcomb_spectral_pp(p, newmag);
+ aubio_pitchmcomb_combdet(p,newmag);
+ //aubio_pitchmcomb_sort_cand_freq(p->candidates,p->ncand);
+ //return p->candidates[p->goodcandidate]->ebin;
+ j = (uint_t)FLOOR(p->candidates[p->goodcandidate]->ebin+.5);
+ instfreq = aubio_unwrap2pi(fftgrain->phas[0][j]
+ - p->theta->data[0][j] - j*p->phasediff);
+ instfreq *= p->phasefreq;
+ /* store phase for next run */
+ for (j=0; j< p->theta->length; j++) {
+ p->theta->data[i][j]=fftgrain->phas[i][j];
+ }
+ //return p->candidates[p->goodcandidate]->ebin;
+ return FLOOR(p->candidates[p->goodcandidate]->ebin+.5) + instfreq;
+ /*} else {
+ return -1.;
+ }*/
+}
+
+uint_t aubio_pitch_cands(aubio_pitchmcomb_t * p, cvec_t * fftgrain,
+ smpl_t * cands) {
+ uint_t i=0,j;
+ uint_t k;
+ fvec_t * newmag = (fvec_t *)p->newmag;
+ aubio_spectralcandidate_t ** scands =
+ (aubio_spectralcandidate_t **)(p->candidates);
+ //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta;
+ /* copy incoming grain to newmag */
+ for (j=0; j< newmag->length; j++)
+ newmag->data[i][j]=fftgrain->norm[i][j];
+ /* detect only if local energy > 10. */
+ if (vec_local_energy(newmag)>10.) {
+ /* hfc = vec_local_hfc(newmag); do not use */
+ aubio_pitchmcomb_spectral_pp(p, newmag);
+ aubio_pitchmcomb_combdet(p,newmag);
+ aubio_pitchmcomb_sort_cand_freq(scands,p->ncand);
+ /* store ncand comb energies in cands[1:ncand] */
+ for (k = 0; k<p->ncand; k++)
+ cands[k] = p->candidates[k]->ene;
+ /* store ncand[end] freq in cands[end] */
+ cands[p->ncand] = p->candidates[p->ncand-1]->ebin;
+ return 1;
+ } else {
+ for (k = 0; k<p->ncand; k++)
+ cands[k] = 0;
+ return 0;
+ }
+}
+
+void aubio_pitchmcomb_spectral_pp(aubio_pitchmcomb_t * p, fvec_t * newmag) {
+ fvec_t * mag = (fvec_t *)p->scratch;
+ fvec_t * tmp = (fvec_t *)p->scratch2;
+ uint_t i=0,j;
+ uint_t length = mag->length;
+ /* copy newmag to mag (scracth) */
+ for (j=0;j<length;j++) {
+ mag->data[i][j] = newmag->data[i][j];
+ }
+ vec_dc_removal(mag); /* dc removal */
+ vec_alpha_normalise(mag,p->alpha); /* alpha normalisation */
+ /* skipped */ /* low pass filtering */
+ /** \bug vec_moving_thres may write out of bounds */
+ vec_adapt_thres(mag,tmp,p->win_post,p->win_pre); /* adaptative threshold */
+ vec_add(mag,-p->threshold); /* fixed threshold */
+ {
+ aubio_spectralpeak_t * peaks = (aubio_spectralpeak_t *)p->peaks;
+ uint_t count;
+ /* return bin and ebin */
+ count = aubio_pitchmcomb_quadpick(peaks,mag);
+ for (j=0;j<count;j++)
+ peaks[j].mag = newmag->data[i][peaks[j].bin];
+ /* reset non peaks */
+ for (j=count;j<length;j++)
+ peaks[j].mag = 0.;
+ p->peaks = peaks;
+ p->count = count;
+ }
+}
+
+void aubio_pitchmcomb_combdet(aubio_pitchmcomb_t * p, fvec_t * newmag) {
+ aubio_spectralpeak_t * peaks = (aubio_spectralpeak_t *)p->peaks;
+ aubio_spectralcandidate_t ** candidate =
+ (aubio_spectralcandidate_t **)p->candidates;
+
+ /* parms */
+ uint_t N = p->npartials; /* maximum number of partials to be considered 10 */
+ uint_t M = p->ncand; /* maximum number of combs to be considered 5 */
+ uint_t length = newmag->length;
+ uint_t count = p->count;
+ uint_t k;
+ uint_t l;
+ uint_t d;
+ uint_t curlen = 0;
+
+ smpl_t delta2;
+ smpl_t xx;
+ uint_t position = 0;
+
+ uint_t root_peak = 0;
+ uint_t tmpl = 0;
+ smpl_t tmpene = 0.;
+
+ /* get the biggest peak in the spectrum */
+ root_peak = aubio_pitchmcomb_get_root_peak(peaks,count);
+ /* not enough partials in highest notes, could be forced */
+ //if (peaks[root_peak].ebin >= aubio_miditofreq(85.)/p->tau) N=2;
+ //if (peaks[root_peak].ebin >= aubio_miditofreq(90.)/p->tau) N=1;
+ /* now calculate the energy of each of the 5 combs */
+ for (l=0;l<M;l++) {
+ smpl_t scaler = (1./(l+1.));
+ candidate[l]->ene = 0.; /* reset ene and len sums */
+ candidate[l]->len = 0.;
+ candidate[l]->ebin=scaler*peaks[root_peak].ebin;
+ /* if less than N peaks available, curlen < N */
+ if (candidate[l]->ebin != 0.)
+ curlen = (uint_t)FLOOR(length/(candidate[l]->ebin));
+ curlen = (N < curlen )? N : curlen;
+ /* fill candidate[l]->ecomb[k] with (k+1)*candidate[l]->ebin */
+ for (k=0;k<curlen;k++)
+ candidate[l]->ecomb[k]=(candidate[l]->ebin)*(k+1.);
+ for (k=curlen;k<length;k++)
+ candidate[l]->ecomb[k]=0.;
+ /* for each in candidate[l]->ecomb[k] */
+ for (k=0;k<curlen;k++) {
+ xx = 100000.;
+ /** get the candidate->ecomb the closer to peaks.ebin
+ * (to cope with the inharmonicity)*/
+ for (d=0;d<count;d++) {
+ delta2 = ABS(candidate[l]->ecomb[k]-peaks[d].ebin);
+ if (delta2 <= xx) {
+ position = d;
+ xx = delta2;
+ }
+ }
+ /* for a Q factor of 17, maintaining "constant Q filtering",
+ * and sum energy and length over non null combs */
+ if ( 17. * xx < candidate[l]->ecomb[k] ) {
+ candidate[l]->ecomb[k]=peaks[position].ebin;
+ candidate[l]->ene += /* ecomb rounded to nearest int */
+ POW(newmag->data[0][(uint_t)FLOOR(candidate[l]->ecomb[k]+.5)],0.25);
+ candidate[l]->len += 1./curlen;
+ } else
+ candidate[l]->ecomb[k]=0.;
+ }
+ /* punishment */
+ /*if (candidate[l]->len<0.6)
+ candidate[l]->ene=0.; */
+ /* remember best candidate energy (in polyphonic, could check for
+ * tmpene*1.1 < candidate->ene to reduce jumps towards low frequencies) */
+ if (tmpene < candidate[l]->ene) {
+ tmpl = l;
+ tmpene = candidate[l]->ene;
+ }
+ }
+ //p->candidates=candidate;
+ //p->peaks=peaks;
+ p->goodcandidate = tmpl;
+}
+
+/** T=quadpick(X): return indices of elements of X which are peaks and positive
+ * exact peak positions are retrieved by quadratic interpolation
+ *
+ * \bug peak-picking too picky, sometimes counts too many peaks ?
+ */
+uint_t aubio_pitchmcomb_quadpick(aubio_spectralpeak_t * spectral_peaks, fvec_t * X){
+ uint_t i, j, ispeak, count = 0;
+ for (i=0;i<X->channels;i++)
+ for (j=1;j<X->length-1;j++) {
+ ispeak = vec_peakpick(X,j);
+ if (ispeak) {
+ count += ispeak;
+ spectral_peaks[count-1].bin = j;
+ spectral_peaks[count-1].ebin = vec_quadint(X,j) - 1.;
+ }
+ }
+ return count;
+}
+
+/* get predominant partial */
+uint_t aubio_pitchmcomb_get_root_peak(aubio_spectralpeak_t * peaks, uint_t length) {
+ uint_t i,pos=0;
+ smpl_t tmp = 0.;
+ for (i=0;i<length;i++)
+ if (tmp <= peaks[i].mag) {
+ pos = i;
+ tmp = peaks[i].mag;
+ }
+ return pos;
+}
+
+void aubio_pitchmcomb_sort_peak(aubio_spectralpeak_t * peaks, uint_t nbins) {
+ qsort(peaks, nbins, sizeof(aubio_spectralpeak_t),
+ aubio_pitchmcomb_sort_peak_comp);
+}
+static sint_t aubio_pitchmcomb_sort_peak_comp(const void *x, const void *y) {
+ return (((aubio_spectralpeak_t *)y)->mag - ((aubio_spectralpeak_t *)x)->mag);
+}
+
+
+void aubio_pitchmcomb_sort_cand_ene(aubio_spectralcandidate_t ** candidates, uint_t nbins) {
+ uint_t cur = 0;
+ uint_t run = 0;
+ for (cur=0;cur<nbins;cur++) {
+ run = cur + 1;
+ for (run=cur;run<nbins;run++) {
+ if(candidates[run]->ene > candidates[cur]->ene)
+ CAND_SWAP(candidates[run], candidates[cur]);
+ }
+ }
+}
+
+
+void aubio_pitchmcomb_sort_cand_freq(aubio_spectralcandidate_t ** candidates, uint_t nbins) {
+ uint_t cur = 0;
+ uint_t run = 0;
+ for (cur=0;cur<nbins;cur++) {
+ run = cur + 1;
+ for (run=cur;run<nbins;run++) {
+ if(candidates[run]->ebin < candidates[cur]->ebin)
+ CAND_SWAP(candidates[run], candidates[cur]);
+ }
+ }
+}
+
+aubio_pitchmcomb_t * new_aubio_pitchmcomb(uint_t bufsize, uint_t hopsize, uint_t channels, uint_t samplerate) {
+ aubio_pitchmcomb_t * p = AUBIO_NEW(aubio_pitchmcomb_t);
+ /* bug: should check if size / 8 > post+pre+1 */
+ uint_t i, j;
+ uint_t spec_size;
+ p->spec_partition = 4;
+ p->ncand = 5;
+ p->npartials = 5;
+ p->cutoff = 1.;
+ p->threshold = 0.01;
+ p->win_post = 8;
+ p->win_pre = 7;
+ p->tau = samplerate/bufsize;
+ p->alpha = 9.;
+ p->goodcandidate = 0;
+ p->phasefreq = bufsize/hopsize/TWO_PI;
+ p->phasediff = TWO_PI*hopsize/bufsize;
+ spec_size = bufsize/p->spec_partition;
+ //p->pickerfn = quadpick;
+ //p->biquad = new_biquad(0.1600,0.3200,0.1600, -0.5949, 0.2348);
+ /* allocate temp memory */
+ p->newmag = new_fvec(spec_size,channels);
+ /* array for median */
+ p->scratch = new_fvec(spec_size,channels);
+ /* array for phase */
+ p->theta = new_fvec(spec_size,channels);
+ /* array for adaptative threshold */
+ p->scratch2 = new_fvec(p->win_post+p->win_pre+1,channels);
+ /* array of spectral peaks */
+ p->peaks = AUBIO_ARRAY(aubio_spectralpeak_t,spec_size);
+ for (i = 0; i < spec_size; i++) {
+ p->peaks[i].bin = 0.;
+ p->peaks[i].ebin = 0.;
+ p->peaks[i].mag = 0.;
+ }
+ /* array of pointers to spectral candidates */
+ p->candidates = AUBIO_ARRAY(aubio_spectralcandidate_t *,p->ncand);
+ for (i=0;i<p->ncand;i++) {
+ p->candidates[i] = AUBIO_NEW(aubio_spectralcandidate_t);
+ p->candidates[i]->ecomb = AUBIO_ARRAY(smpl_t, spec_size);
+ for (j=0; j < spec_size; j++) {
+ p->candidates[i]->ecomb[j] = 0.;
+ }
+ p->candidates[i]->ene = 0.;
+ p->candidates[i]->ebin = 0.;
+ p->candidates[i]->len = 0.;
+ }
+ return p;
+}
+
+
+void del_aubio_pitchmcomb (aubio_pitchmcomb_t *p) {
+ uint_t i;
+ del_fvec(p->newmag);
+ del_fvec(p->scratch);
+ del_fvec(p->theta);
+ del_fvec(p->scratch2);
+ AUBIO_FREE(p->peaks);
+ for (i=0;i<p->ncand;i++) {
+ AUBIO_FREE(p->candidates[i]->ecomb);
+ AUBIO_FREE(p->candidates[i]);
+ }
+ AUBIO_FREE(p->candidates);
+ AUBIO_FREE(p);
+}
--- /dev/null
+++ b/src/pitch/pitchmcomb.h
@@ -1,0 +1,74 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** \file
+
+ Pitch detection using multiple-comb filter
+
+ This fundamental frequency estimation algorithm implements spectral
+ flattening, multi-comb filtering and peak histogramming.
+
+ This method was designed by Juan P. Bello and described in:
+
+ Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic
+ Music''. PhD thesis, Centre for Digital Music, Queen Mary University of
+ London, London, UK, 2003.
+
+*/
+
+#ifndef PITCHMCOMB_H
+#define PITCHMCOMB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** pitch detection object */
+typedef struct _aubio_pitchmcomb_t aubio_pitchmcomb_t;
+
+/** execute pitch detection on an input spectral frame
+
+ \param p pitch detection object as returned by new_aubio_pitchmcomb
+ \param fftgrain input signal spectrum as computed by aubio_pvoc_do
+
+*/
+smpl_t aubio_pitchmcomb_detect(aubio_pitchmcomb_t * p, cvec_t * fftgrain);
+/** select the best candidates */
+uint_t aubio_pitch_cands(aubio_pitchmcomb_t * p, cvec_t * fftgrain, smpl_t * cands);
+/** creation of the pitch detection object
+
+ \param bufsize size of the input buffer to analyse
+ \param hopsize step size between two consecutive analysis instant
+ \param channels number of channels to analyse
+ \param samplerate sampling rate of the signal
+
+*/
+aubio_pitchmcomb_t * new_aubio_pitchmcomb(uint_t bufsize, uint_t hopsize, uint_t channels, uint_t samplerate);
+/** deletion of the pitch detection object
+
+ \param p pitch detection object as returned by new_aubio_pitchfcomb
+
+*/
+void del_aubio_pitchmcomb(aubio_pitchmcomb_t *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif/*PITCHMCOMB_H*/
--- /dev/null
+++ b/src/pitch/pitchschmitt.c
@@ -1,0 +1,107 @@
+/*
+ Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "pitch/pitchschmitt.h"
+
+smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata);
+
+struct _aubio_pitchschmitt_t {
+ uint_t blockSize;
+ uint_t rate;
+ signed short int *schmittBuffer;
+ signed short int *schmittPointer;
+};
+
+aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate)
+{
+ aubio_pitchschmitt_t * p = AUBIO_NEW(aubio_pitchschmitt_t);
+ p->blockSize = size;
+ p->schmittBuffer = AUBIO_ARRAY(signed short int,p->blockSize);
+ p->schmittPointer = p->schmittBuffer;
+ p->rate = samplerate;
+ return p;
+}
+
+smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input)
+{
+ signed short int buf[input->length];
+ uint_t i;
+ for (i=0; i<input->length; i++) {
+ buf[i] = input->data[0][i]*32768.;
+ }
+ return aubio_schmittS16LE(p, input->length, buf);
+}
+
+smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata)
+{
+ uint_t i, j;
+ uint_t blockSize = p->blockSize;
+ signed short int *schmittBuffer = p->schmittBuffer;
+ signed short int *schmittPointer = p->schmittPointer;
+
+ smpl_t freq = 0., trigfact = 0.6;
+
+ for (i=0; i<nframes; i++) {
+ *schmittPointer++ = indata[i];
+ if (schmittPointer-schmittBuffer >= (sint_t)blockSize) {
+ sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered;
+
+ schmittPointer = schmittBuffer;
+
+ for (j=0,A1=0,A2=0; j<blockSize; j++) {
+ if (schmittBuffer[j]>0 && A1<schmittBuffer[j]) A1 = schmittBuffer[j];
+ if (schmittBuffer[j]<0 && A2<-schmittBuffer[j]) A2 = -schmittBuffer[j];
+ }
+ t1 = (sint_t)( A1 * trigfact + 0.5);
+ t2 = - (sint_t)( A2 * trigfact + 0.5);
+ startpoint=0;
+ for (j=1; schmittBuffer[j]<=t1 && j<blockSize; j++);
+ for (; !(schmittBuffer[j] >=t2 &&
+ schmittBuffer[j+1]< t2) && j<blockSize; j++);
+ startpoint=j;
+ schmittTriggered=0;
+ endpoint=startpoint+1;
+ for(j=startpoint,tc=0; j<blockSize; j++) {
+ if (!schmittTriggered) {
+ schmittTriggered = (schmittBuffer[j] >= t1);
+ } else if (schmittBuffer[j]>=t2 && schmittBuffer[j+1]<t2) {
+ endpoint=j;
+ tc++;
+ schmittTriggered = 0;
+ }
+ }
+ if (endpoint > startpoint) {
+ freq = ((smpl_t)p->rate*(tc/(smpl_t)(endpoint-startpoint)));
+ }
+ }
+ }
+
+ p->schmittBuffer = schmittBuffer;
+ p->schmittPointer = schmittPointer;
+ return freq;
+}
+
+void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p)
+{
+ AUBIO_FREE(p->schmittBuffer);
+ AUBIO_FREE(p);
+}
+
--- /dev/null
+++ b/src/pitch/pitchschmitt.h
@@ -1,0 +1,71 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** \file
+
+ Pitch detection using a Schmitt trigger
+
+ This pitch extraction method implements a Schmitt trigger to estimate the
+ period of a signal.
+
+ This file was derived from the tuneit project, written by Mario Lang to
+ detect the fundamental frequency of a sound.
+
+ see http://delysid.org/tuneit.html
+
+*/
+
+#ifndef _PITCHSCHMITT_H
+#define _PITCHSCHMITT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** pitch detection object */
+typedef struct _aubio_pitchschmitt_t aubio_pitchschmitt_t;
+
+/** execute pitch detection on an input buffer
+
+ \param p pitch detection object as returned by new_aubio_pitchschmitt
+ \param input input signal window (length as specified at creation time)
+
+*/
+smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input);
+/** creation of the pitch detection object
+
+ \param size size of the input buffer to analyse
+ \param samplerate sampling rate of the signal
+
+*/
+aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate);
+/** deletion of the pitch detection object
+
+ \param p pitch detection object as returned by new_aubio_pitchschmitt
+
+*/
+void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PITCHSCHMITT_H */
+
--- /dev/null
+++ b/src/pitch/pitchyin.c
@@ -1,0 +1,115 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* This algorithm was developped by A. de Cheveigne and H. Kawahara and
+ * published in:
+ *
+ * de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
+ * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
+ *
+ * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
+ */
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "mathutils.h"
+#include "pitch/pitchyin.h"
+
+/* outputs the difference function */
+void aubio_pitchyin_diff(fvec_t * input, fvec_t * yin){
+ uint_t c,j,tau;
+ smpl_t tmp;
+ for (c=0;c<input->channels;c++)
+ {
+ for (tau=0;tau<yin->length;tau++)
+ {
+ yin->data[c][tau] = 0.;
+ }
+ for (tau=1;tau<yin->length;tau++)
+ {
+ for (j=0;j<yin->length;j++)
+ {
+ tmp = input->data[c][j] - input->data[c][j+tau];
+ yin->data[c][tau] += SQR(tmp);
+ }
+ }
+ }
+}
+
+/* cumulative mean normalized difference function */
+void aubio_pitchyin_getcum(fvec_t * yin) {
+ uint_t c,tau;
+ smpl_t tmp;
+ for (c=0;c<yin->channels;c++)
+ {
+ tmp = 0.;
+ yin->data[c][0] = 1.;
+ //AUBIO_DBG("%f\t",yin->data[c][0]);
+ for (tau=1;tau<yin->length;tau++)
+ {
+ tmp += yin->data[c][tau];
+ yin->data[c][tau] *= tau/tmp;
+ //AUBIO_DBG("%f\t",yin->data[c][tau]);
+ }
+ //AUBIO_DBG("\n");
+ }
+}
+
+uint_t aubio_pitchyin_getpitch(fvec_t * yin) {
+ uint_t c=0,tau=1;
+ do
+ {
+ if(yin->data[c][tau] < 0.1) {
+ while (yin->data[c][tau+1] < yin->data[c][tau]) {
+ tau++;
+ }
+ return tau;
+ }
+ tau++;
+ } while (tau<yin->length);
+ //AUBIO_DBG("No pitch found");
+ return 0;
+}
+
+
+/* all the above in one */
+smpl_t aubio_pitchyin_getpitchfast(fvec_t * input, fvec_t * yin, smpl_t tol){
+ uint_t c=0,j,tau = 0;
+ sint_t period;
+ smpl_t tmp = 0., tmp2 = 0.;
+ yin->data[c][0] = 1.;
+ for (tau=1;tau<yin->length;tau++)
+ {
+ yin->data[c][tau] = 0.;
+ for (j=0;j<yin->length;j++)
+ {
+ tmp = input->data[c][j] - input->data[c][j+tau];
+ yin->data[c][tau] += SQR(tmp);
+ }
+ tmp2 += yin->data[c][tau];
+ yin->data[c][tau] *= tau/tmp2;
+ period = tau-3;
+ if(tau > 4 && (yin->data[c][period] < tol) &&
+ (yin->data[c][period] < yin->data[c][period+1])) {
+ return vec_quadint_min(yin,period,1);
+ }
+ }
+ return vec_quadint_min(yin,vec_min_elem(yin),1);
+ //return 0;
+}
+
--- /dev/null
+++ b/src/pitch/pitchyin.h
@@ -1,0 +1,75 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/** \file
+
+ Pitch detection using the YIN algorithm
+
+ This algorithm was developped by A. de Cheveigne and H. Kawahara and
+ published in:
+
+ De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
+ estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
+
+ see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
+
+*/
+
+#ifndef PITCHYIN_H
+#define PITCHYIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** compute difference function
+
+ \param input input signal
+ \param yinbuf output buffer to store difference function (half shorter than input)
+
+*/
+void aubio_pitchyin_diff(fvec_t * input, fvec_t * yinbuf);
+
+/** in place computation of the YIN cumulative normalised function
+
+ \param yinbuf input signal (a square difference function), also used to store function
+
+*/
+void aubio_pitchyin_getcum(fvec_t * yinbuf);
+
+/** detect pitch in a YIN function
+
+ \param yinbuf input buffer as computed by aubio_pitchyin_getcum
+
+*/
+uint_t aubio_pitchyin_getpitch(fvec_t *yinbuf);
+
+/** fast implementation of the YIN algorithm
+
+ \param input input signal
+ \param yinbuf input buffer used to compute the YIN function
+ \param tol tolerance parameter for minima selection [default 0.15]
+
+*/
+smpl_t aubio_pitchyin_getpitchfast(fvec_t * input, fvec_t *yinbuf, smpl_t tol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PITCHYIN_H*/
--- /dev/null
+++ b/src/pitch/pitchyinfft.c
@@ -1,0 +1,153 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "aubio_priv.h"
+#include "sample.h"
+#include "mathutils.h"
+#include "fft.h"
+#include "pitch/pitchyinfft.h"
+
+/** pitch yinfft structure */
+struct _aubio_pitchyinfft_t {
+ fvec_t * win; /**< temporal weighting window */
+ fvec_t * winput; /**< windowed spectrum */
+ cvec_t * res; /**< complex vector to compute square difference function */
+ fvec_t * sqrmag; /**< square difference function */
+ fvec_t * weight; /**< spectral weighting window (psychoacoustic model) */
+ cvec_t * fftout; /**< Fourier transform output */
+ aubio_fft_t * fft; /**< fft object to compute square difference function */
+ fvec_t * yinfft; /**< Yin function */
+};
+
+static const smpl_t freqs[] = {0., 20., 25., 31.5, 40., 50., 63., 80., 100.,
+ 125., 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250.,
+ 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000.,
+ 12500., 15000., 20000., 25100};
+
+static const smpl_t weight[] = {-75.8, -70.1, -60.8, -52.1, -44.2, -37.5,
+ -31.3, -25.6, -20.9, -16.5, -12.6, -9.6, -7.0, -4.7, -3.0, -1.8, -0.8,
+ -0.2, -0.0, 0.5, 1.6, 3.2, 5.4, 7.8, 8.1, 5.3, -2.4, -11.1, -12.8,
+ -12.2, -7.4, -17.8, -17.8, -17.8};
+
+aubio_pitchyinfft_t * new_aubio_pitchyinfft (uint_t bufsize)
+{
+ aubio_pitchyinfft_t * p = AUBIO_NEW(aubio_pitchyinfft_t);
+ p->winput = new_fvec(bufsize,1);
+ p->fft = new_aubio_fft(bufsize, 1);
+ p->fftout = new_cvec(bufsize,1);
+ p->sqrmag = new_fvec(bufsize,1);
+ p->res = new_cvec(bufsize,1);
+ p->yinfft = new_fvec(bufsize/2+1,1);
+ p->win = new_fvec(bufsize,1);
+ aubio_window(p->win->data[0], bufsize, aubio_win_hanningz);
+ p->weight = new_fvec(bufsize/2+1,1);
+ {
+ uint_t i = 0, j = 1;
+ smpl_t freq = 0, a0 = 0, a1 = 0, f0 = 0, f1 = 0;
+ for (i=0; i<p->weight->length; i++) {
+ freq = (smpl_t)i/(smpl_t)bufsize*(smpl_t)44100.;
+ while (freq > freqs[j]) {
+ j +=1;
+ }
+ a0 = weight[j-1];
+ f0 = freqs[j-1];
+ a1 = weight[j];
+ f1 = freqs[j];
+ if (f0 == f1) { // just in case
+ p->weight->data[0][i] = a0;
+ } else if (f0 == 0) { // y = ax+b
+ p->weight->data[0][i] = (a1-a0)/f1*freq + a0;
+ } else {
+ p->weight->data[0][i] = (a1-a0)/(f1-f0)*freq +
+ (a0 - (a1 - a0)/(f1/f0 - 1.));
+ }
+ while (freq > freqs[j]) {
+ j +=1;
+ }
+ //AUBIO_DBG("%f\n",p->weight->data[0][i]);
+ p->weight->data[0][i] = DB2LIN(p->weight->data[0][i]);
+ //p->weight->data[0][i] = SQRT(DB2LIN(p->weight->data[0][i]));
+ }
+ }
+ return p;
+}
+
+smpl_t aubio_pitchyinfft_detect(aubio_pitchyinfft_t * p, fvec_t * input, smpl_t tol) {
+ uint_t tau, l = 0;
+ uint_t halfperiod;
+ smpl_t tmp = 0, sum = 0;
+ cvec_t * res = (cvec_t *)p->res;
+ fvec_t * yin = (fvec_t *)p->yinfft;
+ for (l=0; l < input->length; l++){
+ p->winput->data[0][l] = p->win->data[0][l] * input->data[0][l];
+ }
+ aubio_fft_do(p->fft,p->winput,p->fftout);
+ for (l=0; l < p->fftout->length; l++){
+ p->sqrmag->data[0][l] = SQR(p->fftout->norm[0][l]);
+ p->sqrmag->data[0][l] *= p->weight->data[0][l];
+ }
+ for (l=1; l < p->fftout->length; l++){
+ p->sqrmag->data[0][(p->fftout->length-1)*2-l] =
+ SQR(p->fftout->norm[0][l]);
+ p->sqrmag->data[0][(p->fftout->length-1)*2-l] *=
+ p->weight->data[0][l];
+ }
+ for (l=0; l < p->sqrmag->length/2+1; l++) {
+ sum += p->sqrmag->data[0][l];
+ }
+ sum *= 2.;
+ aubio_fft_do(p->fft,p->sqrmag,res);
+ yin->data[0][0] = 1.;
+ for (tau=1; tau < yin->length; tau++) {
+ yin->data[0][tau] = sum -
+ res->norm[0][tau]*COS(res->phas[0][tau]);
+ tmp += yin->data[0][tau];
+ yin->data[0][tau] *= tau/tmp;
+ }
+ tau = vec_min_elem(yin);
+ if (yin->data[0][tau] < tol) {
+ /* no interpolation */
+ //return tau;
+ /* 3 point quadratic interpolation */
+ //return vec_quadint_min(yin,tau,1);
+ /* additional check for (unlikely) octave doubling in higher frequencies */
+ if (tau>35) {
+ return vec_quadint_min(yin,tau,1);
+ } else {
+ /* should compare the minimum value of each interpolated peaks */
+ halfperiod = FLOOR(tau/2+.5);
+ if (yin->data[0][halfperiod] < tol)
+ return vec_quadint_min(yin,halfperiod,1);
+ else
+ return vec_quadint_min(yin,tau,1);
+ }
+ } else
+ return 0.;
+}
+
+void del_aubio_pitchyinfft(aubio_pitchyinfft_t *p){
+ del_fvec(p->win);
+ del_aubio_fft(p->fft);
+ del_fvec(p->yinfft);
+ del_fvec(p->sqrmag);
+ del_cvec(p->res);
+ del_cvec(p->fftout);
+ del_fvec(p->winput);
+ del_fvec(p->weight);
+ AUBIO_FREE(p);
+}
--- /dev/null
+++ b/src/pitch/pitchyinfft.h
@@ -1,0 +1,69 @@
+/*
+ Copyright (C) 2003 Paul Brossier
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/** \file
+
+ Pitch detection using a spectral implementation of the YIN algorithm
+
+ This algorithm was derived from the YIN algorithm (see pitchyin.c). In this
+ implementation, a Fourier transform is used to compute a tapered square
+ difference function, which allows spectral weighting. Because the difference
+ function is tapered, the selection of the period is simplified.
+
+ Paul Brossier, ``Automatic annotation of musical audio for interactive
+ systems'', Chapter 3, Pitch Analysis, PhD thesis, Centre for Digital music,
+ Queen Mary University of London, London, UK, 2006.
+
+*/
+
+#ifndef PITCHYINFFT_H
+#define PITCHYINFFT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** pitch detection object */
+typedef struct _aubio_pitchyinfft_t aubio_pitchyinfft_t;
+
+/** execute pitch detection on an input buffer
+
+ \param p pitch detection object as returned by new_aubio_pitchyinfft
+ \param input input signal window (length as specified at creation time)
+ \param tol tolerance parameter for minima selection [default 0.85]
+
+*/
+smpl_t aubio_pitchyinfft_detect (aubio_pitchyinfft_t *p, fvec_t * input, smpl_t tol);
+/** creation of the pitch detection object
+
+ \param bufsize size of the input buffer to analyse
+
+*/
+aubio_pitchyinfft_t * new_aubio_pitchyinfft (uint_t bufsize);
+/** deletion of the pitch detection object
+
+ \param p pitch detection object as returned by new_aubio_pitchyinfft()
+
+*/
+void del_aubio_pitchyinfft (aubio_pitchyinfft_t *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PITCHYINFFT_H*/
--- a/src/pitchdetection.c
+++ b/src/pitchdetection.c
@@ -21,11 +21,11 @@
#include "phasevoc.h"
#include "mathutils.h"
#include "filter.h"
-#include "pitchmcomb.h"
-#include "pitchyin.h"
-#include "pitchfcomb.h"
-#include "pitchschmitt.h"
-#include "pitchyinfft.h"
+#include "pitch/pitchmcomb.h"
+#include "pitch/pitchyin.h"
+#include "pitch/pitchfcomb.h"
+#include "pitch/pitchschmitt.h"
+#include "pitch/pitchyinfft.h"
#include "pitchdetection.h"
typedef smpl_t (*aubio_pitchdetection_func_t)
--- a/src/pitchfcomb.c
+++ /dev/null
@@ -1,135 +1,0 @@
-/*
- Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "mathutils.h"
-#include "fft.h"
-#include "pitchfcomb.h"
-
-#define MAX_PEAKS 8
-
-typedef struct {
- smpl_t freq;
- smpl_t db;
-} aubio_fpeak_t;
-
-struct _aubio_pitchfcomb_t {
- uint_t fftSize;
- uint_t stepSize;
- uint_t rate;
- fvec_t * winput;
- fvec_t * win;
- cvec_t * fftOut;
- fvec_t * fftLastPhase;
- aubio_fft_t * fft;
- //aubio_pvoc_t * pvoc;
-};
-
-aubio_pitchfcomb_t * new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize, uint_t samplerate)
-{
- aubio_pitchfcomb_t * p = AUBIO_NEW(aubio_pitchfcomb_t);
- p->rate = samplerate;
- p->fftSize = bufsize;
- p->stepSize = hopsize;
- p->winput = new_fvec(bufsize,1);
- p->fftOut = new_cvec(bufsize,1);
- p->fftLastPhase = new_fvec(bufsize,1);
- p->fft = new_aubio_fft(bufsize, 1);
- p->win = new_fvec(bufsize,1);
- aubio_window(p->win->data[0], bufsize, aubio_win_hanning);
- return p;
-}
-
-/* input must be stepsize long */
-smpl_t aubio_pitchfcomb_detect (aubio_pitchfcomb_t * p, fvec_t * input)
-{
- uint_t k, l, maxharm = 0;
- smpl_t freqPerBin = p->rate/(smpl_t)p->fftSize,
- phaseDifference = TWO_PI*(smpl_t)p->stepSize/(smpl_t)p->fftSize;
- aubio_fpeak_t peaks[MAX_PEAKS];
-
- for (k=0; k<MAX_PEAKS; k++) {
- peaks[k].db = -200.;
- peaks[k].freq = 0.;
- }
-
- for (k=0; k < input->length; k++){
- p->winput->data[0][k] = p->win->data[0][k] * input->data[0][k];
- }
- aubio_fft_do(p->fft,p->winput,p->fftOut);
-
- for (k=0; k<=p->fftSize/2; k++) {
- smpl_t
- magnitude = 20.*LOG10(2.*p->fftOut->norm[0][k]/(smpl_t)p->fftSize),
- phase = p->fftOut->phas[0][k],
- tmp, freq;
-
- /* compute phase difference */
- tmp = phase - p->fftLastPhase->data[0][k];
- p->fftLastPhase->data[0][k] = phase;
-
- /* subtract expected phase difference */
- tmp -= (smpl_t)k*phaseDifference;
-
- /* map delta phase into +/- Pi interval */
- tmp = aubio_unwrap2pi(tmp);
-
- /* get deviation from bin frequency from the +/- Pi interval */
- tmp = p->fftSize/(smpl_t)p->stepSize*tmp/(TWO_PI);
-
- /* compute the k-th partials' true frequency */
- freq = (smpl_t)k*freqPerBin + tmp*freqPerBin;
-
- if (freq > 0.0 && magnitude > peaks[0].db) { // && magnitude < 0) {
- memmove(peaks+1, peaks, sizeof(aubio_fpeak_t)*(MAX_PEAKS-1));
- peaks[0].freq = freq;
- peaks[0].db = magnitude;
- }
- }
-
- k = 0;
- for (l=1; l<MAX_PEAKS && peaks[l].freq > 0.0; l++) {
- sint_t harmonic;
- for (harmonic=5; harmonic>1; harmonic--) {
- if (peaks[0].freq / peaks[l].freq < harmonic+.02 &&
- peaks[0].freq / peaks[l].freq > harmonic-.02) {
- if (harmonic > (sint_t)maxharm &&
- peaks[0].db < peaks[l].db/2) {
- maxharm = harmonic;
- k = l;
- }
- }
- }
- }
- /* quick hack to clean output a bit */
- if (peaks[k].freq > 5000.) return 0.;
- return peaks[k].freq;
-}
-
-void del_aubio_pitchfcomb (aubio_pitchfcomb_t * p)
-{
- del_cvec(p->fftOut);
- del_fvec(p->fftLastPhase);
- del_fvec(p->win);
- del_fvec(p->winput);
- del_aubio_fft(p->fft);
- AUBIO_FREE(p);
-}
-
--- a/src/pitchfcomb.h
+++ /dev/null
@@ -1,73 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** \file
-
- Pitch detection using a fast harmonic comb filter
-
- This pitch extraction method implements a fast harmonic comb filter to
- determine the fundamental frequency of a harmonic sound.
-
- This file was derived from the tuneit project, written by Mario Lang to
- detect the fundamental frequency of a sound.
-
- see http://delysid.org/tuneit.html
-
-*/
-
-#ifndef _PITCHFCOMB_H
-#define _PITCHFCOMB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** pitch detection object */
-typedef struct _aubio_pitchfcomb_t aubio_pitchfcomb_t;
-
-/** execute pitch detection on an input buffer
-
- \param p pitch detection object as returned by new_aubio_pitchfcomb
- \param input input signal window (length as specified at creation time)
-
-*/
-smpl_t aubio_pitchfcomb_detect (aubio_pitchfcomb_t *p, fvec_t * input);
-/** creation of the pitch detection object
-
- \param bufsize size of the input buffer to analyse
- \param hopsize step size between two consecutive analysis instant
- \param samplerate sampling rate of the signal
-
-*/
-aubio_pitchfcomb_t * new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize, uint_t samplerate);
-/** deletion of the pitch detection object
-
- \param p pitch detection object as returned by new_aubio_pitchfcomb
-
-*/
-void del_aubio_pitchfcomb (aubio_pitchfcomb_t *p);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PITCHFCOMB_H */
-
-
--- a/src/pitchmcomb.c
+++ /dev/null
@@ -1,390 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "mathutils.h"
-#include "pitchmcomb.h"
-
-#define CAND_SWAP(a,b) { register aubio_spectralcandidate_t *t=(a);(a)=(b);(b)=t; }
-
-typedef struct _aubio_spectralpeak_t aubio_spectralpeak_t;
-typedef struct _aubio_spectralcandidate_t aubio_spectralcandidate_t;
-uint_t aubio_pitchmcomb_get_root_peak(aubio_spectralpeak_t * peaks, uint_t length);
-uint_t aubio_pitchmcomb_quadpick(aubio_spectralpeak_t * spectral_peaks, fvec_t * X);
-void aubio_pitchmcomb_spectral_pp(aubio_pitchmcomb_t * p, fvec_t * oldmag);
-void aubio_pitchmcomb_combdet(aubio_pitchmcomb_t * p, fvec_t * newmag);
-/* not used but useful : sort by amplitudes (or anything else)
- * sort_pitchpeak(peaks, length);
- */
-/** spectral_peak comparison function (must return signed int) */
-static sint_t aubio_pitchmcomb_sort_peak_comp(const void *x, const void *y);
-/** sort spectral_peak against their mag */
-void aubio_pitchmcomb_sort_peak(aubio_spectralpeak_t * peaks, uint_t nbins);
-
-/** sort spectral_candidate against their comb ene */
-void aubio_pitchmcomb_sort_cand_ene(aubio_spectralcandidate_t ** candidates, uint_t nbins);
-/** sort spectral_candidate against their frequency */
-void aubio_pitchmcomb_sort_cand_freq(aubio_spectralcandidate_t ** candidates, uint_t nbins);
-
-struct _aubio_pitchmcomb_t {
- smpl_t threshold; /**< offset threshold [0.033 or 0.01] */
- smpl_t alpha; /**< normalisation exponent [9] */
- smpl_t cutoff; /**< low-pass filter cutoff [0.34, 1] */
- smpl_t tol; /**< tolerance [0.05] */
- smpl_t tau; /**< frequency precision [44100/4096] */
- uint_t win_post; /**< median filter window length */
- uint_t win_pre; /**< median filter window */
- uint_t ncand; /**< maximum number of candidates (combs) */
- uint_t npartials; /**< maximum number of partials per combs */
- uint_t count; /**< picked picks */
- uint_t goodcandidate; /**< best candidate */
- uint_t spec_partition; /**< spectrum partition to consider */
- aubio_spectralpeak_t * peaks; /**< up to length win/spec_partition */
- aubio_spectralcandidate_t ** candidates; /** up to five candidates */
- /* some scratch pads */
- /** \bug (unnecessary copied from fftgrain?) */
- fvec_t * newmag; /**< vec to store mag */
- fvec_t * scratch; /**< vec to store modified mag */
- fvec_t * scratch2; /**< vec to compute moving median */
- fvec_t * theta; /**< vec to store phase */
- smpl_t phasediff;
- smpl_t phasefreq;
- /** threshfn: name or handle of fn for computing adaptive threshold [median] */
- /** aubio_thresholdfn_t thresholdfn; */
- /** picker: name or handle of fn for picking event times [quadpick] */
- /** aubio_pickerfn_t pickerfn; */
-};
-
-/** spectral peak object */
-struct _aubio_spectralpeak_t {
- uint_t bin; /**< bin [0-(length-1)] */
- smpl_t ebin; /**< estimated bin */
- smpl_t mag; /**< peak magnitude */
-};
-
-/** spectral candidates array object */
-struct _aubio_spectralcandidate_t {
- smpl_t ebin; /**< interpolated bin */
- smpl_t * ecomb; /**< comb */
- smpl_t ene; /**< candidate energy */
- smpl_t len; /**< length */
-};
-
-
-smpl_t aubio_pitchmcomb_detect(aubio_pitchmcomb_t * p, cvec_t * fftgrain) {
- uint_t i=0,j;
- smpl_t instfreq;
- fvec_t * newmag = (fvec_t *)p->newmag;
- //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta;
- /* copy incoming grain to newmag */
- for (j=0; j< newmag->length; j++)
- newmag->data[i][j]=fftgrain->norm[i][j];
- /* detect only if local energy > 10. */
- //if (vec_local_energy(newmag)>10.) {
- //hfc = vec_local_hfc(newmag); //not used
- aubio_pitchmcomb_spectral_pp(p, newmag);
- aubio_pitchmcomb_combdet(p,newmag);
- //aubio_pitchmcomb_sort_cand_freq(p->candidates,p->ncand);
- //return p->candidates[p->goodcandidate]->ebin;
- j = (uint_t)FLOOR(p->candidates[p->goodcandidate]->ebin+.5);
- instfreq = aubio_unwrap2pi(fftgrain->phas[0][j]
- - p->theta->data[0][j] - j*p->phasediff);
- instfreq *= p->phasefreq;
- /* store phase for next run */
- for (j=0; j< p->theta->length; j++) {
- p->theta->data[i][j]=fftgrain->phas[i][j];
- }
- //return p->candidates[p->goodcandidate]->ebin;
- return FLOOR(p->candidates[p->goodcandidate]->ebin+.5) + instfreq;
- /*} else {
- return -1.;
- }*/
-}
-
-uint_t aubio_pitch_cands(aubio_pitchmcomb_t * p, cvec_t * fftgrain,
- smpl_t * cands) {
- uint_t i=0,j;
- uint_t k;
- fvec_t * newmag = (fvec_t *)p->newmag;
- aubio_spectralcandidate_t ** scands =
- (aubio_spectralcandidate_t **)(p->candidates);
- //smpl_t hfc; //fe=instfreq(theta1,theta,ops); //theta1=theta;
- /* copy incoming grain to newmag */
- for (j=0; j< newmag->length; j++)
- newmag->data[i][j]=fftgrain->norm[i][j];
- /* detect only if local energy > 10. */
- if (vec_local_energy(newmag)>10.) {
- /* hfc = vec_local_hfc(newmag); do not use */
- aubio_pitchmcomb_spectral_pp(p, newmag);
- aubio_pitchmcomb_combdet(p,newmag);
- aubio_pitchmcomb_sort_cand_freq(scands,p->ncand);
- /* store ncand comb energies in cands[1:ncand] */
- for (k = 0; k<p->ncand; k++)
- cands[k] = p->candidates[k]->ene;
- /* store ncand[end] freq in cands[end] */
- cands[p->ncand] = p->candidates[p->ncand-1]->ebin;
- return 1;
- } else {
- for (k = 0; k<p->ncand; k++)
- cands[k] = 0;
- return 0;
- }
-}
-
-void aubio_pitchmcomb_spectral_pp(aubio_pitchmcomb_t * p, fvec_t * newmag) {
- fvec_t * mag = (fvec_t *)p->scratch;
- fvec_t * tmp = (fvec_t *)p->scratch2;
- uint_t i=0,j;
- uint_t length = mag->length;
- /* copy newmag to mag (scracth) */
- for (j=0;j<length;j++) {
- mag->data[i][j] = newmag->data[i][j];
- }
- vec_dc_removal(mag); /* dc removal */
- vec_alpha_normalise(mag,p->alpha); /* alpha normalisation */
- /* skipped */ /* low pass filtering */
- /** \bug vec_moving_thres may write out of bounds */
- vec_adapt_thres(mag,tmp,p->win_post,p->win_pre); /* adaptative threshold */
- vec_add(mag,-p->threshold); /* fixed threshold */
- {
- aubio_spectralpeak_t * peaks = (aubio_spectralpeak_t *)p->peaks;
- uint_t count;
- /* return bin and ebin */
- count = aubio_pitchmcomb_quadpick(peaks,mag);
- for (j=0;j<count;j++)
- peaks[j].mag = newmag->data[i][peaks[j].bin];
- /* reset non peaks */
- for (j=count;j<length;j++)
- peaks[j].mag = 0.;
- p->peaks = peaks;
- p->count = count;
- }
-}
-
-void aubio_pitchmcomb_combdet(aubio_pitchmcomb_t * p, fvec_t * newmag) {
- aubio_spectralpeak_t * peaks = (aubio_spectralpeak_t *)p->peaks;
- aubio_spectralcandidate_t ** candidate =
- (aubio_spectralcandidate_t **)p->candidates;
-
- /* parms */
- uint_t N = p->npartials; /* maximum number of partials to be considered 10 */
- uint_t M = p->ncand; /* maximum number of combs to be considered 5 */
- uint_t length = newmag->length;
- uint_t count = p->count;
- uint_t k;
- uint_t l;
- uint_t d;
- uint_t curlen = 0;
-
- smpl_t delta2;
- smpl_t xx;
- uint_t position = 0;
-
- uint_t root_peak = 0;
- uint_t tmpl = 0;
- smpl_t tmpene = 0.;
-
- /* get the biggest peak in the spectrum */
- root_peak = aubio_pitchmcomb_get_root_peak(peaks,count);
- /* not enough partials in highest notes, could be forced */
- //if (peaks[root_peak].ebin >= aubio_miditofreq(85.)/p->tau) N=2;
- //if (peaks[root_peak].ebin >= aubio_miditofreq(90.)/p->tau) N=1;
- /* now calculate the energy of each of the 5 combs */
- for (l=0;l<M;l++) {
- smpl_t scaler = (1./(l+1.));
- candidate[l]->ene = 0.; /* reset ene and len sums */
- candidate[l]->len = 0.;
- candidate[l]->ebin=scaler*peaks[root_peak].ebin;
- /* if less than N peaks available, curlen < N */
- if (candidate[l]->ebin != 0.)
- curlen = (uint_t)FLOOR(length/(candidate[l]->ebin));
- curlen = (N < curlen )? N : curlen;
- /* fill candidate[l]->ecomb[k] with (k+1)*candidate[l]->ebin */
- for (k=0;k<curlen;k++)
- candidate[l]->ecomb[k]=(candidate[l]->ebin)*(k+1.);
- for (k=curlen;k<length;k++)
- candidate[l]->ecomb[k]=0.;
- /* for each in candidate[l]->ecomb[k] */
- for (k=0;k<curlen;k++) {
- xx = 100000.;
- /** get the candidate->ecomb the closer to peaks.ebin
- * (to cope with the inharmonicity)*/
- for (d=0;d<count;d++) {
- delta2 = ABS(candidate[l]->ecomb[k]-peaks[d].ebin);
- if (delta2 <= xx) {
- position = d;
- xx = delta2;
- }
- }
- /* for a Q factor of 17, maintaining "constant Q filtering",
- * and sum energy and length over non null combs */
- if ( 17. * xx < candidate[l]->ecomb[k] ) {
- candidate[l]->ecomb[k]=peaks[position].ebin;
- candidate[l]->ene += /* ecomb rounded to nearest int */
- POW(newmag->data[0][(uint_t)FLOOR(candidate[l]->ecomb[k]+.5)],0.25);
- candidate[l]->len += 1./curlen;
- } else
- candidate[l]->ecomb[k]=0.;
- }
- /* punishment */
- /*if (candidate[l]->len<0.6)
- candidate[l]->ene=0.; */
- /* remember best candidate energy (in polyphonic, could check for
- * tmpene*1.1 < candidate->ene to reduce jumps towards low frequencies) */
- if (tmpene < candidate[l]->ene) {
- tmpl = l;
- tmpene = candidate[l]->ene;
- }
- }
- //p->candidates=candidate;
- //p->peaks=peaks;
- p->goodcandidate = tmpl;
-}
-
-/** T=quadpick(X): return indices of elements of X which are peaks and positive
- * exact peak positions are retrieved by quadratic interpolation
- *
- * \bug peak-picking too picky, sometimes counts too many peaks ?
- */
-uint_t aubio_pitchmcomb_quadpick(aubio_spectralpeak_t * spectral_peaks, fvec_t * X){
- uint_t i, j, ispeak, count = 0;
- for (i=0;i<X->channels;i++)
- for (j=1;j<X->length-1;j++) {
- ispeak = vec_peakpick(X,j);
- if (ispeak) {
- count += ispeak;
- spectral_peaks[count-1].bin = j;
- spectral_peaks[count-1].ebin = vec_quadint(X,j) - 1.;
- }
- }
- return count;
-}
-
-/* get predominant partial */
-uint_t aubio_pitchmcomb_get_root_peak(aubio_spectralpeak_t * peaks, uint_t length) {
- uint_t i,pos=0;
- smpl_t tmp = 0.;
- for (i=0;i<length;i++)
- if (tmp <= peaks[i].mag) {
- pos = i;
- tmp = peaks[i].mag;
- }
- return pos;
-}
-
-void aubio_pitchmcomb_sort_peak(aubio_spectralpeak_t * peaks, uint_t nbins) {
- qsort(peaks, nbins, sizeof(aubio_spectralpeak_t),
- aubio_pitchmcomb_sort_peak_comp);
-}
-static sint_t aubio_pitchmcomb_sort_peak_comp(const void *x, const void *y) {
- return (((aubio_spectralpeak_t *)y)->mag - ((aubio_spectralpeak_t *)x)->mag);
-}
-
-
-void aubio_pitchmcomb_sort_cand_ene(aubio_spectralcandidate_t ** candidates, uint_t nbins) {
- uint_t cur = 0;
- uint_t run = 0;
- for (cur=0;cur<nbins;cur++) {
- run = cur + 1;
- for (run=cur;run<nbins;run++) {
- if(candidates[run]->ene > candidates[cur]->ene)
- CAND_SWAP(candidates[run], candidates[cur]);
- }
- }
-}
-
-
-void aubio_pitchmcomb_sort_cand_freq(aubio_spectralcandidate_t ** candidates, uint_t nbins) {
- uint_t cur = 0;
- uint_t run = 0;
- for (cur=0;cur<nbins;cur++) {
- run = cur + 1;
- for (run=cur;run<nbins;run++) {
- if(candidates[run]->ebin < candidates[cur]->ebin)
- CAND_SWAP(candidates[run], candidates[cur]);
- }
- }
-}
-
-aubio_pitchmcomb_t * new_aubio_pitchmcomb(uint_t bufsize, uint_t hopsize, uint_t channels, uint_t samplerate) {
- aubio_pitchmcomb_t * p = AUBIO_NEW(aubio_pitchmcomb_t);
- /* bug: should check if size / 8 > post+pre+1 */
- uint_t i, j;
- uint_t spec_size;
- p->spec_partition = 4;
- p->ncand = 5;
- p->npartials = 5;
- p->cutoff = 1.;
- p->threshold = 0.01;
- p->win_post = 8;
- p->win_pre = 7;
- p->tau = samplerate/bufsize;
- p->alpha = 9.;
- p->goodcandidate = 0;
- p->phasefreq = bufsize/hopsize/TWO_PI;
- p->phasediff = TWO_PI*hopsize/bufsize;
- spec_size = bufsize/p->spec_partition;
- //p->pickerfn = quadpick;
- //p->biquad = new_biquad(0.1600,0.3200,0.1600, -0.5949, 0.2348);
- /* allocate temp memory */
- p->newmag = new_fvec(spec_size,channels);
- /* array for median */
- p->scratch = new_fvec(spec_size,channels);
- /* array for phase */
- p->theta = new_fvec(spec_size,channels);
- /* array for adaptative threshold */
- p->scratch2 = new_fvec(p->win_post+p->win_pre+1,channels);
- /* array of spectral peaks */
- p->peaks = AUBIO_ARRAY(aubio_spectralpeak_t,spec_size);
- for (i = 0; i < spec_size; i++) {
- p->peaks[i].bin = 0.;
- p->peaks[i].ebin = 0.;
- p->peaks[i].mag = 0.;
- }
- /* array of pointers to spectral candidates */
- p->candidates = AUBIO_ARRAY(aubio_spectralcandidate_t *,p->ncand);
- for (i=0;i<p->ncand;i++) {
- p->candidates[i] = AUBIO_NEW(aubio_spectralcandidate_t);
- p->candidates[i]->ecomb = AUBIO_ARRAY(smpl_t, spec_size);
- for (j=0; j < spec_size; j++) {
- p->candidates[i]->ecomb[j] = 0.;
- }
- p->candidates[i]->ene = 0.;
- p->candidates[i]->ebin = 0.;
- p->candidates[i]->len = 0.;
- }
- return p;
-}
-
-
-void del_aubio_pitchmcomb (aubio_pitchmcomb_t *p) {
- uint_t i;
- del_fvec(p->newmag);
- del_fvec(p->scratch);
- del_fvec(p->theta);
- del_fvec(p->scratch2);
- AUBIO_FREE(p->peaks);
- for (i=0;i<p->ncand;i++) {
- AUBIO_FREE(p->candidates[i]->ecomb);
- AUBIO_FREE(p->candidates[i]);
- }
- AUBIO_FREE(p->candidates);
- AUBIO_FREE(p);
-}
--- a/src/pitchmcomb.h
+++ /dev/null
@@ -1,74 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** \file
-
- Pitch detection using multiple-comb filter
-
- This fundamental frequency estimation algorithm implements spectral
- flattening, multi-comb filtering and peak histogramming.
-
- This method was designed by Juan P. Bello and described in:
-
- Juan-Pablo Bello. ``Towards the Automated Analysis of Simple Polyphonic
- Music''. PhD thesis, Centre for Digital Music, Queen Mary University of
- London, London, UK, 2003.
-
-*/
-
-#ifndef PITCHMCOMB_H
-#define PITCHMCOMB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** pitch detection object */
-typedef struct _aubio_pitchmcomb_t aubio_pitchmcomb_t;
-
-/** execute pitch detection on an input spectral frame
-
- \param p pitch detection object as returned by new_aubio_pitchmcomb
- \param fftgrain input signal spectrum as computed by aubio_pvoc_do
-
-*/
-smpl_t aubio_pitchmcomb_detect(aubio_pitchmcomb_t * p, cvec_t * fftgrain);
-/** select the best candidates */
-uint_t aubio_pitch_cands(aubio_pitchmcomb_t * p, cvec_t * fftgrain, smpl_t * cands);
-/** creation of the pitch detection object
-
- \param bufsize size of the input buffer to analyse
- \param hopsize step size between two consecutive analysis instant
- \param channels number of channels to analyse
- \param samplerate sampling rate of the signal
-
-*/
-aubio_pitchmcomb_t * new_aubio_pitchmcomb(uint_t bufsize, uint_t hopsize, uint_t channels, uint_t samplerate);
-/** deletion of the pitch detection object
-
- \param p pitch detection object as returned by new_aubio_pitchfcomb
-
-*/
-void del_aubio_pitchmcomb(aubio_pitchmcomb_t *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif/*PITCHMCOMB_H*/
--- a/src/pitchschmitt.c
+++ /dev/null
@@ -1,107 +1,0 @@
-/*
- Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "pitchschmitt.h"
-
-smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata);
-
-struct _aubio_pitchschmitt_t {
- uint_t blockSize;
- uint_t rate;
- signed short int *schmittBuffer;
- signed short int *schmittPointer;
-};
-
-aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate)
-{
- aubio_pitchschmitt_t * p = AUBIO_NEW(aubio_pitchschmitt_t);
- p->blockSize = size;
- p->schmittBuffer = AUBIO_ARRAY(signed short int,p->blockSize);
- p->schmittPointer = p->schmittBuffer;
- p->rate = samplerate;
- return p;
-}
-
-smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input)
-{
- signed short int buf[input->length];
- uint_t i;
- for (i=0; i<input->length; i++) {
- buf[i] = input->data[0][i]*32768.;
- }
- return aubio_schmittS16LE(p, input->length, buf);
-}
-
-smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata)
-{
- uint_t i, j;
- uint_t blockSize = p->blockSize;
- signed short int *schmittBuffer = p->schmittBuffer;
- signed short int *schmittPointer = p->schmittPointer;
-
- smpl_t freq = 0., trigfact = 0.6;
-
- for (i=0; i<nframes; i++) {
- *schmittPointer++ = indata[i];
- if (schmittPointer-schmittBuffer >= (sint_t)blockSize) {
- sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered;
-
- schmittPointer = schmittBuffer;
-
- for (j=0,A1=0,A2=0; j<blockSize; j++) {
- if (schmittBuffer[j]>0 && A1<schmittBuffer[j]) A1 = schmittBuffer[j];
- if (schmittBuffer[j]<0 && A2<-schmittBuffer[j]) A2 = -schmittBuffer[j];
- }
- t1 = (sint_t)( A1 * trigfact + 0.5);
- t2 = - (sint_t)( A2 * trigfact + 0.5);
- startpoint=0;
- for (j=1; schmittBuffer[j]<=t1 && j<blockSize; j++);
- for (; !(schmittBuffer[j] >=t2 &&
- schmittBuffer[j+1]< t2) && j<blockSize; j++);
- startpoint=j;
- schmittTriggered=0;
- endpoint=startpoint+1;
- for(j=startpoint,tc=0; j<blockSize; j++) {
- if (!schmittTriggered) {
- schmittTriggered = (schmittBuffer[j] >= t1);
- } else if (schmittBuffer[j]>=t2 && schmittBuffer[j+1]<t2) {
- endpoint=j;
- tc++;
- schmittTriggered = 0;
- }
- }
- if (endpoint > startpoint) {
- freq = ((smpl_t)p->rate*(tc/(smpl_t)(endpoint-startpoint)));
- }
- }
- }
-
- p->schmittBuffer = schmittBuffer;
- p->schmittPointer = schmittPointer;
- return freq;
-}
-
-void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p)
-{
- AUBIO_FREE(p->schmittBuffer);
- AUBIO_FREE(p);
-}
-
--- a/src/pitchschmitt.h
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** \file
-
- Pitch detection using a Schmitt trigger
-
- This pitch extraction method implements a Schmitt trigger to estimate the
- period of a signal.
-
- This file was derived from the tuneit project, written by Mario Lang to
- detect the fundamental frequency of a sound.
-
- see http://delysid.org/tuneit.html
-
-*/
-
-#ifndef _PITCHSCHMITT_H
-#define _PITCHSCHMITT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** pitch detection object */
-typedef struct _aubio_pitchschmitt_t aubio_pitchschmitt_t;
-
-/** execute pitch detection on an input buffer
-
- \param p pitch detection object as returned by new_aubio_pitchschmitt
- \param input input signal window (length as specified at creation time)
-
-*/
-smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input);
-/** creation of the pitch detection object
-
- \param size size of the input buffer to analyse
- \param samplerate sampling rate of the signal
-
-*/
-aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate);
-/** deletion of the pitch detection object
-
- \param p pitch detection object as returned by new_aubio_pitchschmitt
-
-*/
-void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PITCHSCHMITT_H */
-
--- a/src/pitchyin.c
+++ /dev/null
@@ -1,115 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* This algorithm was developped by A. de Cheveigne and H. Kawahara and
- * published in:
- *
- * de Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
- * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
- *
- * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
- */
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "mathutils.h"
-#include "pitchyin.h"
-
-/* outputs the difference function */
-void aubio_pitchyin_diff(fvec_t * input, fvec_t * yin){
- uint_t c,j,tau;
- smpl_t tmp;
- for (c=0;c<input->channels;c++)
- {
- for (tau=0;tau<yin->length;tau++)
- {
- yin->data[c][tau] = 0.;
- }
- for (tau=1;tau<yin->length;tau++)
- {
- for (j=0;j<yin->length;j++)
- {
- tmp = input->data[c][j] - input->data[c][j+tau];
- yin->data[c][tau] += SQR(tmp);
- }
- }
- }
-}
-
-/* cumulative mean normalized difference function */
-void aubio_pitchyin_getcum(fvec_t * yin) {
- uint_t c,tau;
- smpl_t tmp;
- for (c=0;c<yin->channels;c++)
- {
- tmp = 0.;
- yin->data[c][0] = 1.;
- //AUBIO_DBG("%f\t",yin->data[c][0]);
- for (tau=1;tau<yin->length;tau++)
- {
- tmp += yin->data[c][tau];
- yin->data[c][tau] *= tau/tmp;
- //AUBIO_DBG("%f\t",yin->data[c][tau]);
- }
- //AUBIO_DBG("\n");
- }
-}
-
-uint_t aubio_pitchyin_getpitch(fvec_t * yin) {
- uint_t c=0,tau=1;
- do
- {
- if(yin->data[c][tau] < 0.1) {
- while (yin->data[c][tau+1] < yin->data[c][tau]) {
- tau++;
- }
- return tau;
- }
- tau++;
- } while (tau<yin->length);
- //AUBIO_DBG("No pitch found");
- return 0;
-}
-
-
-/* all the above in one */
-smpl_t aubio_pitchyin_getpitchfast(fvec_t * input, fvec_t * yin, smpl_t tol){
- uint_t c=0,j,tau = 0;
- sint_t period;
- smpl_t tmp = 0., tmp2 = 0.;
- yin->data[c][0] = 1.;
- for (tau=1;tau<yin->length;tau++)
- {
- yin->data[c][tau] = 0.;
- for (j=0;j<yin->length;j++)
- {
- tmp = input->data[c][j] - input->data[c][j+tau];
- yin->data[c][tau] += SQR(tmp);
- }
- tmp2 += yin->data[c][tau];
- yin->data[c][tau] *= tau/tmp2;
- period = tau-3;
- if(tau > 4 && (yin->data[c][period] < tol) &&
- (yin->data[c][period] < yin->data[c][period+1])) {
- return vec_quadint_min(yin,period,1);
- }
- }
- return vec_quadint_min(yin,vec_min_elem(yin),1);
- //return 0;
-}
-
--- a/src/pitchyin.h
+++ /dev/null
@@ -1,75 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/** \file
-
- Pitch detection using the YIN algorithm
-
- This algorithm was developped by A. de Cheveigne and H. Kawahara and
- published in:
-
- De Cheveigné, A., Kawahara, H. (2002) "YIN, a fundamental frequency
- estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930.
-
- see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
-
-*/
-
-#ifndef PITCHYIN_H
-#define PITCHYIN_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** compute difference function
-
- \param input input signal
- \param yinbuf output buffer to store difference function (half shorter than input)
-
-*/
-void aubio_pitchyin_diff(fvec_t * input, fvec_t * yinbuf);
-
-/** in place computation of the YIN cumulative normalised function
-
- \param yinbuf input signal (a square difference function), also used to store function
-
-*/
-void aubio_pitchyin_getcum(fvec_t * yinbuf);
-
-/** detect pitch in a YIN function
-
- \param yinbuf input buffer as computed by aubio_pitchyin_getcum
-
-*/
-uint_t aubio_pitchyin_getpitch(fvec_t *yinbuf);
-
-/** fast implementation of the YIN algorithm
-
- \param input input signal
- \param yinbuf input buffer used to compute the YIN function
- \param tol tolerance parameter for minima selection [default 0.15]
-
-*/
-smpl_t aubio_pitchyin_getpitchfast(fvec_t * input, fvec_t *yinbuf, smpl_t tol);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*PITCHYIN_H*/
--- a/src/pitchyinfft.c
+++ /dev/null
@@ -1,153 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "aubio_priv.h"
-#include "sample.h"
-#include "mathutils.h"
-#include "fft.h"
-#include "pitchyinfft.h"
-
-/** pitch yinfft structure */
-struct _aubio_pitchyinfft_t {
- fvec_t * win; /**< temporal weighting window */
- fvec_t * winput; /**< windowed spectrum */
- cvec_t * res; /**< complex vector to compute square difference function */
- fvec_t * sqrmag; /**< square difference function */
- fvec_t * weight; /**< spectral weighting window (psychoacoustic model) */
- cvec_t * fftout; /**< Fourier transform output */
- aubio_fft_t * fft; /**< fft object to compute square difference function */
- fvec_t * yinfft; /**< Yin function */
-};
-
-static const smpl_t freqs[] = {0., 20., 25., 31.5, 40., 50., 63., 80., 100.,
- 125., 160., 200., 250., 315., 400., 500., 630., 800., 1000., 1250.,
- 1600., 2000., 2500., 3150., 4000., 5000., 6300., 8000., 9000., 10000.,
- 12500., 15000., 20000., 25100};
-
-static const smpl_t weight[] = {-75.8, -70.1, -60.8, -52.1, -44.2, -37.5,
- -31.3, -25.6, -20.9, -16.5, -12.6, -9.6, -7.0, -4.7, -3.0, -1.8, -0.8,
- -0.2, -0.0, 0.5, 1.6, 3.2, 5.4, 7.8, 8.1, 5.3, -2.4, -11.1, -12.8,
- -12.2, -7.4, -17.8, -17.8, -17.8};
-
-aubio_pitchyinfft_t * new_aubio_pitchyinfft (uint_t bufsize)
-{
- aubio_pitchyinfft_t * p = AUBIO_NEW(aubio_pitchyinfft_t);
- p->winput = new_fvec(bufsize,1);
- p->fft = new_aubio_fft(bufsize, 1);
- p->fftout = new_cvec(bufsize,1);
- p->sqrmag = new_fvec(bufsize,1);
- p->res = new_cvec(bufsize,1);
- p->yinfft = new_fvec(bufsize/2+1,1);
- p->win = new_fvec(bufsize,1);
- aubio_window(p->win->data[0], bufsize, aubio_win_hanningz);
- p->weight = new_fvec(bufsize/2+1,1);
- {
- uint_t i = 0, j = 1;
- smpl_t freq = 0, a0 = 0, a1 = 0, f0 = 0, f1 = 0;
- for (i=0; i<p->weight->length; i++) {
- freq = (smpl_t)i/(smpl_t)bufsize*(smpl_t)44100.;
- while (freq > freqs[j]) {
- j +=1;
- }
- a0 = weight[j-1];
- f0 = freqs[j-1];
- a1 = weight[j];
- f1 = freqs[j];
- if (f0 == f1) { // just in case
- p->weight->data[0][i] = a0;
- } else if (f0 == 0) { // y = ax+b
- p->weight->data[0][i] = (a1-a0)/f1*freq + a0;
- } else {
- p->weight->data[0][i] = (a1-a0)/(f1-f0)*freq +
- (a0 - (a1 - a0)/(f1/f0 - 1.));
- }
- while (freq > freqs[j]) {
- j +=1;
- }
- //AUBIO_DBG("%f\n",p->weight->data[0][i]);
- p->weight->data[0][i] = DB2LIN(p->weight->data[0][i]);
- //p->weight->data[0][i] = SQRT(DB2LIN(p->weight->data[0][i]));
- }
- }
- return p;
-}
-
-smpl_t aubio_pitchyinfft_detect(aubio_pitchyinfft_t * p, fvec_t * input, smpl_t tol) {
- uint_t tau, l = 0;
- uint_t halfperiod;
- smpl_t tmp = 0, sum = 0;
- cvec_t * res = (cvec_t *)p->res;
- fvec_t * yin = (fvec_t *)p->yinfft;
- for (l=0; l < input->length; l++){
- p->winput->data[0][l] = p->win->data[0][l] * input->data[0][l];
- }
- aubio_fft_do(p->fft,p->winput,p->fftout);
- for (l=0; l < p->fftout->length; l++){
- p->sqrmag->data[0][l] = SQR(p->fftout->norm[0][l]);
- p->sqrmag->data[0][l] *= p->weight->data[0][l];
- }
- for (l=1; l < p->fftout->length; l++){
- p->sqrmag->data[0][(p->fftout->length-1)*2-l] =
- SQR(p->fftout->norm[0][l]);
- p->sqrmag->data[0][(p->fftout->length-1)*2-l] *=
- p->weight->data[0][l];
- }
- for (l=0; l < p->sqrmag->length/2+1; l++) {
- sum += p->sqrmag->data[0][l];
- }
- sum *= 2.;
- aubio_fft_do(p->fft,p->sqrmag,res);
- yin->data[0][0] = 1.;
- for (tau=1; tau < yin->length; tau++) {
- yin->data[0][tau] = sum -
- res->norm[0][tau]*COS(res->phas[0][tau]);
- tmp += yin->data[0][tau];
- yin->data[0][tau] *= tau/tmp;
- }
- tau = vec_min_elem(yin);
- if (yin->data[0][tau] < tol) {
- /* no interpolation */
- //return tau;
- /* 3 point quadratic interpolation */
- //return vec_quadint_min(yin,tau,1);
- /* additional check for (unlikely) octave doubling in higher frequencies */
- if (tau>35) {
- return vec_quadint_min(yin,tau,1);
- } else {
- /* should compare the minimum value of each interpolated peaks */
- halfperiod = FLOOR(tau/2+.5);
- if (yin->data[0][halfperiod] < tol)
- return vec_quadint_min(yin,halfperiod,1);
- else
- return vec_quadint_min(yin,tau,1);
- }
- } else
- return 0.;
-}
-
-void del_aubio_pitchyinfft(aubio_pitchyinfft_t *p){
- del_fvec(p->win);
- del_aubio_fft(p->fft);
- del_fvec(p->yinfft);
- del_fvec(p->sqrmag);
- del_cvec(p->res);
- del_cvec(p->fftout);
- del_fvec(p->winput);
- del_fvec(p->weight);
- AUBIO_FREE(p);
-}
--- a/src/pitchyinfft.h
+++ /dev/null
@@ -1,69 +1,0 @@
-/*
- Copyright (C) 2003 Paul Brossier
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/** \file
-
- Pitch detection using a spectral implementation of the YIN algorithm
-
- This algorithm was derived from the YIN algorithm (see pitchyin.c). In this
- implementation, a Fourier transform is used to compute a tapered square
- difference function, which allows spectral weighting. Because the difference
- function is tapered, the selection of the period is simplified.
-
- Paul Brossier, ``Automatic annotation of musical audio for interactive
- systems'', Chapter 3, Pitch Analysis, PhD thesis, Centre for Digital music,
- Queen Mary University of London, London, UK, 2006.
-
-*/
-
-#ifndef PITCHYINFFT_H
-#define PITCHYINFFT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** pitch detection object */
-typedef struct _aubio_pitchyinfft_t aubio_pitchyinfft_t;
-
-/** execute pitch detection on an input buffer
-
- \param p pitch detection object as returned by new_aubio_pitchyinfft
- \param input input signal window (length as specified at creation time)
- \param tol tolerance parameter for minima selection [default 0.85]
-
-*/
-smpl_t aubio_pitchyinfft_detect (aubio_pitchyinfft_t *p, fvec_t * input, smpl_t tol);
-/** creation of the pitch detection object
-
- \param bufsize size of the input buffer to analyse
-
-*/
-aubio_pitchyinfft_t * new_aubio_pitchyinfft (uint_t bufsize);
-/** deletion of the pitch detection object
-
- \param p pitch detection object as returned by new_aubio_pitchyinfft()
-
-*/
-void del_aubio_pitchyinfft (aubio_pitchyinfft_t *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*PITCHYINFFT_H*/
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -19,7 +19,7 @@
#include "aubio_priv.h"
#include "sample.h"
-#include "onsetdetection.h"
+#include "onset/detection.h"
#include "beattracking.h"
#include "phasevoc.h"
#include "peakpick.h"