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