source: examples/jackio.c @ 3ac1426

feature/crepe_org
Last change on this file since 3ac1426 was 7585822, checked in by Paul Brossier <piem@piem.org>, 9 years ago

src/, examples/: #ifdef HAVE_, not #if HAVE_

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