2c0bacbc5e7dc4c465286414d40c5984f39c366c
[aubio.git] / examples / utils.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 /**
22
23   This file includes some tools common to all examples. Code specific to the
24   algorithm performed by each program should go in the source file of that
25   program instead.
26
27 */
28
29 #include "utils.h"
30
31 #ifdef HAVE_LASH
32 #include <lash/lash.h>
33 #include <pthread.h>
34 lash_client_t *aubio_lash_client;
35 lash_args_t *lash_args;
36 void *lash_thread_main (void *data);
37 int lash_main (void);
38 void save_data (void);
39 void restore_data (lash_config_t * lash_config);
40 pthread_t lash_thread;
41 #endif /* HAVE_LASH */
42
43 /* settings */
44 const char *sink_uri = NULL;
45 const char *source_uri = NULL;
46 int frames = 0;
47 int verbose = 0;
48 int usejack = 0;
49 int frames_delay = 0;
50
51
52 char_t * pitch_unit = "default";
53 char_t * pitch_mode = "default";
54
55 /* energy,specdiff,hfc,complexdomain,phase */
56 char_t * onset_mode = "default";
57 smpl_t threshold = 0.0;         // leave unset, only set as asked 
58 smpl_t silence = -90.;
59 uint_t buffer_size = 512;       //1024;
60 uint_t overlap_size = 256;      //512;
61 uint_t samplerate = 44100;
62
63 aubio_source_t *this_source = NULL;
64 aubio_sink_t *this_sink = NULL;
65
66 fvec_t *ibuf;
67 fvec_t *obuf;
68 fvec_t *woodblock;
69
70 /* badly redeclare some things */
71 smpl_t threshold;
72 smpl_t averaging;
73 const char *prog_name;
74
75 void flush_process (aubio_process_func_t process_func,
76     aubio_print_func_t print);
77
78 void
79 usage (FILE * stream, int exit_code)
80 {
81   fprintf (stream, "usage: %s [ options ] \n", prog_name);
82   fprintf (stream,
83       "       -h      --help          Display this message.\n"
84       "       -v      --verbose       Be verbose.\n"
85       "       -j      --jack          Use Jack.\n"
86       "       -o      --output        Output type.\n"
87       "       -i      --input         Input type.\n"
88       "       -O      --onset         Select onset detection algorithm.\n"
89       "       -t      --threshold     Set onset detection threshold.\n"
90       "       -s      --silence       Select silence threshold.\n"
91       "       -p      --pitch         Select pitch detection algorithm.\n"
92       "       -B      --bufsize       Set buffer size.\n"
93       "       -H      --hopsize       Set hopsize.\n"
94       "       -a      --averaging     Use averaging.\n");
95   exit (exit_code);
96 }
97
98 int
99 parse_args (int argc, char **argv)
100 {
101   const char *options = "hvjo:i:O:t:s:p:B:H:a";
102   int next_option;
103   struct option long_options[] = {
104     {"help", 0, NULL, 'h'},
105     {"verbose", 0, NULL, 'v'},
106     {"jack", 0, NULL, 'j'},
107     {"output", 1, NULL, 'o'},
108     {"input", 1, NULL, 'i'},
109     {"onset", 1, NULL, 'O'},
110     {"threshold", 1, NULL, 't'},
111     {"silence", 1, NULL, 's'},
112     {"pitch", 1, NULL, 'p'},
113     {"averaging", 0, NULL, 'a'},
114     {"bufsize", 1, NULL, 'B'},
115     {"hopsize", 1, NULL, 'H'},
116     {NULL, 0, NULL, 0}
117   };
118 #ifdef HAVE_LASH
119   lash_args = lash_extract_args (&argc, &argv);
120 #endif /* HAVE_LASH */
121   prog_name = argv[0];
122   if (argc < 1) {
123     usage (stderr, 1);
124     return -1;
125   }
126   do {
127     next_option = getopt_long (argc, argv, options, long_options, NULL);
128     switch (next_option) {
129       case 'o':
130         sink_uri = optarg;
131         break;
132       case 'i':
133         source_uri = optarg;
134         break;
135       case 'h':                /* help */
136         usage (stdout, 0);
137         return -1;
138       case 'v':                /* verbose */
139         verbose = 1;
140         break;
141       case 'j':
142         usejack = 1;
143         break;
144       case 'O':                /*onset type */
145         onset_mode = optarg;
146         break;
147       case 's':                /* silence value for onset */
148         silence = (smpl_t) atof (optarg);
149         break;
150       case 't':                /* threshold value for onset */
151         threshold = (smpl_t) atof (optarg);
152         break;
153       case 'p':
154         pitch_mode = optarg;
155         break;
156       case 'a':
157         averaging = 1;
158         break;
159       case 'B':
160         buffer_size = atoi (optarg);
161         break;
162       case 'H':
163         overlap_size = atoi (optarg);
164         break;
165       case '?':                /* unknown options */
166         usage (stderr, 1);
167         break;
168       case -1:                 /* done with options */
169         break;
170       default:                 /*something else unexpected */
171         fprintf (stderr, "Error parsing option '%c'\n", next_option);
172         abort ();
173     }
174   }
175   while (next_option != -1);
176
177   if ( source_uri == NULL ) {
178     if (argc - optind == 1) {
179       source_uri = argv[optind];
180     } else if ( argc - optind > 1 ) {
181       errmsg ("Error: too many non-option arguments `%s'\n", argv[argc - 1]);
182       usage ( stderr, 1 );
183     }
184   } else if ( argc - optind > 0 ) {
185     errmsg ("Error: extra non-option argument %s\n", argv[optind]);
186     usage ( stderr, 1 );
187   }
188
189   if (source_uri != NULL) {
190     debug ("Input file : %s\n", source_uri);
191   } else if (source_uri != NULL && sink_uri != NULL) {
192     debug ("Input file : %s\n", source_uri);
193     debug ("Output file : %s\n", sink_uri);
194   } else {
195 #if HAVE_JACK
196     debug ("Jack input output\n");
197     usejack = 1;
198 #else
199     errmsg("Error: no arguments given (and no available audio input)\n");
200     usage ( stderr, 1 );
201 #endif
202   }
203
204   return 0;
205 }
206
207 void
208 examples_common_init (int argc, char **argv)
209 {
210
211   /* parse command line arguments */
212   parse_args (argc, argv);
213
214   if (!usejack) {
215     debug ("Opening files ...\n");
216     this_source = new_aubio_source ((char_t*)source_uri, 0, overlap_size);
217     if (this_source == NULL) {
218       outmsg ("Could not open input file %s.\n", source_uri);
219       exit (1);
220     }
221     samplerate = aubio_source_get_samplerate(this_source);
222     if (sink_uri != NULL) {
223       this_sink = new_aubio_sink ((char_t*)sink_uri, samplerate);
224       if (this_sink == NULL) {
225         outmsg ("Could not open output file %s.\n", sink_uri);
226         exit (1);
227       }
228     }
229   }
230 #ifdef HAVE_LASH
231   else {
232     aubio_lash_client = lash_init (lash_args, argv[0],
233         LASH_Config_Data_Set | LASH_Terminal, LASH_PROTOCOL (2, 0));
234     if (!aubio_lash_client) {
235       fprintf (stderr, "%s: could not initialise lash\n", __FUNCTION__);
236     }
237     /* tell the lash server our client id */
238     if (lash_enabled (aubio_lash_client)) {
239       lash_event_t *event =
240           (lash_event_t *) lash_event_new_with_type (LASH_Client_Name);
241       lash_event_set_string (event, "aubio");
242       lash_send_event (aubio_lash_client, event);
243       pthread_create (&lash_thread, NULL, lash_thread_main, NULL);
244     }
245   }
246 #endif /* HAVE_LASH */
247
248   woodblock = new_fvec (overlap_size);
249   //TODO create woodblock sound
250
251   ibuf = new_fvec (overlap_size);
252   obuf = new_fvec (overlap_size);
253
254 }
255
256 void
257 examples_common_del (void)
258 {
259   del_fvec (ibuf);
260   del_fvec (obuf);
261   del_fvec (woodblock);
262   aubio_cleanup ();
263 }
264
265 #if HAVE_JACK
266 aubio_jack_t *jack_setup;
267 #endif
268
269 void
270 examples_common_process (aubio_process_func_t process_func,
271     aubio_print_func_t print)
272 {
273
274   uint_t read = 0;
275   if (usejack) {
276
277 #if HAVE_JACK
278     debug ("Jack init ...\n");
279     jack_setup = new_aubio_jack (1, 1,
280         0, 1, (aubio_process_func_t) process_func);
281     debug ("Jack activation ...\n");
282     aubio_jack_activate (jack_setup);
283     debug ("Processing (Ctrl+C to quit) ...\n");
284     pause ();
285     aubio_jack_close (jack_setup);
286 #else
287     usage (stderr, 1);
288     outmsg ("Compiled without jack output, exiting.\n");
289 #endif
290
291   } else {
292     /* phasevoc */
293     debug ("Processing ...\n");
294
295     frames = 0;
296
297     do {
298       aubio_source_do (this_source, ibuf, &read);
299       process_func (&ibuf->data, &obuf->data, overlap_size);
300       print ();
301       if (this_sink) {
302         aubio_sink_do (this_sink, obuf, overlap_size);
303       }
304       frames++;
305     } while (read == overlap_size);
306
307     debug ("Processed %d frames of %d samples.\n", frames, buffer_size);
308
309     flush_process (process_func, print);
310     del_aubio_source (this_source);
311     del_aubio_sink   (this_sink);
312
313   }
314 }
315
316 void
317 flush_process (aubio_process_func_t process_func, aubio_print_func_t print)
318 {
319   uint_t i;
320   fvec_zeros(obuf);
321   for (i = 0; (signed) i < frames_delay; i++) {
322     process_func (&ibuf->data, &obuf->data, overlap_size);
323     print ();
324   }
325 }
326
327 void
328 send_noteon (int pitch, int velo)
329 {
330   smpl_t mpitch = floor (aubio_freqtomidi (pitch) + .5);
331 #if HAVE_JACK
332   jack_midi_event_t ev;
333   ev.size = 3;
334   ev.buffer = malloc (3 * sizeof (jack_midi_data_t)); // FIXME
335   ev.time = 0;
336   if (usejack) {
337     ev.buffer[2] = velo;
338     ev.buffer[1] = mpitch;
339     if (velo == 0) {
340       ev.buffer[0] = 0x80;      /* note off */
341     } else {
342       ev.buffer[0] = 0x90;      /* note on */
343     }
344     aubio_jack_midi_event_write (jack_setup, (jack_midi_event_t *) & ev);
345   } else
346 #endif
347   if (!verbose) {
348     if (velo == 0) {
349       outmsg ("%f\n", frames * overlap_size / (float) samplerate);
350     } else {
351       outmsg ("%f\t%f\t", mpitch, frames * overlap_size / (float) samplerate);
352     }
353   }
354 }
355
356
357 #if HAVE_LASH
358
359 void *
360 lash_thread_main (void *data __attribute__ ((unused)))
361 {
362   printf ("LASH thread running\n");
363
364   while (!lash_main ())
365     usleep (1000);
366
367   printf ("LASH thread finished\n");
368   return NULL;
369 }
370
371 int
372 lash_main (void)
373 {
374   lash_event_t *lash_event;
375   lash_config_t *lash_config;
376
377   while ((lash_event = lash_get_event (aubio_lash_client))) {
378     switch (lash_event_get_type (lash_event)) {
379       case LASH_Quit:
380         lash_event_destroy (lash_event);
381         exit (1);
382         return 1;
383       case LASH_Restore_Data_Set:
384         lash_send_event (aubio_lash_client, lash_event);
385         break;
386       case LASH_Save_Data_Set:
387         save_data ();
388         lash_send_event (aubio_lash_client, lash_event);
389         break;
390       case LASH_Server_Lost:
391         return 1;
392       default:
393         printf ("%s: received unknown LASH event of type %d",
394             __FUNCTION__, lash_event_get_type (lash_event));
395         lash_event_destroy (lash_event);
396         break;
397     }
398   }
399
400   while ((lash_config = lash_get_config (aubio_lash_client))) {
401     restore_data (lash_config);
402     lash_config_destroy (lash_config);
403   }
404
405   return 0;
406 }
407
408 void
409 save_data ()
410 {
411   lash_config_t *lash_config;
412
413   lash_config = lash_config_new_with_key ("threshold");
414   lash_config_set_value_double (lash_config, threshold);
415   lash_send_config (aubio_lash_client, lash_config);
416
417 }
418
419 void
420 restore_data (lash_config_t * lash_config)
421 {
422   const char *lash_key;
423
424   lash_key = lash_config_get_key (lash_config);
425
426   if (strcmp (lash_key, "threshold") == 0) {
427     threshold = lash_config_get_value_double (lash_config);
428     return;
429   }
430
431 }
432
433 #endif /* HAVE_LASH */