move libc aliases from mathutils.h to to aubio_priv.h
[aubio.git] / src / pitchdetection.c
1 /*
2    Copyright (C) 2003 Paul Brossier
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 #include "aubio_priv.h"
20 #include "sample.h"
21 #include "phasevoc.h"
22 #include "mathutils.h"
23 #include "filter.h"
24 #include "pitchmcomb.h"
25 #include "pitchyin.h"
26 #include "pitchfcomb.h"
27 #include "pitchschmitt.h"
28 #include "pitchyinfft.h"
29 #include "pitchdetection.h"
30
31 typedef smpl_t (*aubio_pitchdetection_func_t)(aubio_pitchdetection_t *p, 
32                 fvec_t * ibuf);
33 typedef smpl_t (*aubio_pitchdetection_conv_t)(smpl_t value,uint_t srate,uint_t bufsize);
34 void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf);
35
36 smpl_t aubio_pitchdetection_mcomb(aubio_pitchdetection_t *p, fvec_t * ibuf);
37 smpl_t aubio_pitchdetection_yin(aubio_pitchdetection_t *p, fvec_t *ibuf);
38 smpl_t aubio_pitchdetection_schmitt(aubio_pitchdetection_t *p, fvec_t *ibuf);
39 smpl_t aubio_pitchdetection_fcomb(aubio_pitchdetection_t *p, fvec_t *ibuf);
40 smpl_t aubio_pitchdetection_yinfft(aubio_pitchdetection_t *p, fvec_t *ibuf);
41
42 /** generic pitch detection structure */
43 struct _aubio_pitchdetection_t {
44   aubio_pitchdetection_type type; /**< pitch detection mode */
45   aubio_pitchdetection_mode mode; /**< pitch detection output mode */
46   uint_t srate;                   /**< samplerate */
47   uint_t bufsize;                 /**< buffer size */
48   aubio_pitchmcomb_t * mcomb;     /**< mcomb object */
49   aubio_pitchfcomb_t * fcomb;     /**< fcomb object */
50   aubio_pitchschmitt_t * schmitt; /**< schmitt object */
51   aubio_pitchyinfft_t * yinfft;   /**< yinfft object */
52   aubio_filter_t * filter;        /**< filter */
53   aubio_pvoc_t * pv;              /**< phase vocoder for mcomb */ 
54   cvec_t * fftgrain;              /**< spectral frame for mcomb */
55   fvec_t * buf;                   /**< temporary buffer for yin */
56   fvec_t * yin;                   /**< yin function */
57   smpl_t yinthres;                /**< yin peak picking threshold parameter */
58   aubio_pitchdetection_func_t callback; /**< pointer to current pitch detection method */
59   aubio_pitchdetection_conv_t freqconv; /**< pointer to current pitch conversion method */ 
60 };
61
62 /* convenience wrapper function for frequency unit conversions 
63  * should probably be rewritten with #defines */
64 smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize);
65 smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize){
66         return aubio_freqtobin(f,srate,bufsize);
67 }
68
69 smpl_t freqconvmidi(smpl_t f,uint_t srate,uint_t bufsize);
70 smpl_t freqconvmidi(smpl_t f,uint_t srate,uint_t bufsize){
71         return aubio_freqtomidi(f);
72 }
73
74 smpl_t freqconvpass(smpl_t f,uint_t srate,uint_t bufsize);
75 smpl_t freqconvpass(smpl_t f,uint_t srate,uint_t bufsize){
76         return f;
77 }
78
79 aubio_pitchdetection_t * new_aubio_pitchdetection(uint_t bufsize, 
80                 uint_t hopsize, 
81                 uint_t channels,
82                 uint_t samplerate,
83                 aubio_pitchdetection_type type,
84                 aubio_pitchdetection_mode mode)
85 {
86         aubio_pitchdetection_t *p = AUBIO_NEW(aubio_pitchdetection_t);
87         p->srate = samplerate;
88         p->type = type;
89         p->mode = mode;
90         p->bufsize = bufsize;
91         switch(p->type) {
92                 case aubio_pitch_yin:
93                         p->buf      = new_fvec(bufsize,channels);
94                         p->yin      = new_fvec(bufsize/2,channels);
95                         p->callback = aubio_pitchdetection_yin;
96                         p->yinthres = 0.15;
97                         break;
98                 case aubio_pitch_mcomb:
99                         p->pv       = new_aubio_pvoc(bufsize, hopsize, channels);
100                         p->fftgrain = new_cvec(bufsize, channels);
101                         p->mcomb    = new_aubio_pitchmcomb(bufsize,hopsize,channels,samplerate);
102                         p->filter   = new_aubio_cdsgn_filter(samplerate);
103                         p->callback = aubio_pitchdetection_mcomb;
104                         break;
105                 case aubio_pitch_fcomb:
106                         p->buf      = new_fvec(bufsize,channels);
107                         p->fcomb    = new_aubio_pitchfcomb(bufsize,hopsize,samplerate);
108                         p->callback = aubio_pitchdetection_fcomb;
109                         break;
110                 case aubio_pitch_schmitt:
111                         p->buf      = new_fvec(bufsize,channels);
112                         p->schmitt  = new_aubio_pitchschmitt(bufsize,samplerate);
113                         p->callback = aubio_pitchdetection_schmitt;
114                         break;
115                 case aubio_pitch_yinfft:
116                         p->buf      = new_fvec(bufsize,channels);
117                         p->yinfft   = new_aubio_pitchyinfft(bufsize);
118                         p->callback = aubio_pitchdetection_yinfft;
119                         p->yinthres = 0.85;
120                         break;
121                 default:
122                         break;
123         }
124         switch(p->mode) {
125                 case aubio_pitchm_freq:
126                         p->freqconv = freqconvpass;
127                         break;
128                 case aubio_pitchm_midi:
129                         p->freqconv = freqconvmidi;
130                         break;
131                 case aubio_pitchm_cent:
132                         /* bug: not implemented */
133                         p->freqconv = freqconvmidi;
134                         break;
135                 case aubio_pitchm_bin:
136                         p->freqconv = freqconvbin;
137                         break;
138                 default:
139                         break;
140         }
141         return p;
142 }
143
144 void del_aubio_pitchdetection(aubio_pitchdetection_t * p) {
145         switch(p->type) {
146                 case aubio_pitch_yin:
147                         del_fvec(p->yin);
148                         del_fvec(p->buf);
149                         break;
150                 case aubio_pitch_mcomb:
151                         del_aubio_pvoc(p->pv);
152                         del_cvec(p->fftgrain);
153                         del_aubio_pitchmcomb(p->mcomb);
154                         break;
155                 case aubio_pitch_schmitt:
156                         del_fvec(p->buf);
157                         del_aubio_pitchschmitt(p->schmitt);
158                         break;
159                 case aubio_pitch_fcomb:
160                         del_fvec(p->buf);
161                         del_aubio_pitchfcomb(p->fcomb);
162                         break;
163                 case aubio_pitch_yinfft:
164                         del_fvec(p->buf);
165                         del_aubio_pitchyinfft(p->yinfft);
166                         break;
167                 default:
168                         break;
169         }
170         AUBIO_FREE(p);
171 }
172
173 void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf){
174         uint_t i,j = 0, overlap_size = 0;
175         overlap_size = p->buf->length-ibuf->length;
176         for (i=0;i<p->buf->channels;i++){
177                 for (j=0;j<overlap_size;j++){
178                         p->buf->data[i][j] = 
179                                 p->buf->data[i][j+ibuf->length];
180                 }
181         }
182         for (i=0;i<ibuf->channels;i++){
183                 for (j=0;j<ibuf->length;j++){
184                         p->buf->data[i][j+overlap_size] = 
185                                 ibuf->data[i][j];
186                 }
187         }
188 }
189
190 void aubio_pitchdetection_set_yinthresh(aubio_pitchdetection_t *p, smpl_t thres) {
191         p->yinthres = thres;
192 }
193
194 smpl_t aubio_pitchdetection(aubio_pitchdetection_t *p, fvec_t * ibuf) {
195         return p->freqconv(p->callback(p,ibuf),p->srate,p->bufsize);
196 }
197
198 smpl_t aubio_pitchdetection_mcomb(aubio_pitchdetection_t *p, fvec_t *ibuf) {
199         smpl_t pitch = 0.;
200         aubio_filter_do(p->filter,ibuf);
201         aubio_pvoc_do(p->pv,ibuf,p->fftgrain);
202         pitch = aubio_pitchmcomb_detect(p->mcomb,p->fftgrain);
203         /** \bug should move the >0 check within aubio_bintofreq */
204         if (pitch>0.) {
205                 pitch = aubio_bintofreq(pitch,p->srate,p->bufsize);
206         } else {
207                 pitch = 0.;
208         }
209         return pitch;
210 }
211
212 smpl_t aubio_pitchdetection_yin(aubio_pitchdetection_t *p, fvec_t *ibuf) {
213         smpl_t pitch = 0.;
214         aubio_pitchdetection_slideblock(p,ibuf);
215         pitch = aubio_pitchyin_getpitchfast(p->buf,p->yin, p->yinthres);
216         if (pitch>0) {
217                 pitch = p->srate/(pitch+0.);
218         } else {
219                 pitch = 0.;
220         }
221         return pitch;
222 }
223
224
225 smpl_t aubio_pitchdetection_yinfft(aubio_pitchdetection_t *p, fvec_t *ibuf){
226         smpl_t pitch = 0.;
227         aubio_pitchdetection_slideblock(p,ibuf);
228         pitch = aubio_pitchyinfft_detect(p->yinfft,p->buf,p->yinthres);
229         if (pitch>0) {
230                 pitch = p->srate/(pitch+0.);
231         } else {
232                 pitch = 0.;
233         }
234         return pitch; 
235 }
236
237 smpl_t aubio_pitchdetection_fcomb(aubio_pitchdetection_t *p, fvec_t *ibuf){
238         aubio_pitchdetection_slideblock(p,ibuf);
239         return aubio_pitchfcomb_detect(p->fcomb,p->buf);
240 }
241
242 smpl_t aubio_pitchdetection_schmitt(aubio_pitchdetection_t *p, fvec_t *ibuf){
243         aubio_pitchdetection_slideblock(p,ibuf);
244         return aubio_pitchschmitt_detect(p->schmitt,p->buf);
245 }