From: Paul Brossier Date: Sat, 24 Nov 2007 19:47:55 +0000 (+0100) Subject: move pitch methods to pitch/, onset detection functions to onset/ X-Git-Tag: 0.4.0-beta1~967 X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=2d8cffabb484b5bee7d4d44c8f753d95ca841d03;p=aubio.git move pitch methods to pitch/, onset detection functions to onset/ --- diff --git a/src/Makefile.am b/src/Makefile.am index f13bb8d0..5e256613 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,16 +10,16 @@ pkginclude_HEADERS = aubio.h \ 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 @@ libaubio_la_SOURCES = aubio.h \ 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 @@ libaubio_la_SOURCES = aubio.h \ 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 \ diff --git a/src/aubio.h b/src/aubio.h index af786446..c0a1acf2 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -64,19 +64,19 @@ extern "C" { #include "mathutils.h" #include "scale.h" #include "hist.h" -#include "onsetdetection.h" #include "tss.h" #include "resample.h" #include "peakpick.h" #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" diff --git a/src/filterbank.h b/src/filterbank.h index feed08d3..84c5ab6a 100644 --- 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 diff --git a/src/onset.c b/src/onset.c index 172a9e50..26445bd9 100644 --- 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" diff --git a/src/onset/onsetdetection.c b/src/onset/onsetdetection.c new file mode 100644 index 00000000..2e4b1bae --- /dev/null +++ b/src/onset/onsetdetection.c @@ -0,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_ 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;ichannels;i++) { + onset->data[i][0] = 0.; + for (j=0;jlength;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;ichannels;i++) { + onset->data[i][0] = 0.; + for (j=0;jlength;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;ichannels; i++) { + onset->data[i][0] = 0.; + for (j=0;jdev1->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;ichannels; i++) { + onset->data[i][0] = 0.0f; + o->dev1->data[i][0]=0.; + for ( j=0;jdev1->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;ichannels; i++) { + onset->data[i][0] = 0.0f; + for (j=0;jdev1->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;ichannels;i++) { + onset->data[i][0] = 0.; + for (j=0;jlength;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;ichannels;i++) { + onset->data[i][0] = 0.; + for (j=0;jlength;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;ichannels;i++) { + onset->data[i][0] = 0.; + for (j=0;jlength;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; imeas[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); +} diff --git a/src/onset/onsetdetection.h b/src/onset/onsetdetection.h new file mode 100644 index 00000000..ba1c1329 --- /dev/null +++ b/src/onset/onsetdetection.h @@ -0,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 441­444, + 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 881­884, 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 */ diff --git a/src/onsetdetection.c b/src/onsetdetection.c deleted file mode 100644 index b6ca0355..00000000 --- a/src/onsetdetection.c +++ /dev/null @@ -1,337 +0,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_ 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;ichannels;i++) { - onset->data[i][0] = 0.; - for (j=0;jlength;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;ichannels;i++) { - onset->data[i][0] = 0.; - for (j=0;jlength;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;ichannels; i++) { - onset->data[i][0] = 0.; - for (j=0;jdev1->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;ichannels; i++) { - onset->data[i][0] = 0.0f; - o->dev1->data[i][0]=0.; - for ( j=0;jdev1->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;ichannels; i++) { - onset->data[i][0] = 0.0f; - for (j=0;jdev1->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;ichannels;i++) { - onset->data[i][0] = 0.; - for (j=0;jlength;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;ichannels;i++) { - onset->data[i][0] = 0.; - for (j=0;jlength;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;ichannels;i++) { - onset->data[i][0] = 0.; - for (j=0;jlength;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; imeas[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); -} diff --git a/src/onsetdetection.h b/src/onsetdetection.h deleted file mode 100644 index ba1c1329..00000000 --- a/src/onsetdetection.h +++ /dev/null @@ -1,181 +0,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 441­444, - 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 881­884, 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 */ diff --git a/src/pitch/pitchfcomb.c b/src/pitch/pitchfcomb.c new file mode 100644 index 00000000..e894b2bc --- /dev/null +++ b/src/pitch/pitchfcomb.c @@ -0,0 +1,135 @@ +/* + Copyright (C) 2004, 2005 Mario Lang + + 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; klength; 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 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); +} + diff --git a/src/pitch/pitchfcomb.h b/src/pitch/pitchfcomb.h new file mode 100644 index 00000000..1f1974b5 --- /dev/null +++ b/src/pitch/pitchfcomb.h @@ -0,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 */ + + diff --git a/src/pitch/pitchmcomb.c b/src/pitch/pitchmcomb.c new file mode 100644 index 00000000..1d07c6fa --- /dev/null +++ b/src/pitch/pitchmcomb.c @@ -0,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; kncand; 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; kncand; 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;jdata[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;jdata[i][peaks[j].bin]; + /* reset non peaks */ + for (j=count;jpeaks = 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;lene = 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;kecomb[k]=(candidate[l]->ebin)*(k+1.); + for (k=curlen;kecomb[k]=0.; + /* for each in candidate[l]->ecomb[k] */ + for (k=0;kecomb the closer to peaks.ebin + * (to cope with the inharmonicity)*/ + for (d=0;decomb[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;ichannels;i++) + for (j=1;jlength-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;imag - ((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;curene > 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;curebin < 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;incand;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;incand;i++) { + AUBIO_FREE(p->candidates[i]->ecomb); + AUBIO_FREE(p->candidates[i]); + } + AUBIO_FREE(p->candidates); + AUBIO_FREE(p); +} diff --git a/src/pitch/pitchmcomb.h b/src/pitch/pitchmcomb.h new file mode 100644 index 00000000..492c35ec --- /dev/null +++ b/src/pitch/pitchmcomb.h @@ -0,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*/ diff --git a/src/pitch/pitchschmitt.c b/src/pitch/pitchschmitt.c new file mode 100644 index 00000000..ceabd78b --- /dev/null +++ b/src/pitch/pitchschmitt.c @@ -0,0 +1,107 @@ +/* + Copyright (C) 2004, 2005 Mario Lang + + 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; ilength; 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= (sint_t)blockSize) { + sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered; + + schmittPointer = schmittBuffer; + + for (j=0,A1=0,A2=0; j0 && A1=t2 && + schmittBuffer[j+1]< t2) && j= t1); + } else if (schmittBuffer[j]>=t2 && schmittBuffer[j+1] 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); +} + diff --git a/src/pitch/pitchschmitt.h b/src/pitch/pitchschmitt.h new file mode 100644 index 00000000..8a3192e2 --- /dev/null +++ b/src/pitch/pitchschmitt.h @@ -0,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 */ + diff --git a/src/pitch/pitchyin.c b/src/pitch/pitchyin.c new file mode 100644 index 00000000..a77baef2 --- /dev/null +++ b/src/pitch/pitchyin.c @@ -0,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;cchannels;c++) + { + for (tau=0;taulength;tau++) + { + yin->data[c][tau] = 0.; + } + for (tau=1;taulength;tau++) + { + for (j=0;jlength;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;cchannels;c++) + { + tmp = 0.; + yin->data[c][0] = 1.; + //AUBIO_DBG("%f\t",yin->data[c][0]); + for (tau=1;taulength;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 (taulength); + //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;taulength;tau++) + { + yin->data[c][tau] = 0.; + for (j=0;jlength;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; +} + diff --git a/src/pitch/pitchyin.h b/src/pitch/pitchyin.h new file mode 100644 index 00000000..3123b6f3 --- /dev/null +++ b/src/pitch/pitchyin.h @@ -0,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*/ diff --git a/src/pitch/pitchyinfft.c b/src/pitch/pitchyinfft.c new file mode 100644 index 00000000..e81b490c --- /dev/null +++ b/src/pitch/pitchyinfft.c @@ -0,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; iweight->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); +} diff --git a/src/pitch/pitchyinfft.h b/src/pitch/pitchyinfft.h new file mode 100644 index 00000000..cccacd6d --- /dev/null +++ b/src/pitch/pitchyinfft.h @@ -0,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*/ diff --git a/src/pitchdetection.c b/src/pitchdetection.c index 3e2c181f..18cc89bc 100644 --- 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) diff --git a/src/pitchfcomb.c b/src/pitchfcomb.c deleted file mode 100644 index c33b4e75..00000000 --- a/src/pitchfcomb.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright (C) 2004, 2005 Mario Lang - - 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; klength; 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 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); -} - diff --git a/src/pitchfcomb.h b/src/pitchfcomb.h deleted file mode 100644 index 1f1974b5..00000000 --- a/src/pitchfcomb.h +++ /dev/null @@ -1,73 +0,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 */ - - diff --git a/src/pitchmcomb.c b/src/pitchmcomb.c deleted file mode 100644 index 20120025..00000000 --- a/src/pitchmcomb.c +++ /dev/null @@ -1,390 +0,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; kncand; 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; kncand; 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;jdata[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;jdata[i][peaks[j].bin]; - /* reset non peaks */ - for (j=count;jpeaks = 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;lene = 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;kecomb[k]=(candidate[l]->ebin)*(k+1.); - for (k=curlen;kecomb[k]=0.; - /* for each in candidate[l]->ecomb[k] */ - for (k=0;kecomb the closer to peaks.ebin - * (to cope with the inharmonicity)*/ - for (d=0;decomb[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;ichannels;i++) - for (j=1;jlength-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;imag - ((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;curene > 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;curebin < 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;incand;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;incand;i++) { - AUBIO_FREE(p->candidates[i]->ecomb); - AUBIO_FREE(p->candidates[i]); - } - AUBIO_FREE(p->candidates); - AUBIO_FREE(p); -} diff --git a/src/pitchmcomb.h b/src/pitchmcomb.h deleted file mode 100644 index 492c35ec..00000000 --- a/src/pitchmcomb.h +++ /dev/null @@ -1,74 +0,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*/ diff --git a/src/pitchschmitt.c b/src/pitchschmitt.c deleted file mode 100644 index 0e356065..00000000 --- a/src/pitchschmitt.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 2004, 2005 Mario Lang - - 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; ilength; 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= (sint_t)blockSize) { - sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered; - - schmittPointer = schmittBuffer; - - for (j=0,A1=0,A2=0; j0 && A1=t2 && - schmittBuffer[j+1]< t2) && j= t1); - } else if (schmittBuffer[j]>=t2 && schmittBuffer[j+1] 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); -} - diff --git a/src/pitchschmitt.h b/src/pitchschmitt.h deleted file mode 100644 index 8a3192e2..00000000 --- a/src/pitchschmitt.h +++ /dev/null @@ -1,71 +0,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 */ - diff --git a/src/pitchyin.c b/src/pitchyin.c deleted file mode 100644 index 01636079..00000000 --- a/src/pitchyin.c +++ /dev/null @@ -1,115 +0,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;cchannels;c++) - { - for (tau=0;taulength;tau++) - { - yin->data[c][tau] = 0.; - } - for (tau=1;taulength;tau++) - { - for (j=0;jlength;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;cchannels;c++) - { - tmp = 0.; - yin->data[c][0] = 1.; - //AUBIO_DBG("%f\t",yin->data[c][0]); - for (tau=1;taulength;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 (taulength); - //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;taulength;tau++) - { - yin->data[c][tau] = 0.; - for (j=0;jlength;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; -} - diff --git a/src/pitchyin.h b/src/pitchyin.h deleted file mode 100644 index 3123b6f3..00000000 --- a/src/pitchyin.h +++ /dev/null @@ -1,75 +0,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*/ diff --git a/src/pitchyinfft.c b/src/pitchyinfft.c deleted file mode 100644 index 1a59609c..00000000 --- a/src/pitchyinfft.c +++ /dev/null @@ -1,153 +0,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; iweight->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); -} diff --git a/src/pitchyinfft.h b/src/pitchyinfft.h deleted file mode 100644 index cccacd6d..00000000 --- a/src/pitchyinfft.h +++ /dev/null @@ -1,69 +0,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*/ diff --git a/src/tempo.c b/src/tempo.c index 4eb56f26..18d9a549 100644 --- 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"