diff options
| author | pp <pp@455248ca-bdda-0310-9134-f4ebb693071a> | 2008-03-22 16:56:08 +0000 |
|---|---|---|
| committer | pp <pp@455248ca-bdda-0310-9134-f4ebb693071a> | 2008-03-22 16:56:08 +0000 |
| commit | c77651dcdf11427071d69821d63b8de80874b7a2 (patch) | |
| tree | 58540adff3441dd55ec36a649fcfe01f6429200a /src/lingot-yin.c | |
| parent | 65d7466d6f9f44b0c7104d941b0e89fdd6938920 (diff) | |
- experimental, very simple implementation of YIN fundamental frequency estimator
git-svn-id: https://lampka.siedziba.pl:790/svn/repos/lingot-win32@309 455248ca-bdda-0310-9134-f4ebb693071a
Diffstat (limited to 'src/lingot-yin.c')
| -rw-r--r-- | src/lingot-yin.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/lingot-yin.c b/src/lingot-yin.c new file mode 100644 index 0000000..617f625 --- /dev/null +++ b/src/lingot-yin.c @@ -0,0 +1,74 @@ +//-*- C++ -*- +/* + * YIN pitch estimator + * Copyright (C) 2008 Piotr Pawlow <pp@siedziba.pl> + * + * This file is part of lingot. + * + * lingot 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. + * + * lingot 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 lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Implementation of YIN algorithm, published in: + * + * A. de Cheveigne and H. Kawahara: YIN, an F0 estimator + * J. Acoust. Soc. Am., Vol. 111, No. 4, April 2002 + * http://www.ircam.fr/pcm/cheveign/pss/2002_JASA_YIN.pdf + */ + +#include "lingot-yin.h" + +inline FLT yin_sqr(FLT x) +{ + return x*x; +} + +inline FLT yin_interpolate_tau(FLT y1, FLT y2, FLT y3) +{ + return ((y1 - y3)/(2.0*(y3 + y1 - (2.0*y2)))); +} + +FLT yin(LingotCore* core) { + FLT dt_tau; + FLT dt_tau_sum = 0; + FLT dpt_right = 1.0/0.0, dpt_center, dpt_left; + FLT thr = core->conf->yin_threshold; + FLT dpt_min = 1.0/0.0; + FLT dpt_min_left, dpt_min_right; + int j, tau, tau_min; + int len = core->conf->temporal_buffer_size / 2; + + for (tau = 1; (tau < len) && ((dpt_center > thr) || (dpt_right < dpt_center) || (tau <= 2)); tau++) + { + dt_tau = 0; + for (j = 0; j < len ; j++) + { + dt_tau += yin_sqr(core->temporal_buffer[j] - core->temporal_buffer[j+tau]); + } + dt_tau_sum += dt_tau; + + dpt_left = dpt_center; + dpt_center = dpt_right; + dpt_right = dt_tau / ( 1.0 / tau * dt_tau_sum ); + + if (dpt_center < dpt_min) + { + dpt_min_left = dpt_left; + dpt_min = dpt_center; + dpt_min_right = dpt_right; + tau_min = tau - 1; + } + } + return (FLT)tau_min + yin_interpolate_tau(dpt_left, dpt_center, dpt_right); +} |
