move libc aliases from mathutils.h to to aubio_priv.h
[aubio.git] / src / pitchschmitt.c
1 /*
2    Copyright (C) 2004, 2005  Mario Lang <mlang@delysid.org>
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "aubio_priv.h"
21 #include "sample.h"
22 #include "pitchschmitt.h"
23
24 smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata);
25
26 struct _aubio_pitchschmitt_t {
27         uint_t blockSize;
28         uint_t rate;
29         signed short int *schmittBuffer;
30         signed short int *schmittPointer;
31 };
32
33 aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate)
34 {
35   aubio_pitchschmitt_t * p = AUBIO_NEW(aubio_pitchschmitt_t);
36   p->blockSize = size;
37   p->schmittBuffer = AUBIO_ARRAY(signed short int,p->blockSize);
38   p->schmittPointer = p->schmittBuffer;
39   p->rate = samplerate;
40   return p;
41 }
42
43 smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input)
44 {
45   signed short int buf[input->length];
46   uint_t i;
47   for (i=0; i<input->length; i++) {
48     buf[i] = input->data[0][i]*32768.;
49   }
50   return aubio_schmittS16LE(p, input->length, buf);
51 }
52
53 smpl_t aubio_schmittS16LE (aubio_pitchschmitt_t *p, uint_t nframes, signed short int *indata)
54 {
55   uint_t i, j;
56   uint_t blockSize = p->blockSize;
57   signed short int *schmittBuffer = p->schmittBuffer;
58   signed short int *schmittPointer = p->schmittPointer;
59
60   smpl_t freq = 0., trigfact = 0.6;
61
62   for (i=0; i<nframes; i++) {
63     *schmittPointer++ = indata[i];
64     if (schmittPointer-schmittBuffer >= (sint_t)blockSize) {
65       sint_t endpoint, startpoint, t1, t2, A1, A2, tc, schmittTriggered;
66
67       schmittPointer = schmittBuffer;
68
69       for (j=0,A1=0,A2=0; j<blockSize; j++) {
70         if (schmittBuffer[j]>0 && A1<schmittBuffer[j])  A1 = schmittBuffer[j];
71         if (schmittBuffer[j]<0 && A2<-schmittBuffer[j]) A2 = -schmittBuffer[j];
72       }
73       t1 =   (sint_t)( A1 * trigfact + 0.5);
74       t2 = - (sint_t)( A2 * trigfact + 0.5);
75       startpoint=0;
76       for (j=1; schmittBuffer[j]<=t1 && j<blockSize; j++);
77       for (; !(schmittBuffer[j]  >=t2 &&
78                schmittBuffer[j+1]< t2) && j<blockSize; j++);
79       startpoint=j;
80       schmittTriggered=0;
81       endpoint=startpoint+1;
82       for(j=startpoint,tc=0; j<blockSize; j++) {
83         if (!schmittTriggered) {
84           schmittTriggered = (schmittBuffer[j] >= t1);
85         } else if (schmittBuffer[j]>=t2 && schmittBuffer[j+1]<t2) {
86           endpoint=j;
87           tc++;
88           schmittTriggered = 0;
89         }
90       }
91       if (endpoint > startpoint) {
92         freq = ((smpl_t)p->rate*(tc/(smpl_t)(endpoint-startpoint)));
93       }
94     }
95   }
96
97   p->schmittBuffer  = schmittBuffer;
98   p->schmittPointer = schmittPointer;
99   return freq;
100 }
101
102 void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p)
103 {
104   AUBIO_FREE(p->schmittBuffer);
105   AUBIO_FREE(p);
106 }
107