source: examples/utils.c @ b4f5967

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since b4f5967 was b4f5967, checked in by Paul Brossier <piem@piem.org>, 11 years ago

src/onset: use a string to set onset mode, keeping onset types enum private, update everywhere onsets are used

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