examples/: make use of aubio_onset in aubioonset and aubionotes, simplify, keep only...
[aubio.git] / examples / aubionotes.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 "utils.h"
20
21 /* pitch objects */
22 smpl_t pitch = 0.;
23
24 uint_t median = 6;
25 smpl_t curlevel = 0.;
26
27 aubio_pitchdetection_t *pitchdet;
28
29 fvec_t *note_buffer = NULL;
30 fvec_t *note_buffer2 = NULL;
31
32 smpl_t curnote = 0.;
33 smpl_t newnote = 0.;
34 uint_t isready = 0;
35 unsigned int pos = 0; /*frames%dspblocksize*/
36
37 aubio_pitchdetection_t *pitchdet;
38 aubio_onset_t *o;
39 fvec_t *onset;
40 fvec_t *pitch_obuf;
41
42 /** append new note candidate to the note_buffer and return filtered value. we
43  * need to copy the input array as fvec_median destroy its input data.*/
44 void note_append (fvec_t * note_buffer, smpl_t curnote);
45 uint_t get_note (fvec_t * note_buffer, fvec_t * note_buffer2);
46
47 static int aubio_process(smpl_t **input, smpl_t **output, int nframes) {
48   unsigned int i;       /*channels*/
49   unsigned int j;       /*frames*/
50   for (j=0;j<(unsigned)nframes;j++) {
51     if(usejack) {
52       for (i=0;i<channels;i++) {
53         /* write input to datanew */
54         fvec_write_sample(ibuf, input[i][j], i, pos);
55         /* put synthnew in output */
56         output[i][j] = fvec_read_sample(obuf, i, pos);
57       }
58     }
59     /*time for fft*/
60     if (pos == overlap_size-1) {         
61       /* block loop */
62       aubio_onset_do(o, ibuf, onset);
63       
64       aubio_pitchdetection_do (pitchdet, ibuf, pitch_obuf);
65       pitch = fvec_read_sample(pitch_obuf, 0, 0);
66       if(median){
67               note_append(note_buffer, pitch);
68       }
69
70       /* curlevel is negatif or 1 if silence */
71       curlevel = aubio_level_detection(ibuf, silence);
72       if (fvec_read_sample(onset, 0, 0)) {
73               /* test for silence */
74               if (curlevel == 1.) {
75                       if (median) isready = 0;
76                       /* send note off */
77                       send_noteon(curnote,0);
78               } else {
79                       if (median) {
80                               isready = 1;
81                       } else {
82                               /* kill old note */
83                               send_noteon(curnote,0);
84                               /* get and send new one */
85                               send_noteon(pitch,127+(int)floor(curlevel));
86                               curnote = pitch;
87                       }
88
89                       for (pos = 0; pos < overlap_size; pos++){
90                               obuf->data[0][pos] = woodblock->data[0][pos];
91                       }
92               }
93       } else {
94               if (median) {
95                       if (isready > 0)
96                               isready++;
97                       if (isready == median)
98                       {
99                               /* kill old note */
100                               send_noteon(curnote,0);
101                               newnote = get_note(note_buffer, note_buffer2);
102                               curnote = newnote;
103                               /* get and send new one */
104                               if (curnote>45){
105                                       send_noteon(curnote,127+(int)floor(curlevel));
106                               }
107                       }
108               } // if median
109         for (pos = 0; pos < overlap_size; pos++)
110           obuf->data[0][pos] = 0.;
111       }
112       /* end of block loop */
113       pos = -1; /* so it will be zero next j loop */
114     }
115     pos++;
116   }
117   return 1;
118 }
119
120 static void process_print (void) {
121       if (verbose) outmsg("%f\n",pitch);
122 }
123
124 void
125 note_append (fvec_t * note_buffer, smpl_t curnote)
126 {
127   uint_t i = 0;
128   for (i = 0; i < note_buffer->length - 1; i++) {
129     note_buffer->data[0][i] = note_buffer->data[0][i + 1];
130   }
131   note_buffer->data[0][note_buffer->length - 1] = curnote;
132   return;
133 }
134
135 uint_t
136 get_note (fvec_t * note_buffer, fvec_t * note_buffer2)
137 {
138   uint_t i = 0;
139   for (i = 0; i < note_buffer->length; i++) {
140     note_buffer2->data[0][i] = note_buffer->data[0][i];
141   }
142   return fvec_median (note_buffer2);
143 }
144
145 int main(int argc, char **argv) {
146   examples_common_init(argc,argv);
147
148   o = new_aubio_onset (onset_mode, buffer_size, overlap_size, channels,
149           samplerate);
150   onset = new_fvec (1, channels);
151
152   pitchdet = new_aubio_pitchdetection (pitch_mode, buffer_size * 4,
153           overlap_size, channels, samplerate);
154   aubio_pitchdetection_set_tolerance (pitchdet, 0.7);
155   pitch_obuf = new_fvec (1, channels);
156   if (median) {
157       note_buffer = new_fvec (median, 1);
158       note_buffer2 = new_fvec (median, 1);
159   }
160
161   examples_common_process(aubio_process, process_print);
162
163   send_noteon (curnote, 0);
164   del_aubio_pitchdetection (pitchdet);
165   if (median) {
166       del_fvec (note_buffer);
167       del_fvec (note_buffer2);
168   }
169   del_fvec (pitch_obuf);
170
171   examples_common_del();
172   debug("End of program.\n");
173   fflush(stderr);
174   return 0;
175 }
176