examples/: move parse_args to parse_args.h, clean up, remove lash and old frames_delay
[aubio.git] / examples / aubionotes.c
1 /*
2   Copyright (C) 2003-2009 Paul Brossier <piem@aubio.org>
3
4   This file is part of aubio.
5
6   aubio is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   aubio is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #define AUBIO_UNSTABLE 1 // for fvec_median
22 #include "utils.h"
23 #define PROG_HAS_PITCH 1
24 #define PROG_HAS_ONSET 1
25 #include "parse_args.h"
26
27 /* pitch objects */
28 smpl_t pitch = 0.;
29
30 uint_t median = 6;
31 smpl_t curlevel = 0.;
32
33 aubio_pitch_t *pitchdet;
34
35 fvec_t *note_buffer = NULL;
36 fvec_t *note_buffer2 = NULL;
37
38 smpl_t curnote = 0.;
39 smpl_t newnote = 0.;
40 uint_t isready = 0;
41 unsigned int pos = 0; /*frames%dspblocksize*/
42
43 aubio_pitch_t *pitchdet;
44 aubio_onset_t *o;
45 fvec_t *onset;
46 fvec_t *pitch_obuf;
47
48 /** append new note candidate to the note_buffer and return filtered value. we
49  * need to copy the input array as fvec_median destroy its input data.*/
50 void note_append (fvec_t * note_buffer, smpl_t curnote);
51 uint_t get_note (fvec_t * note_buffer, fvec_t * note_buffer2);
52
53 static int aubio_process(smpl_t **input, smpl_t **output, int nframes) {
54   unsigned int j;       /*frames*/
55   for (j=0;j<(unsigned)nframes;j++) {
56     if(usejack) {
57       /* write input to datanew */
58       fvec_write_sample(ibuf, input[0][j], pos);
59       /* put synthnew in output */
60       output[0][j] = fvec_read_sample(obuf, pos);
61     }
62     /*time for fft*/
63     if (pos == overlap_size-1) {         
64       /* block loop */
65       aubio_onset_do(o, ibuf, onset);
66       
67       aubio_pitch_do (pitchdet, ibuf, pitch_obuf);
68       pitch = fvec_read_sample(pitch_obuf, 0);
69       if(median){
70               note_append(note_buffer, pitch);
71       }
72
73       /* curlevel is negatif or 1 if silence */
74       curlevel = aubio_level_detection(ibuf, silence);
75       if (fvec_read_sample(onset, 0)) {
76               /* test for silence */
77               if (curlevel == 1.) {
78                       if (median) isready = 0;
79                       /* send note off */
80                       send_noteon(curnote,0);
81               } else {
82                       if (median) {
83                               isready = 1;
84                       } else {
85                               /* kill old note */
86                               send_noteon(curnote,0);
87                               /* get and send new one */
88                               send_noteon(pitch,127+(int)floor(curlevel));
89                               curnote = pitch;
90                       }
91
92                       for (pos = 0; pos < overlap_size; pos++){
93                               //obuf->data[pos] = woodblock->data[pos];
94                       }
95               }
96       } else {
97               if (median) {
98                       if (isready > 0)
99                               isready++;
100                       if (isready == median)
101                       {
102                               /* kill old note */
103                               send_noteon(curnote,0);
104                               newnote = get_note(note_buffer, note_buffer2);
105                               curnote = newnote;
106                               /* get and send new one */
107                               if (curnote>45){
108                                       send_noteon(curnote,127+(int)floor(curlevel));
109                               }
110                       }
111               } // if median
112         for (pos = 0; pos < overlap_size; pos++)
113           obuf->data[pos] = 0.;
114       }
115       /* end of block loop */
116       pos = -1; /* so it will be zero next j loop */
117     }
118     pos++;
119   }
120   return 1;
121 }
122
123 static void process_print (void) {
124       if (verbose) outmsg("%f\n",pitch);
125 }
126
127 void
128 note_append (fvec_t * note_buffer, smpl_t curnote)
129 {
130   uint_t i = 0;
131   for (i = 0; i < note_buffer->length - 1; i++) {
132     note_buffer->data[i] = note_buffer->data[i + 1];
133   }
134   note_buffer->data[note_buffer->length - 1] = curnote;
135   return;
136 }
137
138 uint_t
139 get_note (fvec_t * note_buffer, fvec_t * note_buffer2)
140 {
141   uint_t i;
142   for (i = 0; i < note_buffer->length; i++) {
143     note_buffer2->data[i] = note_buffer->data[i];
144   }
145   return fvec_median (note_buffer2);
146 }
147
148 int main(int argc, char **argv) {
149   examples_common_init(argc,argv);
150
151   o = new_aubio_onset (onset_method, buffer_size, overlap_size, samplerate);
152   if (onset_threshold != 0.) aubio_onset_set_threshold (o, onset_threshold);
153   onset = new_fvec (1);
154
155   pitchdet = new_aubio_pitch (pitch_method, buffer_size * 4,
156           overlap_size, samplerate);
157   aubio_pitch_set_tolerance (pitchdet, 0.7);
158   pitch_obuf = new_fvec (1);
159   if (median) {
160       note_buffer = new_fvec (median);
161       note_buffer2 = new_fvec (median);
162   }
163
164   examples_common_process(aubio_process, process_print);
165
166   send_noteon (curnote, 0);
167   del_aubio_pitch (pitchdet);
168   if (median) {
169       del_fvec (note_buffer);
170       del_fvec (note_buffer2);
171   }
172   del_fvec (pitch_obuf);
173
174   examples_common_del();
175   debug("End of program.\n");
176   fflush(stderr);
177   return 0;
178 }
179