source: examples/jackio.c @ ab7b1b7

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

examples/: include config.h

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