source: examples/jackio.c @ ed73bc6

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

ext/, examples/, swig/, python/, tests/: remove libaubioext, make libsamplerate optional

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