[tests] add run_on_default_source_and_sink helper
[aubio.git] / examples / jackio.c
1 /*
2   Copyright (C) 2003-2013 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 #ifdef HAVE_JACK
25 #include "utils.h" // for aubio_process_func_t
26 #include "jackio.h"
27 #include "aubio_priv.h"
28
29 typedef jack_default_audio_sample_t jack_sample_t;
30
31 #if HAVE_AUBIO_DOUBLE
32 #define AUBIO_JACK_MAX_FRAMES 4096
33 #define AUBIO_JACK_NEEDS_CONVERSION
34 #endif
35
36 #define RINGBUFFER_SIZE 1024*sizeof(jack_midi_event_t)
37
38 /**
39  * jack device structure
40  */
41 struct _aubio_jack_t
42 {
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;
53 #ifdef AUBIO_JACK_NEEDS_CONVERSION
54   /** converted jack input buffer */
55   smpl_t **sibufs;
56   /** converted jack output buffer */
57   smpl_t **sobufs;
58 #endif
59   /** jack input audio channels */
60   uint_t ichan;
61   /** jack output audio channels */
62   uint_t ochan;
63   /** jack input midi channels */
64   uint_t imidichan;
65   /** jack output midi channels */
66   uint_t omidichan;
67   /** midi output ringbuffer */
68   jack_ringbuffer_t *midi_out_ring;
69   /** jack samplerate (Hz) */
70   uint_t samplerate;
71   /** jack processing function */
72   aubio_process_func_t callback;
73   /** internal fvec */
74   fvec_t *ibuf;
75   fvec_t *obuf;
76   uint_t hop_size;
77   int pos;
78 };
79
80 /* static memory management */
81 static aubio_jack_t *aubio_jack_alloc (uint_t ichan, uint_t ochan,
82     uint_t imidichan, uint_t omidichan);
83 /* jack callback functions */
84 static int aubio_jack_process (jack_nframes_t nframes, void *arg);
85 static void aubio_jack_shutdown (void *arg);
86
87 aubio_jack_t *
88 new_aubio_jack (uint_t hop_size, uint_t ichan, uint_t ochan,
89     uint_t imidichan, uint_t omidichan)
90 {
91   aubio_jack_t *jack_setup = aubio_jack_alloc (ichan, ochan,
92       imidichan, omidichan);
93   uint_t i;
94   char *client_name = "aubio";
95   char *jack_port_type;
96   char name[64];
97   /* initial jack client setup */
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) {
101     AUBIO_ERR ("jack server not running?\n");
102     AUBIO_QUIT (AUBIO_FAIL);
103   }
104
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
116   /* set callbacks */
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);
121
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     }
131     if ((jack_setup->oports[i] =
132             jack_port_register (jack_setup->client, name,
133                 jack_port_type, JackPortIsOutput, 0)) == 0) {
134       goto beach;
135     }
136     AUBIO_DBG ("%s:%s\n", client_name, name);
137   }
138
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     }
148     if ((jack_setup->iports[i] =
149             jack_port_register (jack_setup->client, name,
150                 jack_port_type, JackPortIsInput, 0)) == 0) {
151       goto beach;
152     }
153     AUBIO_DBG ("%s:%s\n", client_name, name);
154   }
155
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;
163   return jack_setup;
164
165 beach:
166   AUBIO_ERR ("failed registering port \"%s:%s\"!\n", client_name, name);
167   jack_client_close (jack_setup->client);
168   AUBIO_QUIT (AUBIO_FAIL);
169 }
170
171 uint_t
172 aubio_jack_get_samplerate (aubio_jack_t * jack_setup) {
173   return jack_setup->samplerate;
174 }
175
176 uint_t
177 aubio_jack_activate (aubio_jack_t * jack_setup, aubio_process_func_t callback)
178 {
179   /* set processing callback */
180   jack_setup->callback = callback;
181   /* actual jack process activation */
182   if (jack_activate (jack_setup->client)) {
183     AUBIO_ERR ("jack client activation failed");
184     return 1;
185   }
186   return 0;
187 }
188
189 void
190 aubio_jack_close (aubio_jack_t * jack_setup)
191 {
192   /* bug : should disconnect all ports first */
193   jack_client_close (jack_setup->client);
194 }
195
196 /* memory management */
197 static aubio_jack_t *
198 aubio_jack_alloc (uint_t ichan, uint_t ochan,
199     uint_t imidichan, uint_t omidichan)
200 {
201   aubio_jack_t *jack_setup = AUBIO_NEW (aubio_jack_t);
202   jack_setup->ichan = ichan;
203   jack_setup->ochan = ochan;
204   jack_setup->imidichan = imidichan;
205   jack_setup->omidichan = omidichan;
206   jack_setup->oports = AUBIO_ARRAY (jack_port_t *, ichan + imidichan);
207   jack_setup->iports = AUBIO_ARRAY (jack_port_t *, ochan + omidichan);
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
211   /* allocate arrays for data conversion */
212   jack_setup->sibufs = AUBIO_ARRAY (smpl_t *, ichan);
213   uint_t i;
214   for (i = 0; i < ichan; i++) {
215     jack_setup->sibufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
216   }
217   jack_setup->sobufs = AUBIO_ARRAY (smpl_t *, ochan);
218   for (i = 0; i < ochan; i++) {
219     jack_setup->sobufs[i] = AUBIO_ARRAY (smpl_t, AUBIO_JACK_MAX_FRAMES);
220   }
221 #endif
222   return jack_setup;
223 }
224
225 void
226 del_aubio_jack (aubio_jack_t * jack_setup)
227 {
228   if (jack_setup->omidichan && jack_setup->midi_out_ring) {
229     jack_ringbuffer_free (jack_setup->midi_out_ring);
230   }
231   del_fvec (jack_setup->ibuf);
232   del_fvec (jack_setup->obuf);
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);
238 }
239
240 /* jack callback functions */
241 static void
242 aubio_jack_shutdown (void *arg UNUSED)
243 {
244   AUBIO_ERR ("jack shutdown\n");
245   AUBIO_QUIT (AUBIO_OK);
246 }
247
248 static void process_midi_output (aubio_jack_t * dev, jack_nframes_t nframes);
249
250 static 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 */
255     output[0][j] = fvec_get_sample(dev->obuf, dev->pos);
256     /* write input to datanew */
257     fvec_set_sample(dev->ibuf, input[0][j], dev->pos);
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
270 static int
271 aubio_jack_process (jack_nframes_t nframes, void *arg)
272 {
273   aubio_jack_t *dev = (aubio_jack_t *) arg;
274   uint_t i;
275   for (i = 0; i < dev->ichan; i++) {
276     /* get readable input */
277     dev->ibufs[i] =
278         (jack_sample_t *) jack_port_get_buffer (dev->iports[i], nframes);
279   }
280   for (i = 0; i < dev->ochan; i++) {
281     /* get writable output */
282     dev->obufs[i] =
283         (jack_sample_t *) jack_port_get_buffer (dev->oports[i], nframes);
284   }
285 #ifndef AUBIO_JACK_NEEDS_CONVERSION
286   block_process(dev, dev->ibufs, dev->obufs, nframes);
287 #else
288   uint_t j;
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];
292     }
293   }
294   block_process(dev, dev->sibufs, dev->sobufs, nframes);
295   for (j = 0; j < MIN (nframes, AUBIO_JACK_MAX_FRAMES); j++) {
296     for (i = 0; i < dev->ochan; i++) {
297       dev->obufs[i][j] = (jack_sample_t) dev->sobufs[i][j];
298     }
299   }
300 #endif
301
302   /* now process midi stuff */
303   if (dev->omidichan) {
304     process_midi_output (dev, nframes);
305   }
306
307   return 0;
308 }
309
310 void
311 aubio_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
328 static void
329 process_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 }
379
380 #endif /* HAVE_JACK */