Add in tree aubio

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2022-05-01 06:57:49 +01:00
parent 0d952f80af
commit 2ae7009b0e
No known key found for this signature in database
GPG key ID: CDBAA37ABC74FBA0
48 changed files with 8937 additions and 1 deletions

530
deps/aubio/src/pitch/pitch.c vendored Normal file
View file

@ -0,0 +1,530 @@
/*
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.h"
#include "cvec.h"
#include "lvec.h"
#include "mathutils.h"
#include "musicutils.h"
#include "spectral/phasevoc.h"
#include "temporal/filter.h"
#include "temporal/c_weighting.h"
#include "pitch/pitchmcomb.h"
#include "pitch/pitchyin.h"
#include "pitch/pitchfcomb.h"
#include "pitch/pitchschmitt.h"
#include "pitch/pitchyinfft.h"
#include "pitch/pitchyinfast.h"
#include "pitch/pitchspecacf.h"
#include "pitch/pitch.h"
#define DEFAULT_PITCH_SILENCE -50.
/** pitch detection algorithms */
typedef enum
{
aubio_pitcht_yin, /**< `yin`, YIN algorithm */
aubio_pitcht_mcomb, /**< `mcomb`, Multi-comb filter */
aubio_pitcht_schmitt, /**< `schmitt`, Schmitt trigger */
aubio_pitcht_fcomb, /**< `fcomb`, Fast comb filter */
aubio_pitcht_yinfft, /**< `yinfft`, Spectral YIN */
aubio_pitcht_yinfast, /**< `yinfast`, YIN fast */
aubio_pitcht_specacf, /**< `specacf`, Spectral autocorrelation */
aubio_pitcht_default
= aubio_pitcht_yinfft, /**< `default` */
} aubio_pitch_type;
/** pitch detection output modes */
typedef enum
{
aubio_pitchm_freq, /**< Frequency (Hz) */
aubio_pitchm_midi, /**< MIDI note (0.,127) */
aubio_pitchm_cent, /**< Cent */
aubio_pitchm_bin, /**< Frequency bin (0,bufsize) */
aubio_pitchm_default = aubio_pitchm_freq, /**< the one used when "default" is asked */
} aubio_pitch_mode;
/** callback to get pitch candidate, defined below */
typedef void (*aubio_pitch_detect_t) (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
/** callback to convert pitch from one unit to another, defined below */
typedef smpl_t(*aubio_pitch_convert_t) (smpl_t value, uint_t samplerate, uint_t bufsize);
/** callback to fetch the confidence of the algorithm */
typedef smpl_t (*aubio_pitch_get_conf_t) (void * p);
/** generic pitch detection structure */
struct _aubio_pitch_t
{
aubio_pitch_type type; /**< pitch detection mode */
aubio_pitch_mode mode; /**< pitch detection output mode */
uint_t samplerate; /**< samplerate */
uint_t bufsize; /**< buffer size */
void *p_object; /**< pointer to pitch object */
aubio_filter_t *filter; /**< filter */
fvec_t *filtered; /**< filtered input */
aubio_pvoc_t *pv; /**< phase vocoder for mcomb */
cvec_t *fftgrain; /**< spectral frame for mcomb */
fvec_t *buf; /**< temporary buffer for yin */
aubio_pitch_detect_t detect_cb; /**< callback to get the pitch candidates */
aubio_pitch_convert_t conv_cb; /**< callback to convert it to the desired unit */
aubio_pitch_get_conf_t conf_cb; /**< pointer to the current confidence callback */
smpl_t silence; /**< silence threshold */
};
/* callback functions for pitch detection */
static void aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
static void aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf);
/* internal functions for frequency conversion */
static smpl_t freqconvbin (smpl_t f, uint_t samplerate, uint_t bufsize);
static smpl_t freqconvmidi (smpl_t f, uint_t samplerate, uint_t bufsize);
static smpl_t freqconvpass (smpl_t f, uint_t samplerate, uint_t bufsize);
/* adapter to stack ibuf new samples at the end of buf, and trim `buf` to `bufsize` */
void aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf);
aubio_pitch_t *
new_aubio_pitch (const char_t * pitch_mode,
uint_t bufsize, uint_t hopsize, uint_t samplerate)
{
aubio_pitch_t *p = AUBIO_NEW (aubio_pitch_t);
aubio_pitch_type pitch_type;
if (pitch_mode == NULL) {
AUBIO_ERR ("pitch: can not use NULL for pitch detection method\n");
goto beach;
}
if (strcmp (pitch_mode, "mcomb") == 0)
pitch_type = aubio_pitcht_mcomb;
else if (strcmp (pitch_mode, "yinfast") == 0)
pitch_type = aubio_pitcht_yinfast;
else if (strcmp (pitch_mode, "yinfft") == 0)
pitch_type = aubio_pitcht_yinfft;
else if (strcmp (pitch_mode, "yin") == 0)
pitch_type = aubio_pitcht_yin;
else if (strcmp (pitch_mode, "schmitt") == 0)
pitch_type = aubio_pitcht_schmitt;
else if (strcmp (pitch_mode, "fcomb") == 0)
pitch_type = aubio_pitcht_fcomb;
else if (strcmp (pitch_mode, "specacf") == 0)
pitch_type = aubio_pitcht_specacf;
else if (strcmp (pitch_mode, "default") == 0)
pitch_type = aubio_pitcht_default;
else {
AUBIO_ERR ("pitch: unknown pitch detection method %s\n", pitch_mode);
goto beach;
}
// check parameters are valid
if ((sint_t)hopsize < 1) {
AUBIO_ERR("pitch: got hopsize %d, but can not be < 1\n", hopsize);
goto beach;
} else if ((sint_t)bufsize < 1) {
AUBIO_ERR("pitch: got buffer_size %d, but can not be < 1\n", bufsize);
goto beach;
} else if (bufsize < hopsize) {
AUBIO_ERR("pitch: hop size (%d) is larger than win size (%d)\n", hopsize, bufsize);
goto beach;
} else if ((sint_t)samplerate < 1) {
AUBIO_ERR("pitch: samplerate (%d) can not be < 1\n", samplerate);
goto beach;
}
p->samplerate = samplerate;
p->type = pitch_type;
aubio_pitch_set_unit (p, "default");
p->bufsize = bufsize;
p->silence = DEFAULT_PITCH_SILENCE;
p->conf_cb = NULL;
switch (p->type) {
case aubio_pitcht_yin:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchyin (bufsize);
if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_yin;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyin_get_confidence;
aubio_pitchyin_set_tolerance (p->p_object, 0.15);
break;
case aubio_pitcht_mcomb:
p->filtered = new_fvec (hopsize);
p->pv = new_aubio_pvoc (bufsize, hopsize);
if (!p->pv) goto beach;
p->fftgrain = new_cvec (bufsize);
p->p_object = new_aubio_pitchmcomb (bufsize, hopsize);
p->filter = new_aubio_filter_c_weighting (samplerate);
p->detect_cb = aubio_pitch_do_mcomb;
break;
case aubio_pitcht_fcomb:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchfcomb (bufsize, hopsize);
if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_fcomb;
break;
case aubio_pitcht_schmitt:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchschmitt (bufsize);
p->detect_cb = aubio_pitch_do_schmitt;
break;
case aubio_pitcht_yinfft:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchyinfft (samplerate, bufsize);
if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_yinfft;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfft_get_confidence;
aubio_pitchyinfft_set_tolerance (p->p_object, 0.85);
break;
case aubio_pitcht_yinfast:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchyinfast (bufsize);
if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_yinfast;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchyinfast_get_confidence;
aubio_pitchyinfast_set_tolerance (p->p_object, 0.15);
break;
case aubio_pitcht_specacf:
p->buf = new_fvec (bufsize);
p->p_object = new_aubio_pitchspecacf (bufsize);
if (!p->p_object) goto beach;
p->detect_cb = aubio_pitch_do_specacf;
p->conf_cb = (aubio_pitch_get_conf_t)aubio_pitchspecacf_get_tolerance;
aubio_pitchspecacf_set_tolerance (p->p_object, 0.85);
break;
default:
break;
}
return p;
beach:
if (p->filtered) del_fvec(p->filtered);
if (p->buf) del_fvec(p->buf);
AUBIO_FREE(p);
return NULL;
}
void
del_aubio_pitch (aubio_pitch_t * p)
{
switch (p->type) {
case aubio_pitcht_yin:
del_fvec (p->buf);
del_aubio_pitchyin (p->p_object);
break;
case aubio_pitcht_mcomb:
del_fvec (p->filtered);
del_aubio_pvoc (p->pv);
del_cvec (p->fftgrain);
del_aubio_filter (p->filter);
del_aubio_pitchmcomb (p->p_object);
break;
case aubio_pitcht_schmitt:
del_fvec (p->buf);
del_aubio_pitchschmitt (p->p_object);
break;
case aubio_pitcht_fcomb:
del_fvec (p->buf);
del_aubio_pitchfcomb (p->p_object);
break;
case aubio_pitcht_yinfft:
del_fvec (p->buf);
del_aubio_pitchyinfft (p->p_object);
break;
case aubio_pitcht_yinfast:
del_fvec (p->buf);
del_aubio_pitchyinfast (p->p_object);
break;
case aubio_pitcht_specacf:
del_fvec (p->buf);
del_aubio_pitchspecacf (p->p_object);
break;
default:
break;
}
AUBIO_FREE (p);
}
void
aubio_pitch_slideblock (aubio_pitch_t * p, const fvec_t * ibuf)
{
uint_t overlap_size = p->buf->length - ibuf->length;
#if 1 //!HAVE_MEMCPY_HACKS
uint_t j;
for (j = 0; j < overlap_size; j++) {
p->buf->data[j] = p->buf->data[j + ibuf->length];
}
for (j = 0; j < ibuf->length; j++) {
p->buf->data[j + overlap_size] = ibuf->data[j];
}
#else
smpl_t *data = p->buf->data;
smpl_t *newdata = ibuf->data;
memmove(data, data + ibuf->length, overlap_size);
memcpy(data + overlap_size, newdata, ibuf->length);
#endif
}
uint_t
aubio_pitch_set_unit (aubio_pitch_t * p, const char_t * pitch_unit)
{
uint_t err = AUBIO_OK;
aubio_pitch_mode pitch_mode;
if (strcmp (pitch_unit, "freq") == 0)
pitch_mode = aubio_pitchm_freq;
else if (strcmp (pitch_unit, "hertz") == 0)
pitch_mode = aubio_pitchm_freq;
else if (strcmp (pitch_unit, "Hertz") == 0)
pitch_mode = aubio_pitchm_freq;
else if (strcmp (pitch_unit, "Hz") == 0)
pitch_mode = aubio_pitchm_freq;
else if (strcmp (pitch_unit, "f0") == 0)
pitch_mode = aubio_pitchm_freq;
else if (strcmp (pitch_unit, "midi") == 0)
pitch_mode = aubio_pitchm_midi;
else if (strcmp (pitch_unit, "cent") == 0)
pitch_mode = aubio_pitchm_cent;
else if (strcmp (pitch_unit, "bin") == 0)
pitch_mode = aubio_pitchm_bin;
else if (strcmp (pitch_unit, "default") == 0)
pitch_mode = aubio_pitchm_default;
else {
AUBIO_WRN("pitch: unknown pitch detection unit %s, using default\n",
pitch_unit);
pitch_mode = aubio_pitchm_default;
err = AUBIO_FAIL;
}
p->mode = pitch_mode;
switch (p->mode) {
case aubio_pitchm_freq:
p->conv_cb = freqconvpass;
break;
case aubio_pitchm_midi:
p->conv_cb = freqconvmidi;
break;
case aubio_pitchm_cent:
/* bug: not implemented */
p->conv_cb = freqconvmidi;
break;
case aubio_pitchm_bin:
p->conv_cb = freqconvbin;
break;
default:
break;
}
return err;
}
uint_t
aubio_pitch_set_tolerance (aubio_pitch_t * p, smpl_t tol)
{
switch (p->type) {
case aubio_pitcht_yin:
aubio_pitchyin_set_tolerance (p->p_object, tol);
break;
case aubio_pitcht_yinfft:
aubio_pitchyinfft_set_tolerance (p->p_object, tol);
break;
case aubio_pitcht_yinfast:
aubio_pitchyinfast_set_tolerance (p->p_object, tol);
break;
default:
break;
}
return AUBIO_OK;
}
smpl_t
aubio_pitch_get_tolerance (aubio_pitch_t * p)
{
smpl_t tolerance = 1.;
switch (p->type) {
case aubio_pitcht_yin:
tolerance = aubio_pitchyin_get_tolerance (p->p_object);
break;
case aubio_pitcht_yinfft:
tolerance = aubio_pitchyinfft_get_tolerance (p->p_object);
break;
case aubio_pitcht_yinfast:
tolerance = aubio_pitchyinfast_get_tolerance (p->p_object);
break;
default:
break;
}
return tolerance;
}
uint_t
aubio_pitch_set_silence (aubio_pitch_t * p, smpl_t silence)
{
if (silence <= 0 && silence >= -200) {
p->silence = silence;
return AUBIO_OK;
} else {
AUBIO_WRN("pitch: could not set silence to %.2f\n", silence);
return AUBIO_FAIL;
}
}
smpl_t
aubio_pitch_get_silence (aubio_pitch_t * p)
{
return p->silence;
}
/* do method, calling the detection callback, then the conversion callback */
void
aubio_pitch_do (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
p->detect_cb (p, ibuf, obuf);
if (aubio_silence_detection(ibuf, p->silence) == 1) {
obuf->data[0] = 0.;
}
obuf->data[0] = p->conv_cb (obuf->data[0], p->samplerate, p->bufsize);
}
/* do method for each algorithm */
void
aubio_pitch_do_mcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
aubio_filter_do_outplace (p->filter, ibuf, p->filtered);
aubio_pvoc_do (p->pv, ibuf, p->fftgrain);
aubio_pitchmcomb_do (p->p_object, p->fftgrain, obuf);
obuf->data[0] = aubio_bintofreq (obuf->data[0], p->samplerate, p->bufsize);
}
void
aubio_pitch_do_yin (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
smpl_t pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
aubio_pitchyin_do (p->p_object, p->buf, obuf);
pitch = obuf->data[0];
if (pitch > 0) {
pitch = p->samplerate / (pitch + 0.);
} else {
pitch = 0.;
}
obuf->data[0] = pitch;
}
void
aubio_pitch_do_yinfft (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
smpl_t pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
aubio_pitchyinfft_do (p->p_object, p->buf, obuf);
pitch = obuf->data[0];
if (pitch > 0) {
pitch = p->samplerate / (pitch + 0.);
} else {
pitch = 0.;
}
obuf->data[0] = pitch;
}
void
aubio_pitch_do_yinfast (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * obuf)
{
smpl_t pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
aubio_pitchyinfast_do (p->p_object, p->buf, obuf);
pitch = obuf->data[0];
if (pitch > 0) {
pitch = p->samplerate / (pitch + 0.);
} else {
pitch = 0.;
}
obuf->data[0] = pitch;
}
void
aubio_pitch_do_specacf (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
smpl_t pitch = 0., period;
aubio_pitch_slideblock (p, ibuf);
aubio_pitchspecacf_do (p->p_object, p->buf, out);
//out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize);
period = out->data[0];
if (period > 0) {
pitch = p->samplerate / period;
} else {
pitch = 0.;
}
out->data[0] = pitch;
}
void
aubio_pitch_do_fcomb (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
aubio_pitch_slideblock (p, ibuf);
aubio_pitchfcomb_do (p->p_object, p->buf, out);
out->data[0] = aubio_bintofreq (out->data[0], p->samplerate, p->bufsize);
}
void
aubio_pitch_do_schmitt (aubio_pitch_t * p, const fvec_t * ibuf, fvec_t * out)
{
smpl_t period, pitch = 0.;
aubio_pitch_slideblock (p, ibuf);
aubio_pitchschmitt_do (p->p_object, p->buf, out);
period = out->data[0];
if (period > 0) {
pitch = p->samplerate / period;
} else {
pitch = 0.;
}
out->data[0] = pitch;
}
/* conversion callbacks */
smpl_t
freqconvbin(smpl_t f, uint_t samplerate, uint_t bufsize)
{
return aubio_freqtobin(f, samplerate, bufsize);
}
smpl_t
freqconvmidi (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED)
{
return aubio_freqtomidi (f);
}
smpl_t
freqconvpass (smpl_t f, uint_t samplerate UNUSED, uint_t bufsize UNUSED)
{
return f;
}
/* confidence callbacks */
smpl_t
aubio_pitch_get_confidence (aubio_pitch_t * p)
{
if (p->conf_cb) {
return p->conf_cb(p->p_object);
}
return 0.;
}

197
deps/aubio/src/pitch/pitch.h vendored Normal file
View file

@ -0,0 +1,197 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUBIO_PITCH_H
#define AUBIO_PITCH_H
#ifdef __cplusplus
extern "C" {
#endif
/** \file
Pitch detection object
This file creates the objects required for the computation of the selected
pitch detection algorithm and output the results, in midi note or Hz.
\section pitch Pitch detection methods
A list of the pitch detection methods currently available follows.
\b \p default : use the default method
Currently, the default method is set to \p yinfft .
\b \p schmitt : 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
\b \p fcomb : 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
\b \p mcomb : 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.
\b \p yin : YIN algorithm
This algorithm was developed 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
\b \p yinfast : Yinfast algorithm
This algorithm is equivalent to the YIN algorithm, but computed in the
spectral domain for efficiency. See also `python/demos/demo_yin_compare.py`.
\b \p yinfft : Yinfft algorithm
This algorithm was derived from the YIN algorithm. 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](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis,
Centre for Digital music, Queen Mary University of London, London, UK, 2006.
\example pitch/test-pitch.c
\example examples/aubiopitch.c
*/
/** pitch detection object */
typedef struct _aubio_pitch_t aubio_pitch_t;
/** execute pitch detection on an input signal frame
\param o pitch detection object as returned by new_aubio_pitch()
\param in input signal of size [hop_size]
\param out output pitch candidates of size [1]
*/
void aubio_pitch_do (aubio_pitch_t * o, const fvec_t * in, fvec_t * out);
/** change yin or yinfft tolerance threshold
\param o pitch detection object as returned by new_aubio_pitch()
\param tol tolerance default is 0.15 for yin and 0.85 for yinfft
*/
uint_t aubio_pitch_set_tolerance (aubio_pitch_t * o, smpl_t tol);
/** get yin or yinfft tolerance threshold
\param o pitch detection object as returned by new_aubio_pitch()
\return tolerance (default is 0.15 for yin and 0.85 for yinfft)
*/
smpl_t aubio_pitch_get_tolerance (aubio_pitch_t * o);
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitch()
*/
void del_aubio_pitch (aubio_pitch_t * o);
/** creation of the pitch detection object
\param method set pitch detection algorithm
\param buf_size size of the input buffer to analyse
\param hop_size step size between two consecutive analysis instant
\param samplerate sampling rate of the signal
\return newly created ::aubio_pitch_t
*/
aubio_pitch_t *new_aubio_pitch (const char_t * method,
uint_t buf_size, uint_t hop_size, uint_t samplerate);
/** set the output unit of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitch()
\param mode set pitch units for output
mode can be one of "Hz", "midi", "cent", or "bin". Defaults to "Hz".
\return 0 if successfull, non-zero otherwise
*/
uint_t aubio_pitch_set_unit (aubio_pitch_t * o, const char_t * mode);
/** set the silence threshold of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitch()
\param silence level threshold under which pitch should be ignored, in dB
\return 0 if successfull, non-zero otherwise
*/
uint_t aubio_pitch_set_silence (aubio_pitch_t * o, smpl_t silence);
/** set the silence threshold of the pitch detection object
\param o pitch detection object as returned by ::new_aubio_pitch()
\return level threshold under which pitch should be ignored, in dB
*/
smpl_t aubio_pitch_get_silence (aubio_pitch_t * o);
/** get the current confidence
\param o pitch detection object as returned by new_aubio_pitch()
\return the current confidence of the pitch algorithm
*/
smpl_t aubio_pitch_get_confidence (aubio_pitch_t * o);
#ifdef __cplusplus
}
#endif
#endif /* AUBIO_PITCH_H */

144
deps/aubio/src/pitch/pitchfcomb.c vendored Normal file
View file

@ -0,0 +1,144 @@
/*
Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.h"
#include "cvec.h"
#include "mathutils.h"
#include "musicutils.h"
#include "spectral/fft.h"
#include "pitch/pitchfcomb.h"
#define MAX_PEAKS 8
typedef struct
{
smpl_t bin;
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_pitchfcomb_t *
new_aubio_pitchfcomb (uint_t bufsize, uint_t hopsize)
{
aubio_pitchfcomb_t *p = AUBIO_NEW (aubio_pitchfcomb_t);
p->fftSize = bufsize;
p->stepSize = hopsize;
p->fft = new_aubio_fft (bufsize);
if (!p->fft) goto beach;
p->winput = new_fvec (bufsize);
p->fftOut = new_cvec (bufsize);
p->fftLastPhase = new_fvec (bufsize);
p->win = new_aubio_window ("hanning", bufsize);
return p;
beach:
AUBIO_FREE(p);
return NULL;
}
/* input must be stepsize long */
void
aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input, fvec_t * output)
{
uint_t k, l, maxharm = 0;
smpl_t phaseDifference = TWO_PI * (smpl_t) p->stepSize / (smpl_t) p->fftSize;
aubio_fpeak_t peaks[MAX_PEAKS];
for (k = 0; k < MAX_PEAKS; k++) {
peaks[k].db = -200.;
peaks[k].bin = 0.;
}
for (k = 0; k < input->length; k++) {
p->winput->data[k] = p->win->data[k] * input->data[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[k] / (smpl_t) p->fftSize),
phase = p->fftOut->phas[k], tmp, bin;
/* compute phase difference */
tmp = phase - p->fftLastPhase->data[k];
p->fftLastPhase->data[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 bin */
bin = (smpl_t) k + tmp;
if (bin > 0.0 && magnitude > peaks[0].db) { // && magnitude < 0) {
memmove (peaks + 1, peaks, sizeof (aubio_fpeak_t) * (MAX_PEAKS - 1));
peaks[0].bin = bin;
peaks[0].db = magnitude;
}
}
k = 0;
for (l = 1; l < MAX_PEAKS && peaks[l].bin > 0.0; l++) {
sint_t harmonic;
for (harmonic = 5; harmonic > 1; harmonic--) {
if (peaks[0].bin / peaks[l].bin < harmonic + .02 &&
peaks[0].bin / peaks[l].bin > harmonic - .02) {
if (harmonic > (sint_t) maxharm && peaks[0].db < peaks[l].db / 2) {
maxharm = harmonic;
k = l;
}
}
}
}
output->data[0] = peaks[k].bin;
/* quick hack to clean output a bit */
if (peaks[k].bin > 5000.)
output->data[0] = 0.;
}
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);
}

76
deps/aubio/src/pitch/pitchfcomb.h vendored Normal file
View file

@ -0,0 +1,76 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
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
\example pitch/test-pitchfcomb.c
*/
#ifndef AUBIO_PITCHFCOMB_H
#define AUBIO_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)
\param output pitch candidates in bins
*/
void aubio_pitchfcomb_do (aubio_pitchfcomb_t * p, const fvec_t * input,
fvec_t * output);
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
\param hop_size step size between two consecutive analysis instant
*/
aubio_pitchfcomb_t *new_aubio_pitchfcomb (uint_t buf_size, uint_t hop_size);
/** 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 /* AUBIO_PITCHFCOMB_H */

435
deps/aubio/src/pitch/pitchmcomb.c vendored Normal file
View file

@ -0,0 +1,435 @@
/*
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.h"
#include "cvec.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,
const fvec_t * X);
void aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * oldmag);
void aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag);
/* not used but useful : sort by amplitudes (or anything else)
* sort_pitchpeak(peaks, length);
*/
#if 0
/** 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);
/** select the best candidates */
uint_t aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain,
smpl_t * cands);
#endif
/** sort spectral_candidate against their comb ene */
void aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,
uint_t nbins);
#if 0
/** sort spectral_candidate against their frequency */
void aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
uint_t nbins);
#endif
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 */
};
void
aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, fvec_t * output)
{
uint_t 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[j] = fftgrain->norm[j];
/* detect only if local energy > 10. */
//if (aubio_level_lin (newmag) * newmag->length > 10.) {
//hfc = fvec_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[j]
- p->theta->data[j] - j * p->phasediff);
instfreq *= p->phasefreq;
/* store phase for next run */
for (j = 0; j < p->theta->length; j++) {
p->theta->data[j] = fftgrain->phas[j];
}
//return p->candidates[p->goodcandidate]->ebin;
output->data[0] =
FLOOR (p->candidates[p->goodcandidate]->ebin + .5) + instfreq;
/*} else {
return -1.;
} */
}
#if 0
uint_t
aubio_pitch_cands (aubio_pitchmcomb_t * p, const cvec_t * fftgrain, smpl_t * cands)
{
uint_t 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[j] = fftgrain->norm[j];
/* detect only if local energy > 10. */
if (aubio_level_lin (newmag) * newmag->length > 10.) {
/* hfc = fvec_local_hfc(newmag); do not use */
aubio_pitchmcomb_spectral_pp (p, newmag);
aubio_pitchmcomb_combdet (p, newmag);
aubio_pitchmcomb_sort_cand_freq (scands, p->ncand);
/* store ncand comb energies in cands[1:ncand] */
for (k = 0; k < p->ncand; k++)
cands[k] = p->candidates[k]->ene;
/* store ncand[end] freq in cands[end] */
cands[p->ncand] = p->candidates[p->ncand - 1]->ebin;
return 1;
} else {
for (k = 0; k < p->ncand; k++)
cands[k] = 0;
return 0;
}
}
#endif
void
aubio_pitchmcomb_spectral_pp (aubio_pitchmcomb_t * p, const fvec_t * newmag)
{
fvec_t *mag = (fvec_t *) p->scratch;
fvec_t *tmp = (fvec_t *) p->scratch2;
uint_t j;
uint_t length = mag->length;
/* copy newmag to mag (scracth) */
for (j = 0; j < length; j++) {
mag->data[j] = newmag->data[j];
}
fvec_min_removal (mag); /* min removal */
fvec_alpha_normalise (mag, p->alpha); /* alpha normalisation */
/* skipped *//* low pass filtering */
/** \bug fvec_moving_thres may write out of bounds */
fvec_adapt_thres (mag, tmp, p->win_post, p->win_pre); /* adaptative threshold */
fvec_add (mag, -p->threshold); /* fixed threshold */
{
aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks;
uint_t count;
/* return bin and ebin */
count = aubio_pitchmcomb_quadpick (peaks, mag);
for (j = 0; j < count; j++)
peaks[j].mag = newmag->data[peaks[j].bin];
/* reset non peaks */
for (j = count; j < length; j++)
peaks[j].mag = 0.;
p->peaks = peaks;
p->count = count;
}
}
void
aubio_pitchmcomb_combdet (aubio_pitchmcomb_t * p, const fvec_t * newmag)
{
aubio_spectralpeak_t *peaks = (aubio_spectralpeak_t *) p->peaks;
aubio_spectralcandidate_t **candidate =
(aubio_spectralcandidate_t **) p->candidates;
/* parms */
uint_t N = p->npartials; /* maximum number of partials to be considered 10 */
uint_t M = p->ncand; /* maximum number of combs to be considered 5 */
uint_t length = newmag->length;
uint_t count = p->count;
uint_t k;
uint_t l;
uint_t d;
uint_t curlen = 0;
smpl_t delta2;
smpl_t xx;
uint_t position = 0;
uint_t root_peak = 0;
uint_t tmpl = 0;
smpl_t tmpene = 0.;
/* get the biggest peak in the spectrum */
root_peak = aubio_pitchmcomb_get_root_peak (peaks, count);
/* not enough partials in highest notes, could be forced */
//if (peaks[root_peak].ebin >= aubio_miditofreq(85.)/p->tau) N=2;
//if (peaks[root_peak].ebin >= aubio_miditofreq(90.)/p->tau) N=1;
/* now calculate the energy of each of the 5 combs */
for (l = 0; l < M; l++) {
smpl_t scaler = (1. / (l + 1.));
candidate[l]->ene = 0.; /* reset ene and len sums */
candidate[l]->len = 0.;
candidate[l]->ebin = scaler * peaks[root_peak].ebin;
/* if less than N peaks available, curlen < N */
if (candidate[l]->ebin != 0.)
curlen = (uint_t) FLOOR (length / (candidate[l]->ebin));
curlen = (N < curlen) ? N : curlen;
/* fill candidate[l]->ecomb[k] with (k+1)*candidate[l]->ebin */
for (k = 0; k < curlen; k++)
candidate[l]->ecomb[k] = (candidate[l]->ebin) * (k + 1.);
for (k = curlen; k < length; k++)
candidate[l]->ecomb[k] = 0.;
/* for each in candidate[l]->ecomb[k] */
for (k = 0; k < curlen; k++) {
xx = 100000.;
/** get the candidate->ecomb the closer to peaks.ebin
* (to cope with the inharmonicity)*/
for (d = 0; d < count; d++) {
delta2 = ABS (candidate[l]->ecomb[k] - peaks[d].ebin);
if (delta2 <= xx) {
position = d;
xx = delta2;
}
}
/* for a Q factor of 17, maintaining "constant Q filtering",
* and sum energy and length over non null combs */
if (17. * xx < candidate[l]->ecomb[k]) {
candidate[l]->ecomb[k] = peaks[position].ebin;
candidate[l]->ene += /* ecomb rounded to nearest int */
POW (newmag->data[(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, const fvec_t * X)
{
uint_t j, ispeak, count = 0;
for (j = 1; j < X->length - 1; j++) {
ispeak = fvec_peakpick (X, j);
if (ispeak) {
count += ispeak;
spectral_peaks[count - 1].bin = j;
spectral_peaks[count - 1].ebin = fvec_quadratic_peak_pos (X, j);
}
}
return count;
}
/* get predominant partial */
uint_t
aubio_pitchmcomb_get_root_peak (aubio_spectralpeak_t * peaks, uint_t length)
{
uint_t i, pos = 0;
smpl_t tmp = 0.;
for (i = 0; i < length; i++)
if (tmp <= peaks[i].mag) {
pos = i;
tmp = peaks[i].mag;
}
return pos;
}
#if 0
void
aubio_pitchmcomb_sort_peak (aubio_spectralpeak_t * peaks, uint_t nbins)
{
qsort (peaks, nbins, sizeof (aubio_spectralpeak_t),
aubio_pitchmcomb_sort_peak_comp);
}
static sint_t
aubio_pitchmcomb_sort_peak_comp (const void *x, const void *y)
{
return (((aubio_spectralpeak_t *) y)->mag -
((aubio_spectralpeak_t *) x)->mag);
}
void
aubio_pitchmcomb_sort_cand_ene (aubio_spectralcandidate_t ** candidates,
uint_t nbins)
{
uint_t cur = 0;
uint_t run = 0;
for (cur = 0; cur < nbins; cur++) {
for (run = cur + 1; run < nbins; run++) {
if (candidates[run]->ene > candidates[cur]->ene)
CAND_SWAP (candidates[run], candidates[cur]);
}
}
}
void
aubio_pitchmcomb_sort_cand_freq (aubio_spectralcandidate_t ** candidates,
uint_t nbins)
{
uint_t cur = 0;
uint_t run = 0;
for (cur = 0; cur < nbins; cur++) {
for (run = cur + 1; run < nbins; run++) {
if (candidates[run]->ebin < candidates[cur]->ebin)
CAND_SWAP (candidates[run], candidates[cur]);
}
}
}
#endif
aubio_pitchmcomb_t *
new_aubio_pitchmcomb (uint_t bufsize, uint_t hopsize)
{
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 = 2;
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 + 1;
//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);
/* array for median */
p->scratch = new_fvec (spec_size);
/* array for phase */
p->theta = new_fvec (spec_size);
/* array for adaptative threshold */
p->scratch2 = new_fvec (p->win_post + p->win_pre + 1);
/* array of spectral peaks */
p->peaks = AUBIO_ARRAY (aubio_spectralpeak_t, spec_size);
for (i = 0; i < spec_size; i++) {
p->peaks[i].bin = 0.;
p->peaks[i].ebin = 0.;
p->peaks[i].mag = 0.;
}
/* array of pointers to spectral candidates */
p->candidates = AUBIO_ARRAY (aubio_spectralcandidate_t *, p->ncand);
for (i = 0; i < p->ncand; i++) {
p->candidates[i] = AUBIO_NEW (aubio_spectralcandidate_t);
p->candidates[i]->ecomb = AUBIO_ARRAY (smpl_t, spec_size);
for (j = 0; j < spec_size; j++) {
p->candidates[i]->ecomb[j] = 0.;
}
p->candidates[i]->ene = 0.;
p->candidates[i]->ebin = 0.;
p->candidates[i]->len = 0.;
}
return p;
}
void
del_aubio_pitchmcomb (aubio_pitchmcomb_t * p)
{
uint_t i;
del_fvec (p->newmag);
del_fvec (p->scratch);
del_fvec (p->theta);
del_fvec (p->scratch2);
AUBIO_FREE (p->peaks);
for (i = 0; i < p->ncand; i++) {
AUBIO_FREE (p->candidates[i]->ecomb);
AUBIO_FREE (p->candidates[i]);
}
AUBIO_FREE (p->candidates);
AUBIO_FREE (p);
}

77
deps/aubio/src/pitch/pitchmcomb.h vendored Normal file
View file

@ -0,0 +1,77 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
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.
\example pitch/test-pitchmcomb.c
*/
#ifndef AUBIO_PITCHMCOMB_H
#define AUBIO_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 in_fftgrain input signal spectrum as computed by aubio_pvoc_do
\param out_cands pitch candidate frequenciess, in bins
*/
void aubio_pitchmcomb_do (aubio_pitchmcomb_t * p, const cvec_t * in_fftgrain,
fvec_t * out_cands);
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
\param hop_size step size between two consecutive analysis instant
*/
aubio_pitchmcomb_t *new_aubio_pitchmcomb (uint_t buf_size, uint_t hop_size);
/** 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 /* AUBIO_PITCHMCOMB_H */

119
deps/aubio/src/pitch/pitchschmitt.c vendored Normal file
View file

@ -0,0 +1,119 @@
/*
Copyright (C) 2004, 2005 Mario Lang <mlang@delysid.org>
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.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;
signed short int *buf;
};
aubio_pitchschmitt_t *
new_aubio_pitchschmitt (uint_t size)
{
aubio_pitchschmitt_t *p = AUBIO_NEW (aubio_pitchschmitt_t);
p->blockSize = size;
p->schmittBuffer = AUBIO_ARRAY (signed short int, p->blockSize);
p->buf = AUBIO_ARRAY (signed short int, p->blockSize);
p->schmittPointer = p->schmittBuffer;
return p;
}
void
aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * input,
fvec_t * output)
{
uint_t j;
for (j = 0; j < input->length; j++) {
p->buf[j] = input->data[j] * 32768.;
}
output->data[0] = aubio_schmittS16LE (p, input->length, p->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 period = 0., trigfact = 0.6;
for (i = 0; i < nframes; i++) {
*schmittPointer++ = indata[i];
if (schmittPointer - schmittBuffer >= (sint_t) blockSize) {
sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered;
schmittPointer = schmittBuffer;
for (j = 0, A1 = 0, A2 = 0; j < blockSize; j++) {
if (schmittBuffer[j] > 0 && A1 < schmittBuffer[j])
A1 = schmittBuffer[j];
if (schmittBuffer[j] < 0 && A2 < -schmittBuffer[j])
A2 = -schmittBuffer[j];
}
t1 = (sint_t) (A1 * trigfact + 0.5);
t2 = -(sint_t) (A2 * trigfact + 0.5);
startpoint = 0;
for (j = 1; j < blockSize && schmittBuffer[j] <= t1; j++);
for ( ; j < blockSize - 1 && !(schmittBuffer[j] >= t2 &&
schmittBuffer[j + 1] < t2); j++);
startpoint = j;
schmittTriggered = 0;
endpoint = startpoint + 1;
for (j = startpoint, tc = 0; j < blockSize; j++) {
if (!schmittTriggered) {
schmittTriggered = (schmittBuffer[j] >= t1);
} else if (schmittBuffer[j] >= t2 && schmittBuffer[j + 1] < t2) {
endpoint = j;
tc++;
schmittTriggered = 0;
}
}
if ((endpoint > startpoint) && (tc > 0)) {
period = (smpl_t) (endpoint - startpoint) / tc;
}
}
}
p->schmittBuffer = schmittBuffer;
p->schmittPointer = schmittPointer;
return period;
}
void
del_aubio_pitchschmitt (aubio_pitchschmitt_t * p)
{
AUBIO_FREE (p->schmittBuffer);
AUBIO_FREE (p->buf);
AUBIO_FREE (p);
}

75
deps/aubio/src/pitch/pitchschmitt.h vendored Normal file
View file

@ -0,0 +1,75 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
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
\example pitch/test-pitchschmitt.c
*/
#ifndef AUBIO_PITCHSCHMITT_H
#define AUBIO_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 samples_in input signal vector (length as specified at creation time)
\param cands_out pitch period estimates, in samples
*/
void aubio_pitchschmitt_do (aubio_pitchschmitt_t * p, const fvec_t * samples_in,
fvec_t * cands_out);
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
*/
aubio_pitchschmitt_t *new_aubio_pitchschmitt (uint_t buf_size);
/** 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 /* AUBIO_PITCHSCHMITT_H */

116
deps/aubio/src/pitch/pitchspecacf.c vendored Normal file
View file

@ -0,0 +1,116 @@
/*
Copyright (C) 2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.h"
#include "cvec.h"
#include "mathutils.h"
#include "spectral/fft.h"
#include "pitch/pitchspecacf.h"
/** pitch specacf structure */
struct _aubio_pitchspecacf_t
{
fvec_t *win; /**< temporal weighting window */
fvec_t *winput; /**< windowed spectrum */
aubio_fft_t *fft; /**< fft object to compute*/
fvec_t *fftout; /**< Fourier transform output */
fvec_t *sqrmag; /**< square magnitudes */
fvec_t *acf; /**< auto correlation function */
smpl_t tol; /**< tolerance */
smpl_t confidence; /**< confidence */
};
aubio_pitchspecacf_t *
new_aubio_pitchspecacf (uint_t bufsize)
{
aubio_pitchspecacf_t *p = AUBIO_NEW (aubio_pitchspecacf_t);
p->fft = new_aubio_fft (bufsize);
if (!p->fft) goto beach;
p->win = new_aubio_window ("hanningz", bufsize);
p->winput = new_fvec (bufsize);
p->fftout = new_fvec (bufsize);
p->sqrmag = new_fvec (bufsize);
p->acf = new_fvec (bufsize / 2 + 1);
p->tol = 1.;
p->confidence = 0.;
return p;
beach:
AUBIO_FREE(p);
return NULL;
}
void
aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, const fvec_t * input, fvec_t * output)
{
uint_t l, tau;
fvec_t *fftout = p->fftout;
// window the input
for (l = 0; l < input->length; l++) {
p->winput->data[l] = p->win->data[l] * input->data[l];
}
// get the real / imag parts of its fft
aubio_fft_do_complex (p->fft, p->winput, fftout);
for (l = 0; l < input->length / 2 + 1; l++) {
p->sqrmag->data[l] = SQR(fftout->data[l]);
}
// get the real / imag parts of the fft of the squared magnitude
aubio_fft_do_complex (p->fft, p->sqrmag, fftout);
// copy real part to acf
for (l = 0; l < fftout->length / 2 + 1; l++) {
p->acf->data[l] = fftout->data[l];
}
// get the minimum
tau = fvec_min_elem (p->acf);
// get the interpolated minimum
output->data[0] = fvec_quadratic_peak_pos (p->acf, tau) * 2.;
}
void
del_aubio_pitchspecacf (aubio_pitchspecacf_t * p)
{
del_fvec (p->win);
del_fvec (p->winput);
del_aubio_fft (p->fft);
del_fvec (p->sqrmag);
del_fvec (p->fftout);
del_fvec (p->acf);
AUBIO_FREE (p);
}
smpl_t
aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o) {
// no confidence for now
return o->confidence;
}
uint_t
aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * p, smpl_t tol)
{
p->tol = tol;
return 0;
}
smpl_t
aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * p)
{
return p->tol;
}

103
deps/aubio/src/pitch/pitchspecacf.h vendored Normal file
View file

@ -0,0 +1,103 @@
/*
Copyright (C) 2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
Pitch detection using spectral auto correlation
This algorithm implements pitch detection by computing the autocorrelation
function as the cosine transform of the square spectral magnitudes.
Anssi Klapuri. Qualitative and quantitative aspects in the design of
periodicity esti- mation algorithms. In Proceedings of the European Signal
Processing Conference (EUSIPCO), 2000.
Paul Brossier, [Automatic annotation of musical audio for interactive
systems](http://aubio.org/phd/), Chapter 3, Pitch Analysis, Autocorrelation,
pp. 75-77, PhD thesis, Centre for Digital music, Queen Mary University of
London, London, UK, 2006.
\example pitch/test-pitchspecacf.c
*/
#ifndef AUBIO_PITCHSPECACF_H
#define AUBIO_PITCHSPECACF_H
#ifdef __cplusplus
extern "C" {
#endif
/** pitch detection object */
typedef struct _aubio_pitchspecacf_t aubio_pitchspecacf_t;
/** execute pitch detection on an input buffer
\param o pitch detection object as returned by new_aubio_pitchspecacf
\param samples_in input signal vector (length as specified at creation time)
\param cands_out pitch period candidates, in samples
*/
void aubio_pitchspecacf_do (aubio_pitchspecacf_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
*/
aubio_pitchspecacf_t *new_aubio_pitchspecacf (uint_t buf_size);
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitchspecacf()
*/
void del_aubio_pitchspecacf (aubio_pitchspecacf_t * o);
/** get tolerance parameter for `specacf` pitch detection object
\param o pitch detection object
\return tolerance parameter for minima selection [default 1.]
*/
smpl_t aubio_pitchspecacf_get_tolerance (const aubio_pitchspecacf_t * o);
/** set tolerance parameter for `specacf` pitch detection object
\param o pitch detection object
\param tol tolerance parameter for minima selection [default 1.]
\return `1` on error, `0` on success
*/
uint_t aubio_pitchspecacf_set_tolerance (aubio_pitchspecacf_t * o, smpl_t tol);
/** get currenct confidence for `specacf` pitch detection object
\param o pitch detection object
\return confidence parameter
*/
smpl_t aubio_pitchspecacf_get_confidence (const aubio_pitchspecacf_t * o);
#ifdef __cplusplus
}
#endif
#endif /* AUBIO_PITCHSPECACF_H */

189
deps/aubio/src/pitch/pitchyin.c vendored Normal file
View file

@ -0,0 +1,189 @@
/*
Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/* This algorithm was developed by A. de Cheveigné 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 "fvec.h"
#include "mathutils.h"
#include "pitch/pitchyin.h"
struct _aubio_pitchyin_t
{
fvec_t *yin;
smpl_t tol;
uint_t peak_pos;
};
#if 0
/** 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 (const fvec_t * yinbuf);
#endif
aubio_pitchyin_t *
new_aubio_pitchyin (uint_t bufsize)
{
aubio_pitchyin_t *o = AUBIO_NEW (aubio_pitchyin_t);
o->yin = new_fvec (bufsize / 2);
o->tol = 0.15;
o->peak_pos = 0;
return o;
}
void
del_aubio_pitchyin (aubio_pitchyin_t * o)
{
del_fvec (o->yin);
AUBIO_FREE (o);
}
#if 0
/* outputs the difference function */
void
aubio_pitchyin_diff (fvec_t * input, fvec_t * yin)
{
uint_t j, tau;
smpl_t tmp;
for (tau = 0; tau < yin->length; tau++) {
yin->data[tau] = 0.;
}
for (tau = 1; tau < yin->length; tau++) {
for (j = 0; j < yin->length; j++) {
tmp = input->data[j] - input->data[j + tau];
yin->data[tau] += SQR (tmp);
}
}
}
/* cumulative mean normalized difference function */
void
aubio_pitchyin_getcum (fvec_t * yin)
{
uint_t tau;
smpl_t tmp = 0.;
yin->data[0] = 1.;
//AUBIO_DBG("%f\t",yin->data[0]);
for (tau = 1; tau < yin->length; tau++) {
tmp += yin->data[tau];
yin->data[tau] *= tau / tmp;
//AUBIO_DBG("%f\t",yin->data[tau]);
}
//AUBIO_DBG("\n");
}
uint_t
aubio_pitchyin_getpitch (const fvec_t * yin)
{
uint_t tau = 1;
do {
if (yin->data[tau] < 0.1) {
while (yin->data[tau + 1] < yin->data[tau]) {
tau++;
}
return tau;
}
tau++;
} while (tau < yin->length);
//AUBIO_DBG("No pitch found");
return 0;
}
#endif
/* all the above in one */
void
aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * input, fvec_t * out)
{
const smpl_t tol = o->tol;
fvec_t* yin = o->yin;
const smpl_t *input_data = input->data;
const uint_t length = yin->length;
smpl_t *yin_data = yin->data;
uint_t j, tau;
sint_t period;
smpl_t tmp, tmp2 = 0.;
yin_data[0] = 1.;
for (tau = 1; tau < length; tau++) {
yin_data[tau] = 0.;
for (j = 0; j < length; j++) {
tmp = input_data[j] - input_data[j + tau];
yin_data[tau] += SQR (tmp);
}
tmp2 += yin_data[tau];
if (tmp2 != 0) {
yin->data[tau] *= tau / tmp2;
} else {
yin->data[tau] = 1.;
}
period = tau - 3;
if (tau > 4 && (yin_data[period] < tol) &&
(yin_data[period] < yin_data[period + 1])) {
o->peak_pos = (uint_t)period;
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
return;
}
}
o->peak_pos = (uint_t)fvec_min_elem (yin);
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
}
smpl_t
aubio_pitchyin_get_confidence (aubio_pitchyin_t * o) {
return 1. - o->yin->data[o->peak_pos];
}
uint_t
aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol)
{
o->tol = tol;
return 0;
}
smpl_t
aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o)
{
return o->tol;
}

100
deps/aubio/src/pitch/pitchyin.h vendored Normal file
View file

@ -0,0 +1,100 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
Pitch detection using the YIN algorithm
This algorithm was developed 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
http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf
\example pitch/test-pitchyin.c
*/
#ifndef AUBIO_PITCHYIN_H
#define AUBIO_PITCHYIN_H
#ifdef __cplusplus
extern "C" {
#endif
/** pitch detection object */
typedef struct _aubio_pitchyin_t aubio_pitchyin_t;
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
*/
aubio_pitchyin_t *new_aubio_pitchyin (uint_t buf_size);
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitchyin()
*/
void del_aubio_pitchyin (aubio_pitchyin_t * o);
/** execute pitch detection an input buffer
\param o pitch detection object as returned by new_aubio_pitchyin()
\param samples_in input signal vector (length as specified at creation time)
\param cands_out pitch period candidates, in samples
*/
void aubio_pitchyin_do (aubio_pitchyin_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** set tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\param tol tolerance parameter for minima selection [default 0.15]
*/
uint_t aubio_pitchyin_set_tolerance (aubio_pitchyin_t * o, smpl_t tol);
/** get tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\return tolerance parameter for minima selection [default 0.15]
*/
smpl_t aubio_pitchyin_get_tolerance (aubio_pitchyin_t * o);
/** get current confidence of YIN algorithm
\param o YIN pitch detection object
\return confidence parameter
*/
smpl_t aubio_pitchyin_get_confidence (aubio_pitchyin_t * o);
#ifdef __cplusplus
}
#endif
#endif /* AUBIO_PITCHYIN_H */

201
deps/aubio/src/pitch/pitchyinfast.c vendored Normal file
View file

@ -0,0 +1,201 @@
/*
Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/* This algorithm was developed by A. de Cheveigné 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 "fvec.h"
#include "mathutils.h"
#include "cvec.h"
#include "spectral/fft.h"
#include "pitch/pitchyinfast.h"
struct _aubio_pitchyinfast_t
{
fvec_t *yin;
smpl_t tol;
uint_t peak_pos;
fvec_t *tmpdata;
fvec_t *sqdiff;
fvec_t *kernel;
fvec_t *samples_fft;
fvec_t *kernel_fft;
aubio_fft_t *fft;
};
aubio_pitchyinfast_t *
new_aubio_pitchyinfast (uint_t bufsize)
{
aubio_pitchyinfast_t *o = AUBIO_NEW (aubio_pitchyinfast_t);
o->yin = new_fvec (bufsize / 2);
o->tmpdata = new_fvec (bufsize);
o->sqdiff = new_fvec (bufsize / 2);
o->kernel = new_fvec (bufsize);
o->samples_fft = new_fvec (bufsize);
o->kernel_fft = new_fvec (bufsize);
o->fft = new_aubio_fft (bufsize);
if (!o->yin || !o->tmpdata || !o->tmpdata || !o->sqdiff
|| !o->kernel || !o->samples_fft || !o->kernel || !o->fft)
{
del_aubio_pitchyinfast(o);
return NULL;
}
o->tol = 0.15;
o->peak_pos = 0;
return o;
}
void
del_aubio_pitchyinfast (aubio_pitchyinfast_t * o)
{
if (o->yin)
del_fvec (o->yin);
if (o->tmpdata)
del_fvec (o->tmpdata);
if (o->sqdiff)
del_fvec (o->sqdiff);
if (o->kernel)
del_fvec (o->kernel);
if (o->samples_fft)
del_fvec (o->samples_fft);
if (o->kernel_fft)
del_fvec (o->kernel_fft);
if (o->fft)
del_aubio_fft (o->fft);
AUBIO_FREE (o);
}
/* all the above in one */
void
aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * input, fvec_t * out)
{
const smpl_t tol = o->tol;
fvec_t* yin = o->yin;
const uint_t length = yin->length;
uint_t B = o->tmpdata->length;
uint_t W = o->yin->length; // B / 2
fvec_t tmp_slice, kernel_ptr;
uint_t tau;
sint_t period;
smpl_t tmp2 = 0.;
// compute r_t(0) + r_t+tau(0)
{
fvec_t *squares = o->tmpdata;
fvec_weighted_copy(input, input, squares);
#if 0
for (tau = 0; tau < W; tau++) {
tmp_slice.data = squares->data + tau;
tmp_slice.length = W;
o->sqdiff->data[tau] = fvec_sum(&tmp_slice);
}
#else
tmp_slice.data = squares->data;
tmp_slice.length = W;
o->sqdiff->data[0] = fvec_sum(&tmp_slice);
for (tau = 1; tau < W; tau++) {
o->sqdiff->data[tau] = o->sqdiff->data[tau-1];
o->sqdiff->data[tau] -= squares->data[tau-1];
o->sqdiff->data[tau] += squares->data[W+tau-1];
}
#endif
fvec_add(o->sqdiff, o->sqdiff->data[0]);
}
// compute r_t(tau) = -2.*ifft(fft(samples)*fft(samples[W-1::-1]))
{
fvec_t *compmul = o->tmpdata;
fvec_t *rt_of_tau = o->samples_fft;
aubio_fft_do_complex(o->fft, input, o->samples_fft);
// build kernel, take a copy of first half of samples
tmp_slice.data = input->data;
tmp_slice.length = W;
kernel_ptr.data = o->kernel->data + 1;
kernel_ptr.length = W;
fvec_copy(&tmp_slice, &kernel_ptr);
// reverse them
fvec_rev(&kernel_ptr);
// compute fft(kernel)
aubio_fft_do_complex(o->fft, o->kernel, o->kernel_fft);
// compute complex product
compmul->data[0] = o->kernel_fft->data[0] * o->samples_fft->data[0];
for (tau = 1; tau < W; tau++) {
compmul->data[tau] = o->kernel_fft->data[tau] * o->samples_fft->data[tau];
compmul->data[tau] -= o->kernel_fft->data[B-tau] * o->samples_fft->data[B-tau];
}
compmul->data[W] = o->kernel_fft->data[W] * o->samples_fft->data[W];
for (tau = 1; tau < W; tau++) {
compmul->data[B-tau] = o->kernel_fft->data[B-tau] * o->samples_fft->data[tau];
compmul->data[B-tau] += o->kernel_fft->data[tau] * o->samples_fft->data[B-tau];
}
// compute inverse fft
aubio_fft_rdo_complex(o->fft, compmul, rt_of_tau);
// compute square difference r_t(tau) = sqdiff - 2 * r_t_tau[W-1:-1]
for (tau = 0; tau < W; tau++) {
yin->data[tau] = o->sqdiff->data[tau] - 2. * rt_of_tau->data[tau+W];
}
}
// now build yin and look for first minimum
fvec_zeros(out);
yin->data[0] = 1.;
for (tau = 1; tau < length; tau++) {
tmp2 += yin->data[tau];
if (tmp2 != 0) {
yin->data[tau] *= tau / tmp2;
} else {
yin->data[tau] = 1.;
}
period = tau - 3;
if (tau > 4 && (yin->data[period] < tol) &&
(yin->data[period] < yin->data[period + 1])) {
o->peak_pos = (uint_t)period;
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
return;
}
}
// use global minimum
o->peak_pos = (uint_t)fvec_min_elem (yin);
out->data[0] = fvec_quadratic_peak_pos (yin, o->peak_pos);
}
smpl_t
aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o) {
return 1. - o->yin->data[o->peak_pos];
}
uint_t
aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol)
{
o->tol = tol;
return 0;
}
smpl_t
aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o)
{
return o->tol;
}

102
deps/aubio/src/pitch/pitchyinfast.h vendored Normal file
View file

@ -0,0 +1,102 @@
/*
Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
Pitch detection using YIN algorithm (fast implementation)
This algorithm was developed 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.
This implementation compute the autocorrelation function using time domain
convolution computed in the spectral domain.
see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html
http://recherche.ircam.fr/equipes/pcm/cheveign/ps/2002_JASA_YIN_proof.pdf
*/
#ifndef AUBIO_PITCHYINFAST_H
#define AUBIO_PITCHYINFAST_H
#ifdef __cplusplus
extern "C" {
#endif
/** pitch detection object */
typedef struct _aubio_pitchyinfast_t aubio_pitchyinfast_t;
/** creation of the pitch detection object
\param buf_size size of the input buffer to analyse
*/
aubio_pitchyinfast_t *new_aubio_pitchyinfast (uint_t buf_size);
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitchyin()
*/
void del_aubio_pitchyinfast (aubio_pitchyinfast_t * o);
/** execute pitch detection an input buffer
\param o pitch detection object as returned by new_aubio_pitchyin()
\param samples_in input signal vector (length as specified at creation time)
\param cands_out pitch period candidates, in samples
*/
void aubio_pitchyinfast_do (aubio_pitchyinfast_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** set tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\param tol tolerance parameter for minima selection [default 0.15]
*/
uint_t aubio_pitchyinfast_set_tolerance (aubio_pitchyinfast_t * o, smpl_t tol);
/** get tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\return tolerance parameter for minima selection [default 0.15]
*/
smpl_t aubio_pitchyinfast_get_tolerance (aubio_pitchyinfast_t * o);
/** get current confidence of YIN algorithm
\param o YIN pitch detection object
\return confidence parameter
*/
smpl_t aubio_pitchyinfast_get_confidence (aubio_pitchyinfast_t * o);
#ifdef __cplusplus
}
#endif
#endif /* AUBIO_PITCHYINFAST_H */

208
deps/aubio/src/pitch/pitchyinfft.c vendored Normal file
View file

@ -0,0 +1,208 @@
/*
Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
#include "aubio_priv.h"
#include "fvec.h"
#include "cvec.h"
#include "mathutils.h"
#include "spectral/fft.h"
#include "pitch/pitchyinfft.h"
/** pitch yinfft structure */
struct _aubio_pitchyinfft_t
{
fvec_t *win; /**< temporal weighting window */
fvec_t *winput; /**< windowed spectrum */
fvec_t *sqrmag; /**< square difference function */
fvec_t *weight; /**< spectral weighting window (psychoacoustic model) */
fvec_t *fftout; /**< Fourier transform output */
aubio_fft_t *fft; /**< fft object to compute square difference function */
fvec_t *yinfft; /**< Yin function */
smpl_t tol; /**< Yin tolerance */
uint_t peak_pos; /**< currently selected peak pos*/
uint_t short_period; /** shortest period under which to check for octave error */
};
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., -1.
};
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.60, -7.00, -4.70, -3.00, -1.80, -0.80, -0.20, -0.00, 0.50,
1.60, 3.20, 5.40, 7.80, 8.10, 5.30, -2.40, -11.1, -12.8, -12.2,
-7.40, -17.8, -17.8, -17.8
};
aubio_pitchyinfft_t *
new_aubio_pitchyinfft (uint_t samplerate, uint_t bufsize)
{
uint_t i = 0, j = 1;
smpl_t freq = 0, a0 = 0, a1 = 0, f0 = 0, f1 = 0;
aubio_pitchyinfft_t *p = AUBIO_NEW (aubio_pitchyinfft_t);
p->winput = new_fvec (bufsize);
p->fft = new_aubio_fft (bufsize);
if (!p->fft) goto beach;
p->fftout = new_fvec (bufsize);
p->sqrmag = new_fvec (bufsize);
p->yinfft = new_fvec (bufsize / 2 + 1);
p->tol = 0.85;
p->peak_pos = 0;
p->win = new_aubio_window ("hanningz", bufsize);
p->weight = new_fvec (bufsize / 2 + 1);
for (i = 0; i < p->weight->length; i++) {
freq = (smpl_t) i / (smpl_t) bufsize *(smpl_t) samplerate;
while (freq > freqs[j] && freqs[j] > 0) {
//AUBIO_DBG("freq %3.5f > %3.5f \tsamplerate %d (Hz) \t"
// "(weight length %d, bufsize %d) %d %d\n", freq, freqs[j],
// samplerate, p->weight->length, bufsize, i, 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[i] = a0;
} else if (f0 == 0) { // y = ax+b
p->weight->data[i] = (a1 - a0) / f1 * freq + a0;
} else {
p->weight->data[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[i]);
p->weight->data[i] = DB2LIN (p->weight->data[i]);
//p->weight->data[i] = SQRT(DB2LIN(p->weight->data[i]));
}
// check for octave errors above 1300 Hz
p->short_period = (uint_t)ROUND(samplerate / 1300.);
return p;
beach:
if (p->winput) del_fvec(p->winput);
AUBIO_FREE(p);
return NULL;
}
void
aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, const fvec_t * input, fvec_t * output)
{
uint_t tau, l;
uint_t length = p->fftout->length;
uint_t halfperiod;
fvec_t *fftout = p->fftout;
fvec_t *yin = p->yinfft;
smpl_t tmp = 0., sum = 0.;
// window the input
fvec_weighted_copy(input, p->win, p->winput);
// get the real / imag parts of its fft
aubio_fft_do_complex (p->fft, p->winput, fftout);
// get the squared magnitude spectrum, applying some weight
p->sqrmag->data[0] = SQR(fftout->data[0]);
p->sqrmag->data[0] *= p->weight->data[0];
for (l = 1; l < length / 2; l++) {
p->sqrmag->data[l] = SQR(fftout->data[l]) + SQR(fftout->data[length - l]);
p->sqrmag->data[l] *= p->weight->data[l];
p->sqrmag->data[length - l] = p->sqrmag->data[l];
}
p->sqrmag->data[length / 2] = SQR(fftout->data[length / 2]);
p->sqrmag->data[length / 2] *= p->weight->data[length / 2];
// get sum of weighted squared mags
for (l = 0; l < length / 2 + 1; l++) {
sum += p->sqrmag->data[l];
}
sum *= 2.;
// get the real / imag parts of the fft of the squared magnitude
aubio_fft_do_complex (p->fft, p->sqrmag, fftout);
yin->data[0] = 1.;
for (tau = 1; tau < yin->length; tau++) {
// compute the square differences
yin->data[tau] = sum - fftout->data[tau];
// and the cumulative mean normalized difference function
tmp += yin->data[tau];
if (tmp != 0) {
yin->data[tau] *= tau / tmp;
} else {
yin->data[tau] = 1.;
}
}
// find best candidates
tau = fvec_min_elem (yin);
if (yin->data[tau] < p->tol) {
// no interpolation, directly return the period as an integer
//output->data[0] = tau;
//return;
// 3 point quadratic interpolation
//return fvec_quadratic_peak_pos (yin,tau,1);
/* additional check for (unlikely) octave doubling in higher frequencies */
if (tau > p->short_period) {
output->data[0] = fvec_quadratic_peak_pos (yin, tau);
} else {
/* should compare the minimum value of each interpolated peaks */
halfperiod = FLOOR (tau / 2 + .5);
if (yin->data[halfperiod] < p->tol)
p->peak_pos = halfperiod;
else
p->peak_pos = tau;
output->data[0] = fvec_quadratic_peak_pos (yin, p->peak_pos);
}
} else {
p->peak_pos = 0;
output->data[0] = 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_fvec (p->fftout);
del_fvec (p->winput);
del_fvec (p->weight);
AUBIO_FREE (p);
}
smpl_t
aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o) {
return 1. - o->yinfft->data[o->peak_pos];
}
uint_t
aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * p, smpl_t tol)
{
p->tol = tol;
return 0;
}
smpl_t
aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * p)
{
return p->tol;
}

99
deps/aubio/src/pitch/pitchyinfft.h vendored Normal file
View file

@ -0,0 +1,99 @@
/*
Copyright (C) 2003-2015 Paul Brossier <piem@aubio.org>
This file is part of aubio.
aubio is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
aubio is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with aubio. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
Pitch detection using a spectral implementation of the YIN algorithm
This algorithm was derived from the YIN algorithm. 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](http://aubio.org/phd/), Chapter 3, Pitch Analysis, PhD thesis,
Centre for Digital music, Queen Mary University of London, London, UK, 2006.
\example pitch/test-pitchyinfft.c
*/
#ifndef AUBIO_PITCHYINFFT_H
#define AUBIO_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 o pitch detection object as returned by new_aubio_pitchyinfft
\param samples_in input signal vector (length as specified at creation time)
\param cands_out pitch period candidates, in samples
*/
void aubio_pitchyinfft_do (aubio_pitchyinfft_t * o, const fvec_t * samples_in, fvec_t * cands_out);
/** creation of the pitch detection object
\param samplerate samplerate of the input signal
\param buf_size size of the input buffer to analyse
*/
aubio_pitchyinfft_t *new_aubio_pitchyinfft (uint_t samplerate, uint_t buf_size);
/** deletion of the pitch detection object
\param o pitch detection object as returned by new_aubio_pitchyinfft()
*/
void del_aubio_pitchyinfft (aubio_pitchyinfft_t * o);
/** get tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\return tolerance parameter for minima selection [default 0.15]
*/
smpl_t aubio_pitchyinfft_get_tolerance (aubio_pitchyinfft_t * o);
/** set tolerance parameter for YIN algorithm
\param o YIN pitch detection object
\param tol tolerance parameter for minima selection [default 0.15]
*/
uint_t aubio_pitchyinfft_set_tolerance (aubio_pitchyinfft_t * o, smpl_t tol);
/** get current confidence of YIN algorithm
\param o YIN pitch detection object
\return confidence parameter
*/
smpl_t aubio_pitchyinfft_get_confidence (aubio_pitchyinfft_t * o);
#ifdef __cplusplus
}
#endif
#endif /* AUBIO_PITCHYINFFT_H */