SphinxBase  5prealpha
ad_jack.c
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 2011 Glenn Pierce. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GLENN PIERCE ``AS IS'' AND
18  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
21  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * ====================================================================
30  *
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include <fcntl.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <limits.h>
44 
45 #include "prim_type.h"
46 #include "ad.h"
47 
48 #include <jack/jack.h>
49 #include <jack/jack.h>
50 #include <jack/ringbuffer.h>
51 
52 #define DEFAULT_DEVICE "system:capture_1"
53 #define BUFFER_SIZE 352800
54 
55 struct ad_rec_s {
56  jack_client_t *client;
57  jack_port_t *input_port;
58  jack_port_t *output_port;
59  jack_ringbuffer_t* rbuffer;
60  jack_default_audio_sample_t* sample_buffer;
61  int32 recording;
62  int32 sps;
63  int32 bps;
64 };
65 
66 /* #define MIC_SPEAKER_PASSTHROUGH_DEBUG */
67 
68 const size_t sample_size = sizeof(jack_default_audio_sample_t);
69 const size_t int16_range_over_two = (-SHRT_MIN + SHRT_MAX) / 2.0;
70 
71 int
72 process (jack_nframes_t nframes, void *arg)
73 {
74  ad_rec_t *handle = (ad_rec_t *) arg;
75 
76  size_t buffer_size = jack_ringbuffer_write_space (handle->rbuffer);
77 
78  jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (handle->input_port, nframes);
79 
80  if (buffer_size <= 0) {
81  fprintf(stderr, "JACK: buffer is full. Deactivating JACK client.\n");
82  return 1;
83  }
84 
85  /* Write to jack ringbuffer which should be thread safe */
86  jack_ringbuffer_write (handle->rbuffer, (char*) in, sample_size * nframes);
87 
88 #ifdef MIC_SPEAKER_PASSTHROUGH_DEBUG
89 
90  jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (handle->output_port, nframes);
91 
92  /* Output mic output to speakers (Just for testing) */
93  memcpy (out, in, sample_size * nframes);
94 
95 #endif
96 
97  return 0;
98 }
99 
100 void
101 error (const char *desc)
102 {
103  fprintf (stderr, "JACK error: %s\n", desc);
104 }
105 
106 void
107 jack_shutdown (void *arg)
108 {
109  exit(1);
110 }
111 
112 int
113 srate (jack_nframes_t nframes, void *arg)
114 
115 {
116  printf ("JACK: The sample rate is now %u/sec\n", nframes);
117  return 0;
118 }
119 
120 ad_rec_t *
121 ad_open_dev(const char *dev, int32 sps)
122 {
123  ad_rec_t *handle;
124  const char **ports;
125 
126  if (dev == NULL) {
127  dev = DEFAULT_DEVICE;
128  }
129 
130  printf("JACK: Setting default device: %s\n", dev);
131 
132  if ((handle = (ad_rec_t *) calloc(1, sizeof(ad_rec_t))) == NULL) {
133  fprintf(stderr, "calloc(%d) failed\n", (int)sizeof(ad_rec_t));
134  abort();
135  }
136 
137  /* Tell the JACK server to call error() whenever it
138  experiences an error.
139  */
140  jack_set_error_function (error);
141 
142  /* Try to become a client of the JACK server */
143  if ((handle->client = jack_client_open ("jack_ad", (jack_options_t)0, NULL)) == 0) {
144  fprintf (stderr, "jack server not running?\n");
145  return NULL;
146  }
147 
148  handle->rbuffer = jack_ringbuffer_create(BUFFER_SIZE);
149  handle->sample_buffer = malloc(BUFFER_SIZE);
150 
151  if(handle->rbuffer == NULL) {
152  fprintf (stderr, "Failed to create jack ringbuffer\n");
153  return NULL;
154  }
155 
156  /* Tell the JACK server to call `process()' whenever
157  there is work to be done.
158  */
159  jack_set_process_callback (handle->client, process, handle);
160 
161  /* Tell the JACK server to call `srate()' whenever
162  the sample rate of the system changes.
163  */
164  jack_set_sample_rate_callback (handle->client, srate, 0);
165 
166  /* Tell the JACK server to call `jack_shutdown()' if
167  it ever shuts down, either entirely, or if it
168  just decides to stop calling us.
169  */
170  jack_on_shutdown (handle->client, jack_shutdown, 0);
171 
172 
173  /* Create the input port */
174  if((handle->input_port = jack_port_register (handle->client, "jack_ad_input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
175  fprintf (stderr, "cannot register input port!\n");
176  return NULL;
177  }
178 
179  if((handle->output_port = jack_port_register (handle->client, "jack_ad_output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsOutput, 0)) == 0) {
180  fprintf (stderr, "cannot register output port!\n");
181  return NULL;
182  }
183 
184  /* Tell the JACK server that we are ready to start */
185  if (jack_activate (handle->client)) {
186  fprintf (stderr, "cannot activate client");
187  return NULL;
188  }
189 
190  /* Connect the ports. Note: you can't do this before
191  the client is activated, because we can't allow
192  connections to be made to clients that aren't
193  running.
194  */
195 
196  if ((ports = jack_get_ports (handle->client, dev, NULL, JackPortIsOutput)) == NULL) {
197  fprintf(stderr, "Cannot find any physical capture ports\n");
198  return NULL;
199  }
200 
201  if (jack_connect (handle->client, ports[0], jack_port_name (handle->input_port))) {
202  fprintf (stderr, "cannot connect input ports\n");
203  return NULL;
204  }
205 
206  free (ports);
207 
208 #ifdef MIC_SPEAKER_PASSTHROUGH_DEBUG
209  int i;
210  if ((ports = jack_get_ports (handle->client, "system:playback", NULL,
211  JackPortIsPhysical|JackPortIsInput)) == NULL) {
212  fprintf(stderr, "Cannot find any physical playback ports\n");
213  return NULL;
214  }
215 
216  for (i = 0; ports[i] != NULL; i++) {
217  if (jack_connect (handle->client, jack_port_name (handle->output_port), ports[i])) {
218  fprintf (stderr, "cannot connect output ports\n");
219  }
220  }
221 
222  free (ports);
223 #endif
224 
225  handle->recording = 0;
226  handle->sps = sps;
227  handle->bps = sizeof(int16);
228 
229  /* Give the jack process callback time to run ? */
230  sleep (1);
231 
232  return (ad_rec_t *) handle;
233 }
234 
235 ad_rec_t *
236 ad_open_sps(int32 sps)
237 {
238  /* Ignored the sps has to set for the jackd server */
239  return ad_open_dev(DEFAULT_DEVICE, sps);
240 }
241 
242 ad_rec_t *
243 ad_open(void)
244 {
245  return ad_open_sps(DEFAULT_SAMPLES_PER_SEC);
246 }
247 
248 int32
249 ad_close(ad_rec_t * handle)
250 {
251  free (handle->sample_buffer);
252  jack_ringbuffer_free (handle->rbuffer);
253  jack_client_close (handle->client);
254  free(handle);
255 
256  return 0;
257 }
258 
259 int32
260 ad_start_rec(ad_rec_t * handle)
261 {
262  if (handle->recording)
263  return AD_ERR_GEN;
264 
265  handle->recording = 1;
266 
267  return 0;
268 }
269 
270 int32
271 ad_stop_rec(ad_rec_t * handle)
272 {
273  handle->recording = 0;
274 
275  return 0;
276 }
277 
278 int32
279 ad_read(ad_rec_t * handle, int16 * buf, int32 max)
280 {
281  int i;
282  if (!handle->recording)
283  return AD_EOF;
284 
285  size_t length = sample_size * max;
286 
287  length = jack_ringbuffer_read (handle->rbuffer, (char*) handle->sample_buffer, length);
288  size_t length_in_samples = length / sample_size;
289 
290  for(i = 0; i < length_in_samples; i++) {
291  buf[i] = (int16) (int16_range_over_two * (handle->sample_buffer[i] + 1.0) + SHRT_MIN);
292  }
293 
294  if (length == 0 && (!handle->recording)) {
295  return AD_EOF;
296  }
297 
298  return length_in_samples;
299 }
Audio recording structure.
int32 bps
Bytes/sample.
Definition: ad_alsa.c:94
Basic type definitions used in Sphinx.
SPHINXBASE_EXPORT ad_rec_t * ad_open(void)
Open the default audio device.
Definition: ad_alsa.c:228
generic live audio interface for recording and playback
int32 sps
Samples/sec.
Definition: ad_alsa.c:93
SPHINXBASE_EXPORT ad_rec_t * ad_open_dev(const char *dev, int32 samples_per_sec)
Open a specific audio device for recording.
Definition: ad_alsa.c:187
SPHINXBASE_EXPORT ad_rec_t * ad_open_sps(int32 samples_per_sec)
Open the default audio device with a given sampling rate.
Definition: ad_alsa.c:222
Audio recording structure.
Definition: ad_alsa.c:90