src/types.h: add some documentation, use HAVE_AUBIO_DOUBLE, not AUBIO_SINGLE_PRECISION
[aubio.git] / ext / 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
23 #if HAVE_JACK
24 #include "aubio_priv.h"
25 #include "jackio.h"
26
27 typedef jack_default_audio_sample_t jack_sample_t;
28
29 #if HAVE_AUBIO_DOUBLE
30 #define AUBIO_JACK_MAX_FRAMES 4096
31 #define AUBIO_JACK_NEEDS_CONVERSION
32 #endif
33
34 #define RINGBUFFER_SIZE 1024*sizeof(jack_midi_event_t)
35
36 /**
37  * jack device structure 
38  */
39 struct _aubio_jack_t
40 {
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;
51 #ifdef AUBIO_JACK_NEEDS_CONVERSION
52   /** converted jack input buffer */
53   smpl_t **sibufs;
54   /** converted jack output buffer */
55   smpl_t **sobufs;
56 #endif
57   /** jack input audio channels */
58   uint_t ichan;
59   /** jack output audio channels */
60   uint_t ochan;
61   /** jack input midi channels */
62   uint_t imidichan;
63   /** jack output midi channels */
64   uint_t omidichan;
65   /** midi output ringbuffer */
66   jack_ringbuffer_t *midi_out_ring;
67   /** jack samplerate (Hz) */
68   uint_t samplerate;
69   /** jack processing function */
70   aubio_process_func_t callback;
71 };
72
73 /* static memory management */
74 static aubio_jack_t *aubio_jack_alloc (uint_t ichan, uint_t ochan,
75     uint_t imidichan, uint_t omidichan);
76 static uint_t aubio_jack_free (aubio_jack_t * jack_setup);
77 /* jack callback functions */
78 static int aubio_jack_process (jack_nframes_t nframes, void *arg);
79 static void aubio_jack_shutdown (void *arg);
80
81 aubio_jack_t *
82 new_aubio_jack (uint_t ichan, uint_t ochan,
83     uint_t imidichan, uint_t omidichan, aubio_process_func_t callback)
84 {
85   aubio_jack_t *jack_setup = aubio_jack_alloc (ichan, ochan,
86       imidichan, omidichan);
87   uint_t i;
88   char *client_name = "aubio";
89   char *jack_port_type;
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");
94     AUBIO_QUIT (AUBIO_FAIL);
95   }
96
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
108   /* set callbacks */
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);
113
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     }
123     if ((jack_setup->oports[i] =
124             jack_port_register (jack_setup->client, name,
125                 jack_port_type, JackPortIsOutput, 0)) == 0) {
126       goto beach;
127     }
128     AUBIO_DBG ("%s:%s\n", client_name, name);
129   }
130
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     }
140     if ((jack_setup->iports[i] =
141             jack_port_register (jack_setup->client, name,
142                 jack_port_type, JackPortIsInput, 0)) == 0) {
143       goto beach;
144     }
145     AUBIO_DBG ("%s:%s\n", client_name, name);
146   }
147
148   /* set processing callback */
149   jack_setup->callback = callback;
150   return jack_setup;
151
152 beach:
153   AUBIO_ERR ("failed registering port \"%s:%s\"!\n", client_name, name);
154   jack_client_close (jack_setup->client);
155   AUBIO_QUIT (AUBIO_FAIL);
156 }
157
158 uint_t
159 aubio_jack_activate (aubio_jack_t * jack_setup)
160 {
161   /* get sample rate */
162   jack_setup->samplerate = jack_get_sample_rate (jack_setup->client);
163   /* actual jack process activation */
164   if (jack_activate (jack_setup->client)) {
165     AUBIO_ERR ("jack client activation failed");
166     return 1;
167   }
168   return 0;
169 }
170
171 void
172 aubio_jack_close (aubio_jack_t * jack_setup)
173 {
174   /* bug : should disconnect all ports first */
175   jack_client_close (jack_setup->client);
176   aubio_jack_free (jack_setup);
177 }
178
179 /* memory management */
180 static aubio_jack_t *
181 aubio_jack_alloc (uint_t ichan, uint_t ochan,
182     uint_t imidichan, uint_t omidichan)
183 {
184   aubio_jack_t *jack_setup = AUBIO_NEW (aubio_jack_t);
185   jack_setup->ichan = ichan;
186   jack_setup->ochan = ochan;
187   jack_setup->imidichan = imidichan;
188   jack_setup->omidichan = omidichan;
189   jack_setup->oports = AUBIO_ARRAY (jack_port_t *, ichan + imidichan);
190   jack_setup->iports = AUBIO_ARRAY (jack_port_t *, ochan + omidichan);
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
194   /* allocate arrays for data conversion */
195   jack_setup->sibufs = AUBIO_ARRAY (smpl_t *, ichan);
196   uint_t i;
197   for (i = 0; i < ichan; i++) {
198     jack_setup->sibufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
199   }
200   jack_setup->sobufs = AUBIO_ARRAY (smpl_t *, ochan);
201   for (i = 0; i < ochan; i++) {
202     jack_setup->sobufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
203   }
204 #endif
205   return jack_setup;
206 }
207
208 static uint_t
209 aubio_jack_free (aubio_jack_t * jack_setup)
210 {
211   if (jack_setup->omidichan && jack_setup->midi_out_ring) {
212     jack_ringbuffer_free (jack_setup->midi_out_ring);
213   }
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);
219   return AUBIO_OK;
220 }
221
222 /* jack callback functions */
223 static void
224 aubio_jack_shutdown (void *arg UNUSED)
225 {
226   AUBIO_ERR ("jack shutdown\n");
227   AUBIO_QUIT (AUBIO_OK);
228 }
229
230 static void process_midi_output (aubio_jack_t * dev, jack_nframes_t nframes);
231
232 static int
233 aubio_jack_process (jack_nframes_t nframes, void *arg)
234 {
235   aubio_jack_t *dev = (aubio_jack_t *) arg;
236   uint_t i;
237   for (i = 0; i < dev->ichan; i++) {
238     /* get readable input */
239     dev->ibufs[i] =
240         (jack_sample_t *) jack_port_get_buffer (dev->iports[i], nframes);
241   }
242   for (i = 0; i < dev->ochan; i++) {
243     /* get writable output */
244     dev->obufs[i] =
245         (jack_sample_t *) jack_port_get_buffer (dev->oports[i], nframes);
246   }
247 #ifndef AUBIO_JACK_NEEDS_CONVERSION
248   dev->callback (dev->ibufs, dev->obufs, nframes);
249 #else
250   uint_t j;
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];
254     }
255   }
256   dev->callback (dev->sibufs, dev->sobufs, nframes);
257   for (j = 0; j < MIN (nframes, AUBIO_JACK_MAX_FRAMES); j++) {
258     for (i = 0; i < dev->ochan; i++) {
259       dev->obufs[i][j] = (jack_sample_t) dev->sobufs[i][j];
260     }
261   }
262 #endif
263
264   /* now process midi stuff */
265   if (dev->omidichan) {
266     process_midi_output (dev, nframes);
267   }
268
269   return 0;
270 }
271
272 void
273 aubio_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
290 static void
291 process_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 }
341
342 #endif /* HAVE_JACK */