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