source: examples/jackio.c @ 466dff3

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 466dff3 was 466dff3, checked in by Paul Brossier <piem@piem.org>, 10 years ago

examples/: large refactoring, improve option management, remove old stuff, move blocking logic to jackio

  • Property mode set to 100644
File size: 10.4 KB
RevLine 
[96fb8ad]1/*
[466dff3]2  Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
[96fb8ad]3
[1274e9f]4  This file is part of aubio.
[96fb8ad]5
[1274e9f]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.
[96fb8ad]10
[1274e9f]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/>.
[96fb8ad]18
19*/
20
[194ef6b]21#include <aubio.h>
[9817026]22#include "config.h"
[194ef6b]23
24#if HAVE_JACK
[96fb8ad]25#include "aubio_priv.h"
26#include "jackio.h"
27
[194ef6b]28typedef jack_default_audio_sample_t jack_sample_t;
29
[46044ed]30#if HAVE_AUBIO_DOUBLE
[194ef6b]31#define AUBIO_JACK_MAX_FRAMES 4096
32#define AUBIO_JACK_NEEDS_CONVERSION
33#endif
[96fb8ad]34
[c201306]35#define RINGBUFFER_SIZE 1024*sizeof(jack_midi_event_t)
36
[96fb8ad]37/**
[466dff3]38 * jack device structure
[96fb8ad]39 */
[1274e9f]40struct _aubio_jack_t
41{
[96fb8ad]42  /** jack client */
43  jack_client_t *client;
44  /** jack output ports */
45  jack_port_t **oports;
46  /** jack input ports */
47  jack_port_t **iports;
48  /** jack input buffer */
49  jack_sample_t **ibufs;
50  /** jack output buffer */
51  jack_sample_t **obufs;
[1274e9f]52#ifdef AUBIO_JACK_NEEDS_CONVERSION
[194ef6b]53  /** converted jack input buffer */
54  smpl_t **sibufs;
55  /** converted jack output buffer */
56  smpl_t **sobufs;
57#endif
[bccac6b]58  /** jack input audio channels */
[96fb8ad]59  uint_t ichan;
[bccac6b]60  /** jack output audio channels */
[96fb8ad]61  uint_t ochan;
[bccac6b]62  /** jack input midi channels */
63  uint_t imidichan;
64  /** jack output midi channels */
65  uint_t omidichan;
[c201306]66  /** midi output ringbuffer */
67  jack_ringbuffer_t *midi_out_ring;
[96fb8ad]68  /** jack samplerate (Hz) */
69  uint_t samplerate;
70  /** jack processing function */
[1274e9f]71  aubio_process_func_t callback;
[466dff3]72  /** internal fvec */
73  fvec_t *ibuf;
74  fvec_t *obuf;
75  uint_t hop_size;
76  int pos;
[96fb8ad]77};
78
79/* static memory management */
[bccac6b]80static aubio_jack_t *aubio_jack_alloc (uint_t ichan, uint_t ochan,
81    uint_t imidichan, uint_t omidichan);
[96fb8ad]82/* jack callback functions */
[1274e9f]83static int aubio_jack_process (jack_nframes_t nframes, void *arg);
[96fb8ad]84static void aubio_jack_shutdown (void *arg);
85
[1274e9f]86aubio_jack_t *
[466dff3]87new_aubio_jack (uint_t hop_size, uint_t ichan, uint_t ochan,
88    uint_t imidichan, uint_t omidichan)
[1274e9f]89{
[bccac6b]90  aubio_jack_t *jack_setup = aubio_jack_alloc (ichan, ochan,
91      imidichan, omidichan);
[96fb8ad]92  uint_t i;
[1274e9f]93  char *client_name = "aubio";
[bccac6b]94  char *jack_port_type;
[96fb8ad]95  char name[64];
96  /* initial jack client setup */
[5bfb0fd]97  jack_options_t options = JackNullOption;
98  jack_status_t *status = NULL;
99  if ((jack_setup->client = jack_client_open (client_name, options, status)) == 0) {
[96fb8ad]100    AUBIO_ERR ("jack server not running?\n");
[1274e9f]101    AUBIO_QUIT (AUBIO_FAIL);
[96fb8ad]102  }
103
[c201306]104  if (jack_setup->omidichan) {
105    jack_setup->midi_out_ring = jack_ringbuffer_create (RINGBUFFER_SIZE);
106
107    if (jack_setup->midi_out_ring == NULL) {
108      AUBIO_ERR ("Failed creating jack midi output ringbuffer.");
109      AUBIO_QUIT (AUBIO_FAIL);
110    }
111
112    jack_ringbuffer_mlock (jack_setup->midi_out_ring);
113  }
114
[96fb8ad]115  /* set callbacks */
[1274e9f]116  jack_set_process_callback (jack_setup->client, aubio_jack_process,
117      (void *) jack_setup);
118  jack_on_shutdown (jack_setup->client, aubio_jack_shutdown,
119      (void *) jack_setup);
[96fb8ad]120
[bccac6b]121  /* register jack output audio and midi ports */
122  for (i = 0; i < ochan + omidichan; i++) {
123    if (i < ochan) {
124      jack_port_type = JACK_DEFAULT_AUDIO_TYPE;
125      AUBIO_SPRINTF (name, "out_%d", i + 1);
126    } else {
127      jack_port_type = JACK_DEFAULT_MIDI_TYPE;
128      AUBIO_SPRINTF (name, "midi_out_%d", i - ochan + 1);
129    }
[1274e9f]130    if ((jack_setup->oports[i] =
131            jack_port_register (jack_setup->client, name,
[bccac6b]132                jack_port_type, JackPortIsOutput, 0)) == 0) {
133      goto beach;
[96fb8ad]134    }
[bccac6b]135    AUBIO_DBG ("%s:%s\n", client_name, name);
[96fb8ad]136  }
137
[bccac6b]138  /* register jack input audio ports */
139  for (i = 0; i < ichan + imidichan; i++) {
140    if (i < ichan) {
141      jack_port_type = JACK_DEFAULT_AUDIO_TYPE;
142      AUBIO_SPRINTF (name, "in_%d", i + 1);
143    } else {
144      jack_port_type = JACK_DEFAULT_MIDI_TYPE;
145      AUBIO_SPRINTF (name, "midi_in_%d", i - ichan + 1);
146    }
[1274e9f]147    if ((jack_setup->iports[i] =
148            jack_port_register (jack_setup->client, name,
[bccac6b]149                jack_port_type, JackPortIsInput, 0)) == 0) {
150      goto beach;
[96fb8ad]151    }
[bccac6b]152    AUBIO_DBG ("%s:%s\n", client_name, name);
[96fb8ad]153  }
154
[466dff3]155  /* get sample rate */
156  jack_setup->samplerate = jack_get_sample_rate (jack_setup->client);
157
158  jack_setup->hop_size = hop_size;
159  jack_setup->ibuf = new_fvec(hop_size);
160  jack_setup->obuf = new_fvec(hop_size);
161  jack_setup->pos = 0;
[96fb8ad]162  return jack_setup;
[bccac6b]163
164beach:
[c201306]165  AUBIO_ERR ("failed registering port \"%s:%s\"!\n", client_name, name);
[bccac6b]166  jack_client_close (jack_setup->client);
167  AUBIO_QUIT (AUBIO_FAIL);
[96fb8ad]168}
169
[1274e9f]170uint_t
[466dff3]171aubio_jack_get_samplerate (aubio_jack_t * jack_setup) {
172  return jack_setup->samplerate;
173}
174
175uint_t
176aubio_jack_activate (aubio_jack_t * jack_setup, aubio_process_func_t callback)
[1274e9f]177{
[466dff3]178  /* set processing callback */
179  jack_setup->callback = callback;
[96fb8ad]180  /* actual jack process activation */
[1274e9f]181  if (jack_activate (jack_setup->client)) {
182    AUBIO_ERR ("jack client activation failed");
[96fb8ad]183    return 1;
184  }
185  return 0;
186}
187
[1274e9f]188void
189aubio_jack_close (aubio_jack_t * jack_setup)
190{
[96fb8ad]191  /* bug : should disconnect all ports first */
[1274e9f]192  jack_client_close (jack_setup->client);
[96fb8ad]193}
194
195/* memory management */
[1274e9f]196static aubio_jack_t *
[bccac6b]197aubio_jack_alloc (uint_t ichan, uint_t ochan,
198    uint_t imidichan, uint_t omidichan)
[1274e9f]199{
200  aubio_jack_t *jack_setup = AUBIO_NEW (aubio_jack_t);
[96fb8ad]201  jack_setup->ichan = ichan;
202  jack_setup->ochan = ochan;
[c201306]203  jack_setup->imidichan = imidichan;
204  jack_setup->omidichan = omidichan;
[bccac6b]205  jack_setup->oports = AUBIO_ARRAY (jack_port_t *, ichan + imidichan);
206  jack_setup->iports = AUBIO_ARRAY (jack_port_t *, ochan + omidichan);
[1274e9f]207  jack_setup->ibufs = AUBIO_ARRAY (jack_sample_t *, ichan);
208  jack_setup->obufs = AUBIO_ARRAY (jack_sample_t *, ochan);
209#ifdef AUBIO_JACK_NEEDS_CONVERSION
[bccac6b]210  /* allocate arrays for data conversion */
[1274e9f]211  jack_setup->sibufs = AUBIO_ARRAY (smpl_t *, ichan);
[194ef6b]212  uint_t i;
213  for (i = 0; i < ichan; i++) {
[1274e9f]214    jack_setup->sibufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
[194ef6b]215  }
[1274e9f]216  jack_setup->sobufs = AUBIO_ARRAY (smpl_t *, ochan);
[194ef6b]217  for (i = 0; i < ochan; i++) {
[1274e9f]218    jack_setup->sobufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
[194ef6b]219  }
220#endif
[96fb8ad]221  return jack_setup;
222}
223
[466dff3]224void
225del_aubio_jack (aubio_jack_t * jack_setup)
[1274e9f]226{
[c201306]227  if (jack_setup->omidichan && jack_setup->midi_out_ring) {
228    jack_ringbuffer_free (jack_setup->midi_out_ring);
229  }
[466dff3]230  del_fvec (jack_setup->ibuf);
231  del_fvec (jack_setup->obuf);
[1274e9f]232  AUBIO_FREE (jack_setup->oports);
233  AUBIO_FREE (jack_setup->iports);
234  AUBIO_FREE (jack_setup->ibufs);
235  AUBIO_FREE (jack_setup->obufs);
236  AUBIO_FREE (jack_setup);
[96fb8ad]237}
238
239/* jack callback functions */
[1274e9f]240static void
241aubio_jack_shutdown (void *arg UNUSED)
242{
243  AUBIO_ERR ("jack shutdown\n");
244  AUBIO_QUIT (AUBIO_OK);
[96fb8ad]245}
246
[c201306]247static void process_midi_output (aubio_jack_t * dev, jack_nframes_t nframes);
248
[466dff3]249static int block_process(aubio_jack_t *dev,
250    smpl_t **input, smpl_t **output, int nframes) {
251  unsigned int j;       /*frames*/
252  for (j=0;j<(unsigned)nframes;j++) {
253    /* put synthnew in output */
254    output[0][j] = fvec_read_sample(dev->obuf, dev->pos);
255    /* write input to datanew */
256    fvec_write_sample(dev->ibuf, input[0][j], dev->pos);
257    /*time for fft*/
258    if (dev->pos == (int)(dev->hop_size) - 1) {
259      /* block loop */
260      dev->callback(dev->ibuf, dev->obuf);
261      /* end of block loop */
262      dev->pos = -1; /* so it will be zero next j loop */
263    }
264    dev->pos++;
265  }
266  return 1;
267}
268
[1274e9f]269static int
270aubio_jack_process (jack_nframes_t nframes, void *arg)
271{
272  aubio_jack_t *dev = (aubio_jack_t *) arg;
[96fb8ad]273  uint_t i;
[1274e9f]274  for (i = 0; i < dev->ichan; i++) {
[96fb8ad]275    /* get readable input */
[1274e9f]276    dev->ibufs[i] =
277        (jack_sample_t *) jack_port_get_buffer (dev->iports[i], nframes);
[58779e3]278  }
279  for (i = 0; i < dev->ochan; i++) {
[96fb8ad]280    /* get writable output */
[1274e9f]281    dev->obufs[i] =
282        (jack_sample_t *) jack_port_get_buffer (dev->oports[i], nframes);
[96fb8ad]283  }
[194ef6b]284#ifndef AUBIO_JACK_NEEDS_CONVERSION
[466dff3]285  block_process(dev, dev->ibufs, dev->obufs, nframes);
[194ef6b]286#else
287  uint_t j;
[1274e9f]288  for (j = 0; j < MIN (nframes, AUBIO_JACK_MAX_FRAMES); j++) {
289    for (i = 0; i < dev->ichan; i++) {
290      dev->sibufs[i][j] = (smpl_t) dev->ibufs[i][j];
[194ef6b]291    }
292  }
[466dff3]293  block_process(dev, dev->sibufs, dev->sobufs, nframes);
[1274e9f]294  for (j = 0; j < MIN (nframes, AUBIO_JACK_MAX_FRAMES); j++) {
[52ecf09]295    for (i = 0; i < dev->ochan; i++) {
[1274e9f]296      dev->obufs[i][j] = (jack_sample_t) dev->sobufs[i][j];
[194ef6b]297    }
298  }
299#endif
[c201306]300
301  /* now process midi stuff */
302  if (dev->omidichan) {
303    process_midi_output (dev, nframes);
304  }
305
[96fb8ad]306  return 0;
307}
308
[c201306]309void
310aubio_jack_midi_event_write (aubio_jack_t * dev, jack_midi_event_t * event)
311{
312  int written;
313
314  if (jack_ringbuffer_write_space (dev->midi_out_ring) < sizeof (*event)) {
315    AUBIO_ERR ("Not enough space to write midi output, midi event lost!\n");
316    return;
317  }
318
319  written = jack_ringbuffer_write (dev->midi_out_ring,
320      (char *) event, sizeof (*event));
321
322  if (written != sizeof (*event)) {
323    AUBIO_WRN ("Call to jack_ringbuffer_write failed, midi event lost! \n");
324  }
325}
326
327static void
328process_midi_output (aubio_jack_t * dev, jack_nframes_t nframes)
329{
330  int read, sendtime;
331  jack_midi_event_t ev;
332  unsigned char *buffer;
333  jack_nframes_t last_frame_time = jack_last_frame_time (dev->client);
334  // TODO for each omidichan
335  void *port_buffer = jack_port_get_buffer (dev->oports[dev->ochan], nframes);
336
337  if (port_buffer == NULL) {
338    AUBIO_WRN ("Failed to get jack midi output port, will not send anything\n");
339    return;
340  }
341
342  jack_midi_clear_buffer (port_buffer);
343
344  // TODO add rate_limit
345
346  while (jack_ringbuffer_read_space (dev->midi_out_ring)) {
347    read = jack_ringbuffer_peek (dev->midi_out_ring, (char *) &ev, sizeof (ev));
348
349    if (read != sizeof (ev)) {
350      AUBIO_WRN ("Short read from the ringbuffer, possible note loss.\n");
351      jack_ringbuffer_read_advance (dev->midi_out_ring, read);
352      continue;
353    }
354
355    sendtime = ev.time + nframes - last_frame_time;
356
357    /* send time is after current period, will do this one later */
358    if (sendtime >= (int) nframes) {
359      break;
360    }
361
362    if (sendtime < 0) {
363      sendtime = 0;
364    }
365
366    jack_ringbuffer_read_advance (dev->midi_out_ring, sizeof (ev));
367
368    buffer = jack_midi_event_reserve (port_buffer, sendtime, ev.size);
369
370    if (buffer == NULL) {
371      AUBIO_WRN ("Call to jack_midi_event_reserve failed, note lost.\n");
372      break;
373    }
374
375    AUBIO_MEMCPY (buffer, ev.buffer, ev.size);
376  }
377}
[96fb8ad]378
[b511fa9]379#endif /* HAVE_JACK */
Note: See TracBrowser for help on using the repository browser.