SphinxBase 0.6
|
00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ 00002 /* ==================================================================== 00003 * Copyright (c) 2011 Glenn Pierce. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY GLENN PIERCE ``AS IS'' AND 00018 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00019 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00020 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 00021 * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00022 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00023 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00024 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00025 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00026 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00027 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 * 00029 * ==================================================================== 00030 * 00031 */ 00032 /* Sphinx II libad (Linux) 00033 * ^^^^^^^^^^^^^^^^^^^^^^^ 00034 * 00035 * 00036 * Glenn Pierce (glennpierce@gmail.com) 00037 * ******************************************************************** 00038 */ 00039 00040 #include <fcntl.h> 00041 #include <stdio.h> 00042 #include <stdlib.h> 00043 #include <string.h> 00044 #include <errno.h> 00045 #include <unistd.h> 00046 #include <config.h> 00047 #include <limits.h> 00048 00049 #include "prim_type.h" 00050 #include "ad.h" 00051 00052 #include <jack/jack.h> 00053 00054 #define DEFAULT_DEVICE "system:capture_1" 00055 #define BUFFER_SIZE 352800 00056 00057 //#define MIC_SPEAKER_PASSTHROUGH_DEBUG 00058 00059 const size_t sample_size = sizeof(jack_default_audio_sample_t); 00060 const size_t int16_range_over_two = (-SHRT_MIN + SHRT_MAX) / 2.0; 00061 00062 int 00063 process (jack_nframes_t nframes, void *arg) 00064 { 00065 ad_rec_t *handle = (ad_rec_t *) arg; 00066 00067 size_t buffer_size = jack_ringbuffer_write_space (handle->rbuffer); 00068 00069 jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (handle->input_port, nframes); 00070 00071 if (buffer_size <= 0) { 00072 fprintf(stderr, "JACK: buffer is full. Deactivating JACK client.\n"); 00073 return 1; 00074 } 00075 00076 // Write to jack ringbuffer which should be thread safe 00077 jack_ringbuffer_write (handle->rbuffer, (char*) in, sample_size * nframes); 00078 00079 #ifdef MIC_SPEAKER_PASSTHROUGH_DEBUG 00080 00081 jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (handle->output_port, nframes); 00082 00083 // Output mic output to speakers (Just for testing) 00084 memcpy (out, in, sample_size * nframes); 00085 00086 #endif 00087 00088 return 0; 00089 } 00090 00091 void 00092 error (const char *desc) 00093 { 00094 fprintf (stderr, "JACK error: %s\n", desc); 00095 } 00096 00097 void 00098 jack_shutdown (void *arg) 00099 { 00100 exit(1); 00101 } 00102 00103 int 00104 srate (jack_nframes_t nframes, void *arg) 00105 00106 { 00107 printf ("JACK: The sample rate is now %u/sec\n", nframes); 00108 return 0; 00109 } 00110 00111 ad_rec_t * 00112 ad_open_dev(const char *dev, int32 sps) 00113 { 00114 ad_rec_t *handle; 00115 const char **ports; 00116 00117 #ifdef HAVE_SAMPLERATE_H 00118 int resample_error; 00119 double samplerates_ratio; 00120 jack_nframes_t jack_samplerate; 00121 #endif 00122 00123 if (dev == NULL) { 00124 dev = DEFAULT_DEVICE; 00125 } 00126 00127 printf("JACK: Setting default device: %s\n", dev); 00128 00129 if ((handle = (ad_rec_t *) calloc(1, sizeof(ad_rec_t))) == NULL) { 00130 fprintf(stderr, "calloc(%d) failed\n", (int)sizeof(ad_rec_t)); 00131 abort(); 00132 } 00133 00134 /* Tell the JACK server to call error() whenever it 00135 experiences an error. 00136 */ 00137 jack_set_error_function (error); 00138 00139 /* Try to become a client of the JACK server */ 00140 if ((handle->client = jack_client_open ("jack_ad", (jack_options_t)0, NULL)) == 0) { 00141 fprintf (stderr, "jack server not running?\n"); 00142 return NULL; 00143 } 00144 00145 #ifdef HAVE_SAMPLERATE_H 00146 handle->resample_buffer = malloc(BUFFER_SIZE); 00147 00148 jack_samplerate = jack_get_sample_rate(handle->client); 00149 samplerates_ratio = (double)((double)jack_samplerate / (double)sps); 00150 00151 handle->rbuffer = jack_ringbuffer_create((int)((double)BUFFER_SIZE * samplerates_ratio)); 00152 handle->sample_buffer = malloc((int)((double)BUFFER_SIZE * samplerates_ratio)); 00153 #else 00154 handle->rbuffer = jack_ringbuffer_create(BUFFER_SIZE); 00155 handle->sample_buffer = malloc(BUFFER_SIZE); 00156 #endif 00157 00158 if(handle->rbuffer == NULL) { 00159 fprintf (stderr, "Failed to create jack ringbuffer\n"); 00160 return NULL; 00161 } 00162 00163 /* Tell the JACK server to call `process()' whenever 00164 there is work to be done. 00165 */ 00166 jack_set_process_callback (handle->client, process, handle); 00167 00168 /* Tell the JACK server to call `srate()' whenever 00169 the sample rate of the system changes. 00170 */ 00171 jack_set_sample_rate_callback (handle->client, srate, 0); 00172 00173 /* Tell the JACK server to call `jack_shutdown()' if 00174 it ever shuts down, either entirely, or if it 00175 just decides to stop calling us. 00176 */ 00177 jack_on_shutdown (handle->client, jack_shutdown, 0); 00178 00179 00180 /* Create the input port */ 00181 if((handle->input_port = jack_port_register (handle->client, "jack_ad_input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) { 00182 fprintf (stderr, "cannot register input port!\n"); 00183 return NULL; 00184 } 00185 00186 if((handle->output_port = jack_port_register (handle->client, "jack_ad_output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsOutput, 0)) == 0) { 00187 fprintf (stderr, "cannot register output port!\n"); 00188 return NULL; 00189 } 00190 00191 /* Tell the JACK server that we are ready to start */ 00192 if (jack_activate (handle->client)) { 00193 fprintf (stderr, "cannot activate client"); 00194 return NULL; 00195 } 00196 00197 /* Connect the ports. Note: you can't do this before 00198 the client is activated, because we can't allow 00199 connections to be made to clients that aren't 00200 running. 00201 */ 00202 00203 if ((ports = jack_get_ports (handle->client, dev, NULL, JackPortIsOutput)) == NULL) { 00204 fprintf(stderr, "Cannot find any physical capture ports\n"); 00205 return NULL; 00206 } 00207 00208 if (jack_connect (handle->client, ports[0], jack_port_name (handle->input_port))) { 00209 fprintf (stderr, "cannot connect input ports\n"); 00210 return NULL; 00211 } 00212 00213 free (ports); 00214 00215 #ifdef MIC_SPEAKER_PASSTHROUGH_DEBUG 00216 int i; 00217 if ((ports = jack_get_ports (handle->client, "system:playback", NULL, 00218 JackPortIsPhysical|JackPortIsInput)) == NULL) { 00219 fprintf(stderr, "Cannot find any physical playback ports\n"); 00220 return NULL; 00221 } 00222 00223 for (i = 0; ports[i] != NULL; i++) { 00224 if (jack_connect (handle->client, jack_port_name (handle->output_port), ports[i])) { 00225 fprintf (stderr, "cannot connect output ports\n"); 00226 } 00227 } 00228 00229 free (ports); 00230 #endif 00231 00232 #ifdef HAVE_SAMPLERATE_H 00233 // Initialize the sample rate converter. 00234 if ((handle->resample_state = src_new (SRC_SINC_BEST_QUALITY, 1, &resample_error)) == NULL) { 00235 fprintf (stderr, "Error : src_new() failed: %s\n", src_strerror(resample_error)); 00236 return NULL; 00237 } 00238 #endif 00239 00240 handle->recording = 0; 00241 handle->sps = sps; 00242 handle->bps = sizeof(int16); 00243 00244 // Give the jack process callback time to run ? 00245 sleep (1); 00246 00247 return (ad_rec_t *) handle; 00248 } 00249 00250 ad_rec_t * 00251 ad_open_sps(int32 sps) 00252 { 00253 // Ignored the sps has to set for the jackd server 00254 return ad_open_dev(DEFAULT_DEVICE, sps); 00255 } 00256 00257 ad_rec_t * 00258 ad_open(void) 00259 { 00260 return ad_open_sps(DEFAULT_SAMPLES_PER_SEC); 00261 } 00262 00263 int32 00264 ad_close(ad_rec_t * handle) 00265 { 00266 free (handle->sample_buffer); 00267 #ifdef HAVE_SAMPLERATE_H 00268 free (handle->resample_buffer); 00269 #endif 00270 jack_ringbuffer_free (handle->rbuffer); 00271 jack_client_close (handle->client); 00272 free(handle); 00273 00274 return 0; 00275 } 00276 00277 int32 00278 ad_start_rec(ad_rec_t * handle) 00279 { 00280 if (handle->recording) 00281 return AD_ERR_GEN; 00282 00283 handle->recording = 1; 00284 00285 return 0; 00286 } 00287 00288 int32 00289 ad_stop_rec(ad_rec_t * handle) 00290 { 00291 handle->recording = 0; 00292 00293 return 0; 00294 } 00295 00296 int32 00297 ad_read(ad_rec_t * handle, int16 * buf, int32 max) 00298 { 00299 #ifdef HAVE_SAMPLERATE_H 00300 int resample_error; 00301 #endif 00302 00303 if (!handle->recording) 00304 return AD_EOF; 00305 00306 size_t length = sample_size * max; 00307 00308 #ifdef HAVE_SAMPLERATE_H 00309 00310 // Resample the data from the sample rate set in the jack server to that required 00311 // by sphinx 00312 00313 length = jack_ringbuffer_peek (handle->rbuffer, (char*) handle->sample_buffer, length); 00314 size_t length_in_samples = length / sample_size; 00315 00316 if(handle->resample_state == NULL) 00317 return AD_EOF; 00318 00319 // We will try to downsample if jackd is running at a higher sample rate 00320 jack_nframes_t jack_samplerate = jack_get_sample_rate(handle->client); 00321 00322 SRC_DATA data; 00323 00324 data.data_in = handle->sample_buffer; 00325 data.input_frames = length_in_samples; 00326 data.data_out = handle->resample_buffer; 00327 data.output_frames = BUFFER_SIZE / sample_size; 00328 data.src_ratio = (float) handle->sps / jack_samplerate; 00329 data.end_of_input = 0; 00330 00331 if ((resample_error = src_process(handle->resample_state, &data)) != 0) { 00332 fprintf (stderr, "resample error %s\n", src_strerror (resample_error)); 00333 return 1; 00334 } 00335 00336 for(int i=0; i<data.output_frames_gen; i++) { 00337 buf[i] = (int16) (int16_range_over_two * (handle->resample_buffer[i] + 1.0) + SHRT_MIN); 00338 } 00339 00340 jack_ringbuffer_read_advance(handle->rbuffer, data.input_frames_used * sample_size); 00341 00342 if(length == 0 && (!handle->recording)) { 00343 return AD_EOF; 00344 } 00345 00346 return data.output_frames_gen; 00347 00348 #else 00349 00350 length = jack_ringbuffer_read (handle->rbuffer, (char*) handle->sample_buffer, length); 00351 size_t length_in_samples = length / sample_size; 00352 00353 for(int i=0; i<length_in_samples; i++) { 00354 buf[i] = (int16) (int16_range_over_two * (handle->sample_buffer[i] + 1.0) + SHRT_MIN); 00355 } 00356 00357 if(length == 0 && (!handle->recording)) { 00358 return AD_EOF; 00359 } 00360 00361 return length_in_samples; 00362 00363 #endif 00364 }