add -v switch to examples usage string
[aubio.git] / examples / utils.c
1
2 #include "aubio.h"
3
4 #ifndef JACK_SUPPORT
5 #define JACK_SUPPORT 0
6 #endif
7
8 #include <getopt.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <math.h> /* for isfinite */
13 #include "utils.h"
14
15 #ifdef LASH_SUPPORT
16 #include <lash/lash.h>
17 #include <pthread.h>
18 lash_client_t * aubio_lash_client;
19 lash_args_t * lash_args;
20 void * lash_thread_main (void * data);
21 int lash_main (void);
22 void save_data (void);
23 void restore_data(lash_config_t * lash_config);
24 pthread_t lash_thread;
25 #endif /* LASH_SUPPORT */
26
27 /* settings */
28 const char * output_filename = NULL;
29 const char * input_filename  = NULL;
30 const char * onset_filename  = AUBIO_PREFIX "/share/sounds/" PACKAGE "/woodblock.aiff";
31 int frames = 0;
32 int verbose = 0;
33 int usejack = 0;
34 int usedoubled = 1;
35
36
37 /* energy,specdiff,hfc,complexdomain,phase */
38 aubio_onsetdetection_type type_onset  = aubio_onset_kl;
39 aubio_onsetdetection_type type_onset2 = aubio_onset_complex;
40 smpl_t threshold                      = 0.3;
41 smpl_t silence                        = -90.;
42 uint_t buffer_size                    = 512; //1024;
43 uint_t overlap_size                   = 256; //512;
44 uint_t channels                       = 1;
45 uint_t samplerate                     = 44100;
46
47
48 aubio_sndfile_t * file = NULL;
49 aubio_sndfile_t * fileout = NULL;
50
51 aubio_pvoc_t * pv;
52 fvec_t * ibuf;
53 fvec_t * obuf;
54 cvec_t * fftgrain;
55 fvec_t * woodblock;
56 aubio_onsetdetection_t *o;
57 aubio_onsetdetection_t *o2;
58 fvec_t *onset;
59 fvec_t *onset2;
60 int isonset = 0;
61 aubio_pickpeak_t * parms;
62
63
64 /* pitch objects */
65 smpl_t pitch               = 0.;
66 aubio_pitchdetection_t * pitchdet;
67 aubio_pitchdetection_type type_pitch = aubio_pitch_yinfft; // aubio_pitch_mcomb
68 aubio_pitchdetection_mode mode_pitch = aubio_pitchm_freq;
69 uint_t median         = 6;
70
71 fvec_t * note_buffer  = NULL;
72 fvec_t * note_buffer2 = NULL;
73 smpl_t curlevel       = 0.;
74 smpl_t maxonset       = 0.;
75
76 /* midi objects */
77 aubio_midi_player_t * mplay; 
78 aubio_midi_driver_t * mdriver; 
79 aubio_midi_event_t  * event;
80
81 smpl_t curnote = 0.;
82 smpl_t newnote = 0.;
83 uint_t isready = 0;
84
85
86
87 /* badly redeclare some things */
88 aubio_onsetdetection_type type_onset;
89 smpl_t threshold;
90 smpl_t averaging;
91 const char * prog_name;
92
93 void usage (FILE * stream, int exit_code)
94 {
95         fprintf(stream, "usage: %s [ options ] \n", prog_name);
96         fprintf(stream, 
97                         "       -h      --help          Display this message.\n"
98                         "       -v      --verbose       Be verbose.\n"
99                         "       -j      --jack          Use Jack.\n"
100                         "       -o      --output        Output type.\n"
101                         "       -i      --input         Input type.\n"
102                         "       -O      --onset         Select onset detection algorithm.\n"
103                         "       -t      --threshold     Set onset detection threshold.\n"
104                         "       -s      --silence       Select silence threshold.\n"
105                         "       -p      --pitch         Select pitch detection algorithm.\n"
106                         "       -H      --hopsize       Set hopsize.\n"
107                         "       -a      --averaging     Use averaging.\n"
108                );
109         exit(exit_code);
110 }
111
112 int parse_args (int argc, char **argv) {
113         const char *options = "hvjo:i:O:t:s:p:H:a";
114         int next_option;
115         struct option long_options[] =
116         {
117                 {"help"     , 0, NULL, 'h'},
118                 {"verbose"  , 0, NULL, 'v'},
119                 {"jack"     , 0, NULL, 'j'},
120                 {"output"   , 1, NULL, 'o'},
121                 {"input"    , 1, NULL, 'i'},
122                 {"onset"    , 1, NULL, 'O'},
123                 {"threshold", 1, NULL, 't'},
124                 {"silence"  , 1, NULL, 's'},
125                 {"pitch"    , 1, NULL, 'p'},
126                 {"averaging", 0, NULL, 'a'},
127                 {"hopsize",   1, NULL, 'H'},
128                 {NULL       , 0, NULL, 0}
129         };
130 #ifdef LASH_SUPPORT
131         lash_args = lash_extract_args(&argc, &argv);
132 #endif /* LASH_SUPPORT */
133         prog_name = argv[0];
134         if( argc < 1 ) {
135                 usage (stderr, 1);
136                 return -1;
137         }
138         do {
139                 next_option = getopt_long (argc, argv, options, 
140                                 long_options, NULL);
141                 switch (next_option) {
142                         case 'o':
143                                 output_filename = optarg;
144                                 break;
145                         case 'i':
146                                 input_filename = optarg;
147                                 break;
148                         case 'h': /* help */
149                                 usage (stdout, 0);
150                                 return -1;
151                         case 'v': /* verbose */
152                                 verbose = 1;
153                                 break;
154                         case 'j':
155                                 usejack = 1;
156                                 break;
157                         case 'O':   /*onset type*/
158                                 if (strcmp(optarg,"energy") == 0) 
159                                         type_onset = aubio_onset_energy;
160                                 else if (strcmp(optarg,"specdiff") == 0) 
161                                         type_onset = aubio_onset_specdiff;
162                                 else if (strcmp(optarg,"hfc") == 0) 
163                                         type_onset = aubio_onset_hfc;
164                                 else if (strcmp(optarg,"complexdomain") == 0) 
165                                         type_onset = aubio_onset_complex;
166                                 else if (strcmp(optarg,"complex") == 0) 
167                                         type_onset = aubio_onset_complex;
168                                 else if (strcmp(optarg,"phase") == 0) 
169                                         type_onset = aubio_onset_phase;
170                                 else if (strcmp(optarg,"mkl") == 0) 
171                                         type_onset = aubio_onset_mkl;
172                                 else if (strcmp(optarg,"kl") == 0) 
173                                         type_onset = aubio_onset_kl;
174                                 else {
175                                         errmsg("unknown onset type.\n");
176                                         abort();
177                                 }
178                                 usedoubled = 0;
179                                 break;
180                         case 's':   /* threshold value for onset */
181                                 silence = (smpl_t)atof(optarg);
182                                 break;
183                         case 't':   /* threshold value for onset */
184                                 threshold = (smpl_t)atof(optarg);
185                                 /*
186                                    if (!isfinite(threshold)) {
187                                    debug("could not get threshold.\n");
188                                    abort();
189                                    }
190                                    */
191                                 break;
192                         case 'p':
193                                 if (strcmp(optarg,"mcomb") == 0) 
194                                         type_pitch = aubio_pitch_mcomb;
195                                 else if (strcmp(optarg,"yinfft") == 0) 
196                                         type_pitch = aubio_pitch_yin;
197                                 else if (strcmp(optarg,"yin") == 0) 
198                                         type_pitch = aubio_pitch_yin;
199                                 else if (strcmp(optarg,"schmitt") == 0) 
200                                         type_pitch = aubio_pitch_schmitt;
201                                 else if (strcmp(optarg,"fcomb") == 0) 
202                                         type_pitch = aubio_pitch_fcomb;
203                                 else {
204                                         errmsg("unknown pitch type.\n");
205                                         abort();
206                                 }
207                                 break;
208                         case 'a':
209                                 averaging = 1;
210                                 break; 
211                         case 'H':
212                                 overlap_size = atoi(optarg);
213                                 break;
214                         case '?': /* unknown options */
215                                 usage(stderr, 1);
216                                 break;
217                         case -1: /* done with options */
218                                 break;
219                         default: /*something else unexpected */
220                                 abort ();
221                 }
222         }
223         while (next_option != -1);
224
225         if (input_filename != NULL) {
226                 debug ("Input file : %s\n", input_filename );
227         } else if (input_filename != NULL && output_filename != NULL) {
228                 debug ("Input file : %s\n", input_filename );
229                 debug ("Output file : %s\n", output_filename );
230         } else {
231                 if (JACK_SUPPORT)
232                 {
233                         debug ("Jack input output\n");
234                         usejack = 1;
235                 } else {
236                         debug ("Error: Could not switch to jack mode\n   aubio was compiled without jack support\n");
237                         exit(1);
238                 }
239         }
240
241         return 0;
242 }
243
244 void examples_common_init(int argc,char ** argv) {
245
246
247   aubio_sndfile_t * onsetfile = NULL;
248   /* parse command line arguments */
249   parse_args(argc, argv);
250
251   woodblock = new_fvec(buffer_size,1);
252   if (output_filename || usejack) {
253           /* dummy assignement to keep egcs happy */
254           isonset = (onsetfile = new_aubio_sndfile_ro(onset_filename)) ||
255                   (onsetfile = new_aubio_sndfile_ro("sounds/woodblock.aiff")) ||
256                   (onsetfile = new_aubio_sndfile_ro("../sounds/woodblock.aiff"));
257           if (onsetfile == NULL) {
258             outmsg("Could not find woodblock.aiff\n");
259             exit(1);
260           }
261   }
262   if (onsetfile) {
263           /* read the output sound once */
264           aubio_sndfile_read(onsetfile, overlap_size, woodblock);
265   }
266
267   if(!usejack)
268   {
269     debug("Opening files ...\n");
270     file = new_aubio_sndfile_ro (input_filename);
271     if (file == NULL) {
272       outmsg("Could not open input file %s.\n", input_filename);
273       exit(1);
274     }
275     if (verbose) aubio_sndfile_info(file);
276     channels = aubio_sndfile_channels(file);
277     samplerate = aubio_sndfile_samplerate(file);
278     if (output_filename != NULL)
279       fileout = new_aubio_sndfile_wo(file, output_filename);
280   }
281 #ifdef LASH_SUPPORT
282   else {
283     aubio_lash_client = lash_init(lash_args, argv[0],
284         LASH_Config_Data_Set | LASH_Terminal,
285         LASH_PROTOCOL(2, 0));
286     if (!aubio_lash_client) {
287       fprintf(stderr, "%s: could not initialise lash\n", __FUNCTION__);
288     }
289     /* tell the lash server our client id */
290     if (lash_enabled(aubio_lash_client)) {
291       lash_event_t * event = (lash_event_t *)lash_event_new_with_type(LASH_Client_Name);
292       lash_event_set_string(event, "aubio");
293       lash_send_event(aubio_lash_client, event);
294       pthread_create(&lash_thread, NULL, lash_thread_main, NULL);
295     }
296   }
297 #endif /* LASH_SUPPORT */
298
299   ibuf      = new_fvec(overlap_size, channels);
300   obuf      = new_fvec(overlap_size, channels);
301   fftgrain  = new_cvec(buffer_size, channels);
302
303   if (usepitch) {
304     pitchdet = new_aubio_pitchdetection(buffer_size*4, 
305         overlap_size, channels, samplerate, type_pitch, mode_pitch);
306     aubio_pitchdetection_set_yinthresh(pitchdet, 0.7);
307
308     if (median) {
309       note_buffer = new_fvec(median, 1);
310       note_buffer2= new_fvec(median, 1);
311     }
312   }
313   /* phase vocoder */
314   pv = new_aubio_pvoc(buffer_size, overlap_size, channels);
315   /* onsets */
316   parms = new_aubio_peakpicker(threshold);
317   o = new_aubio_onsetdetection(type_onset,buffer_size,channels);
318   onset = new_fvec(1, channels);
319   if (usedoubled)    {
320     o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels);
321     onset2 = new_fvec(1 , channels);
322   }
323
324 }
325
326
327 void examples_common_del(void){
328   if (usepitch) {
329           send_noteon(curnote,0);
330           del_aubio_pitchdetection(pitchdet);
331           if (median) {
332                   del_fvec(note_buffer);
333                   del_fvec(note_buffer2);
334           }
335   }
336   if (usedoubled)    {
337     del_aubio_onsetdetection(o2);
338     del_fvec(onset2);
339   }
340   del_aubio_onsetdetection(o);
341   del_aubio_peakpicker(parms);
342   del_aubio_pvoc(pv);
343   del_fvec(obuf);
344   del_fvec(ibuf);
345   del_cvec(fftgrain);
346   del_fvec(onset);
347   del_fvec(woodblock);
348   aubio_cleanup();
349 }
350
351 void examples_common_process(aubio_process_func_t process_func, aubio_print_func_t print ){
352   if(usejack) {
353 #if JACK_SUPPORT
354     aubio_jack_t * jack_setup;
355     debug("Jack init ...\n");
356     jack_setup = new_aubio_jack(channels, channels,
357           (aubio_process_func_t)process_func);
358     if (usepitch) {
359             debug("Midi init ...\n");
360             mplay = new_aubio_midi_player();
361             mdriver = new_aubio_midi_driver("alsa_seq",
362                             (handle_midi_event_func_t)aubio_midi_send_event, mplay);
363             event = new_aubio_midi_event();
364     }
365     debug("Jack activation ...\n");
366     aubio_jack_activate(jack_setup);
367     debug("Processing (Ctrl+C to quit) ...\n");
368     pause();
369     aubio_jack_close(jack_setup);
370     if (usepitch) {
371             send_noteon(curnote,0);
372             del_aubio_midi_driver(mdriver);
373     }
374 #else
375     usage(stderr, 1);
376     outmsg("Compiled without jack output, exiting.\n");
377 #endif
378
379   } else {
380     /* phasevoc */
381     debug("Processing ...\n");
382
383     frames = 0;
384
385     while ((signed)overlap_size == aubio_sndfile_read(file, overlap_size, ibuf))
386     {
387       isonset=0;
388       process_func(ibuf->data, obuf->data, overlap_size);
389       print(); 
390       if (output_filename != NULL) {
391         aubio_sndfile_write(fileout,overlap_size,obuf);
392       }
393       frames++;
394     }
395
396     debug("Processed %d frames of %d samples.\n", frames, buffer_size);
397     del_aubio_sndfile(file);
398
399     if (output_filename != NULL)
400       del_aubio_sndfile(fileout);
401
402   }
403 }
404
405
406
407 void send_noteon(int pitch, int velo)
408 {
409     smpl_t mpitch = floor(aubio_freqtomidi(pitch)+.5);
410     /* we should check if we use midi here, not jack */
411 #if ALSA_SUPPORT
412     if (usejack) {
413         if (velo==0) {
414             aubio_midi_event_set_type(event,NOTE_OFF);
415         } else {
416             aubio_midi_event_set_type(event,NOTE_ON);
417         }
418         aubio_midi_event_set_channel(event,0);
419         aubio_midi_event_set_pitch(event,mpitch);
420         aubio_midi_event_set_velocity(event,velo);
421         aubio_midi_direct_output(mdriver,event);
422     } else 
423 #endif
424     if (!verbose)
425     {
426         if (velo==0) {
427             outmsg("%f\n",frames*overlap_size/(float)samplerate);
428         } else {
429             outmsg("%f\t%f\t", mpitch,
430                         frames*overlap_size/(float)samplerate);
431         }
432     }
433 }
434
435
436 void note_append(fvec_t * note_buffer, smpl_t curnote) {
437   uint_t i = 0;
438   for (i = 0; i < note_buffer->length - 1; i++) { 
439       note_buffer->data[0][i] = note_buffer->data[0][i+1];
440   }
441   note_buffer->data[0][note_buffer->length - 1] = curnote;
442   return;
443 }
444
445 uint_t get_note(fvec_t *note_buffer, fvec_t *note_buffer2){
446   uint_t i = 0;
447   for (i = 0; i < note_buffer->length; i++) { 
448       note_buffer2->data[0][i] = note_buffer->data[0][i];
449   }
450   return vec_median(note_buffer2);
451 }
452
453 #if LASH_SUPPORT
454
455 void * lash_thread_main(void *data)
456 {
457         printf("LASH thread running\n");
458
459         while (!lash_main())
460                 usleep(1000);
461
462         printf("LASH thread finished\n");
463         return NULL;
464 }
465
466 int lash_main(void) {
467         lash_event_t *lash_event;
468         lash_config_t *lash_config;
469
470         while ((lash_event = lash_get_event(aubio_lash_client))) {
471                 switch (lash_event_get_type(lash_event)) {
472                 case LASH_Quit:
473                         lash_event_destroy(lash_event);
474       exit(1);
475       return 1;
476                 case LASH_Restore_Data_Set:
477                         lash_send_event(aubio_lash_client, lash_event);
478                         break;
479                 case LASH_Save_Data_Set:
480                         save_data();
481                         lash_send_event(aubio_lash_client, lash_event);
482                         break;
483                 case LASH_Server_Lost:
484                         return 1;
485                 default:
486                         printf("%s: received unknown LASH event of type %d",
487                                    __FUNCTION__, lash_event_get_type(lash_event));
488                         lash_event_destroy(lash_event);
489       break;
490                 }
491         }
492
493         while ((lash_config = lash_get_config(aubio_lash_client))) {
494                 restore_data(lash_config);
495                 lash_config_destroy(lash_config);
496         }
497
498         return 0;
499 }
500
501 void save_data() {
502         lash_config_t *lash_config;
503
504         lash_config = lash_config_new_with_key("threshold");
505         lash_config_set_value_double(lash_config, threshold);
506         lash_send_config(aubio_lash_client, lash_config);
507
508 }
509
510 void restore_data(lash_config_t * lash_config) {
511         const char *lash_key;
512
513         lash_key = lash_config_get_key(lash_config);
514
515         if (strcmp(lash_key, "threshold") == 0) {
516                 threshold = lash_config_get_value_double(lash_config);
517                 return;
518         }
519
520 }
521
522 #endif /* LASH_SUPPORT */
523