import 0.1.7.1
[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 <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <getopt.h>
23 #include <unistd.h>
24 #include <math.h> // how do i do a floorf with a mask again ?
25 #include "aubio.h"
26 #include "utils.h"
27
28 /* settings */
29 const char * output_filename = NULL;
30 const char * input_filename  = NULL;
31 const char * onset_filename  = "/usr/share/sounds/aubio/woodblock.aiff";
32 int verbose = 0;
33 int usejack = 0;
34 int usedoubled = 1;
35 int usemidi = 1;
36
37 /* energy,specdiff,hfc,complexdomain,phase */
38 aubio_onsetdetection_type type_onset  = hfc;
39 aubio_onsetdetection_type type_onset2 = hfc;
40 smpl_t threshold                      = 0.3;
41 smpl_t threshold2                     = -90.;
42 uint_t buffer_size                    = 1024;
43 uint_t overlap_size                   = 512;
44 uint_t channels                       = 1;
45 uint_t samplerate                     = 44100;
46
47 /* global objects */
48 int frames;
49 aubio_pvoc_t * pv;
50 fvec_t * ibuf;
51 fvec_t * obuf;
52 cvec_t * fftgrain;
53 fvec_t * woodblock;
54 aubio_onsetdetection_t *o;
55 aubio_onsetdetection_t *o2;
56 fvec_t *onset;
57 fvec_t *onset2;
58 int isonset = 0;
59 aubio_pickpeak_t * parms;
60
61 /* pitch objects */
62 int curnote                = 0;
63 smpl_t pitch               = 0.;
64 aubio_pitchdetection_t * pitchdet;
65 int bufpos = 0;
66 smpl_t curlevel = 0;
67 smpl_t maxonset = 0.;
68
69 /* midi objects */
70 aubio_midi_player_t * mplay; 
71 aubio_midi_driver_t * mdriver; 
72 aubio_midi_event_t  * event;
73
74 void send_noteon(aubio_midi_driver_t * d, int pitch, int velo);
75 void send_noteon(aubio_midi_driver_t * d, int pitch, int velo)
76 {
77     /* we should check if we use midi here, not jack */
78 #if ALSA_SUPPORT
79     if (usejack) {
80         if (velo==0) {
81             aubio_midi_event_set_type(event,NOTE_OFF);
82         } else {
83             aubio_midi_event_set_type(event,NOTE_ON);
84         }
85         aubio_midi_event_set_channel(event,0);
86         aubio_midi_event_set_pitch(event,pitch);
87         aubio_midi_event_set_velocity(event,velo);
88         aubio_midi_direct_output(mdriver,event);
89     } else 
90 #endif
91     {
92         if (velo==0) {
93             outmsg("%f\n",frames*overlap_size/(float)samplerate);
94         } else {
95             outmsg("%d\t%f\t",pitch,frames*overlap_size/(float)samplerate);
96         }
97     }
98 }
99
100 int aubio_process(float **input, float **output, int nframes);
101 int aubio_process(float **input, float **output, int nframes) {
102   unsigned int i;       /*channels*/
103   unsigned int j;       /*frames*/
104   unsigned int pos = 0; /*frames%dspblocksize*/
105   for (j=0;j<nframes;j++) {
106     if(usejack) {
107       for (i=0;i<channels;i++) {
108         /* write input to datanew */
109         fvec_write_sample(ibuf, input[i][j], i, pos);
110         /* put synthnew in output */
111         output[i][j] = fvec_read_sample(obuf, i, pos);
112       }
113     }
114     /*time for fft*/
115     if (pos == overlap_size-1) {         
116       /* block loop */
117       aubio_pvoc_do (pv,ibuf, fftgrain);
118       aubio_onsetdetection(o,fftgrain, onset);
119       if (usedoubled) {
120         aubio_onsetdetection(o2,fftgrain, onset2);
121         onset->data[0][0] *= onset2->data[0][0];
122       }
123       isonset = aubio_peakpick_pimrt(onset,parms);
124       
125       pitch = aubio_pitchdetection(pitchdet,ibuf);
126
127       /* curlevel is negatif or 1 if silence */
128       curlevel = aubio_level_detection(ibuf, threshold2);
129       if (isonset) {
130         /* test for silence */
131         if (curlevel == 1.) {
132           isonset=0;
133           /* send note off */
134           send_noteon(mdriver,curnote,0);
135         } else {
136           /* kill old note */
137           send_noteon(mdriver,curnote,0);
138           //curnote = (int)FLOOR(bintomidi(pitch,samplerate,buffer_size*4) + .5);
139           curnote = (int)FLOOR(freqtomidi(pitch) + .5);
140           /* get and send new one */
141           /*if (curnote<45){
142             send_noteon(mdriver,curnote,0);
143           } else {*/
144           if (curnote>45){
145             send_noteon(mdriver,curnote,127+(int)FLOOR(curlevel));
146           }
147           for (pos = 0; pos < overlap_size; pos++){
148             obuf->data[0][pos] = woodblock->data[0][pos];
149           }
150         }
151       } else {
152         for (pos = 0; pos < overlap_size; pos++)
153           obuf->data[0][pos] = 0.;
154       }
155       /* end of block loop */
156       pos = -1; /* so it will be zero next j loop */
157     }
158     pos++;
159   }
160   return 1;
161 }
162
163 int main(int argc, char **argv) {
164
165   aubio_file_t * file = NULL;
166   aubio_file_t * fileout = NULL;
167
168   aubio_file_t * onsetfile = new_file_ro(onset_filename);
169   /* parse command line arguments */
170   parse_args(argc, argv);
171
172   if(!usejack)
173   {
174     debug("Opening files ...\n");
175     file = new_file_ro (input_filename);
176     file_info(file);
177     samplerate = aubio_file_samplerate(file);
178     channels = aubio_file_channels(file);
179     if (output_filename != NULL)
180       fileout = new_file_wo(file, output_filename);
181   }
182
183   ibuf        = new_fvec(overlap_size, channels);
184   obuf        = new_fvec(overlap_size, channels);
185   woodblock   = new_fvec(buffer_size,1);
186   fftgrain    = new_cvec(buffer_size, channels);
187
188   pitchdet = new_aubio_pitchdetection(buffer_size*4, overlap_size, channels, samplerate, mcomb, freq);
189   //pitchdet = new_aubio_pitchdetection(buffer_size*2, overlap_size, channels, samplerate, yin, freq);
190   
191   /* read the output sound once */
192   file_read(onsetfile, overlap_size, woodblock);
193   /* phase vocoder */
194   pv = new_aubio_pvoc(buffer_size, overlap_size, channels);
195   /* onsets */
196   parms = new_aubio_peakpicker(threshold);
197   o = new_aubio_onsetdetection(type_onset,buffer_size,channels);
198   onset = new_fvec(1, channels);
199   if (usedoubled)    {
200     o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels);
201     onset2 = new_fvec(1 , channels);
202   }
203
204   if(usejack) {
205 #ifdef JACK_SUPPORT
206     aubio_jack_t * jack_setup;
207     debug("Midi init ...\n");
208     debug("Jack init ...\n");
209     jack_setup = new_aubio_jack(channels, channels,
210           (aubio_process_func_t)aubio_process);
211
212     mplay = new_aubio_midi_player();
213
214     mdriver = new_aubio_midi_driver("alsa_seq",
215         (handle_midi_event_func_t)aubio_midi_send_event, mplay);
216
217     event = new_aubio_midi_event();
218     
219     debug("Jack activation ...\n");
220     aubio_jack_activate(jack_setup);
221     debug("Processing (Ctrl+C to quit) ...\n");
222     pause();
223     send_noteon(mdriver,curnote,0);
224     aubio_jack_close(jack_setup);
225     del_aubio_midi_driver(mdriver);
226 #else
227     usage(stderr, 1);
228     outmsg("Compiled without jack output, exiting.\n");
229 #endif
230
231   } else {
232     /* phasevoc */
233     debug("Processing ...\n");
234
235     frames = 0;
236
237     while (overlap_size == file_read(file, overlap_size, ibuf))
238     {
239       isonset=0;
240       aubio_process(ibuf->data, obuf->data, overlap_size);
241       if (output_filename != NULL) {
242         file_write(fileout,overlap_size,obuf);
243       }
244       frames++;
245     }
246     send_noteon(mdriver,curnote,0);
247
248     debug("Processed %d frames of %d samples.\n", frames, buffer_size);
249     del_file(file);
250
251     if (output_filename != NULL)
252       del_file(fileout);
253
254   }
255
256   del_aubio_pvoc(pv);
257   del_fvec(obuf);
258   del_fvec(ibuf);
259   del_cvec(fftgrain);
260   del_aubio_pitchdetection(pitchdet);
261   del_fvec(onset);
262
263   debug("End of program.\n");
264   fflush(stderr);
265   return 0;
266 }
267