summaryrefslogtreecommitdiffhomepage
path: root/src/lingot-yin.c
diff options
context:
space:
mode:
authorpp <pp@455248ca-bdda-0310-9134-f4ebb693071a>2008-03-22 16:56:08 +0000
committerpp <pp@455248ca-bdda-0310-9134-f4ebb693071a>2008-03-22 16:56:08 +0000
commitc77651dcdf11427071d69821d63b8de80874b7a2 (patch)
tree58540adff3441dd55ec36a649fcfe01f6429200a /src/lingot-yin.c
parent65d7466d6f9f44b0c7104d941b0e89fdd6938920 (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.c74
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);
+}