bump micro version
[jack.git] / tools / alsa_in.c
blob24ffc230d96c8e81e599744a2943352efe14e407
1 /** @file simple_client.c
3 * @brief This simple client demonstrates the basic features of JACK
4 * as they would be used by many applications.
5 */
7 #include <stdio.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include <alloca.h>
14 #include <math.h>
16 #include <jack/jack.h>
17 #include <jack/jslist.h>
19 #define ALSA_PCM_OLD_HW_PARAMS_API
20 #define ALSA_PCM_OLD_SW_PARAMS_API
21 #include "alsa/asoundlib.h"
23 #include <samplerate.h>
24 #include "time_smoother.h"
26 typedef signed short ALSASAMPLE;
28 // Here are the lists of the jack ports...
30 JSList *capture_ports = NULL;
31 JSList *capture_srcs = NULL;
32 JSList *playback_ports = NULL;
33 JSList *playback_srcs = NULL;
34 jack_client_t *client;
36 // TODO: make the sample format configurable soon...
37 snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
39 snd_pcm_t *alsa_handle;
41 int jack_sample_rate;
43 double current_resample_factor = 1.0;
45 time_smoother *smoother;
47 // ------------------------------------------------------ commandline parameters
49 int sample_rate = 0; /* stream rate */
50 int num_channels = 2; /* count of channels */
51 int period_size = 1024;
52 int num_periods = 2;
54 int target_delay = 0; /* the delay which the program should try to approach. */
55 int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */
56 int catch_factor = 1000;
58 // Debug stuff:
60 int print_counter = 10;
62 volatile float output_resampling_factor = 0.0;
63 volatile int output_new_delay = 0;
64 volatile float output_offset = 0.0;
65 volatile float output_diff = 0.0;
67 // Alsa stuff... i dont want to touch this bullshit in the next years.... please...
69 static int xrun_recovery(snd_pcm_t *handle, int err) {
70 //printf( "xrun !!!....\n" );
71 if (err == -EPIPE) { /* under-run */
72 err = snd_pcm_prepare(handle);
73 if (err < 0)
74 printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
75 return 0;
76 } else if (err == -ESTRPIPE) {
77 while ((err = snd_pcm_resume(handle)) == -EAGAIN)
78 sleep(1); /* wait until the suspend flag is released */
79 if (err < 0) {
80 err = snd_pcm_prepare(handle);
81 if (err < 0)
82 printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
84 return 0;
86 return err;
89 static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) {
90 int err, dir=0;
92 /* choose all parameters */
93 err = snd_pcm_hw_params_any(handle, params);
94 if (err < 0) {
95 printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
96 return err;
98 /* set the interleaved read/write format */
99 err = snd_pcm_hw_params_set_access(handle, params, access);
100 if (err < 0) {
101 printf("Access type not available for playback: %s\n", snd_strerror(err));
102 return err;
104 /* set the sample format */
105 err = snd_pcm_hw_params_set_format(handle, params, format);
106 if (err < 0) {
107 printf("Sample format not available for playback: %s\n", snd_strerror(err));
108 return err;
110 /* set the count of channels */
111 err = snd_pcm_hw_params_set_channels(handle, params, channels);
112 if (err < 0) {
113 printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
114 return err;
116 /* set the stream rate */
117 err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0);
118 if (err < 0) {
119 printf("Rate %iHz not available for capture: %s\n", rate, snd_strerror(err));
120 return err;
122 if (err != rate) {
123 printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
124 return -EINVAL;
126 /* set the buffer time */
127 err = snd_pcm_hw_params_set_buffer_time_near(handle, params, 1000000*period*nperiods/rate, &dir);
128 if (err < 0) {
129 printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err));
130 return err;
132 if( snd_pcm_hw_params_get_buffer_size(params) != nperiods * period ) {
133 printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) snd_pcm_hw_params_get_buffer_size(params) );
135 /* set the period time */
136 err = snd_pcm_hw_params_set_period_time_near(handle, params, 1000000*period/rate, &dir);
137 if (err < 0) {
138 printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err));
139 return err;
141 int ps = snd_pcm_hw_params_get_period_size(params, NULL );
142 if( ps != period ) {
143 printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, ps );
145 /* write the parameters to device */
146 err = snd_pcm_hw_params(handle, params);
147 if (err < 0) {
148 printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
149 return err;
151 return 0;
154 static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period) {
155 int err;
157 /* get the current swparams */
158 err = snd_pcm_sw_params_current(handle, swparams);
159 if (err < 0) {
160 printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
161 return err;
163 /* start the transfer when the buffer is full */
164 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period );
165 if (err < 0) {
166 printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
167 return err;
169 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
170 if (err < 0) {
171 printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
172 return err;
174 /* allow the transfer when at least period_size samples can be processed */
175 err = snd_pcm_sw_params_set_avail_min(handle, swparams, 2*period );
176 if (err < 0) {
177 printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
178 return err;
180 /* align all transfers to 1 sample */
181 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
182 if (err < 0) {
183 printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
184 return err;
186 /* write the parameters to the playback device */
187 err = snd_pcm_sw_params(handle, swparams);
188 if (err < 0) {
189 printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
190 return err;
192 return 0;
195 // ok... i only need this function to communicate with the alsa bloat api...
197 static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) {
198 int err;
199 snd_pcm_t *handle;
200 snd_pcm_hw_params_t *hwparams;
201 snd_pcm_sw_params_t *swparams;
203 snd_pcm_hw_params_alloca(&hwparams);
204 snd_pcm_sw_params_alloca(&swparams);
206 if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) {
207 printf("Capture open error: %s\n", snd_strerror(err));
208 return NULL;
211 if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) {
212 printf("Setting of hwparams failed: %s\n", snd_strerror(err));
213 return NULL;
215 if ((err = set_swparams(handle, swparams, period)) < 0) {
216 printf("Setting of swparams failed: %s\n", snd_strerror(err));
217 return NULL;
220 snd_pcm_start( handle );
221 snd_pcm_wait( handle, 200 );
223 return handle;
226 jack_nframes_t soundcard_frames = 0;
229 * The process callback for this JACK application.
230 * It is called by JACK at the appropriate times.
232 int process (jack_nframes_t nframes, void *arg) {
234 ALSASAMPLE *outbuf;
235 float *floatbuf, *resampbuf;
236 int rlen;
237 int err;
238 snd_pcm_sframes_t delay, absolute_delay;
239 jack_nframes_t this_frame_time;
240 jack_nframes_t this_soundcard_time;
241 int put_back_samples=0;
242 int dont_adjust_resampling_factor = 0;
243 double a, b;
246 snd_pcm_delay( alsa_handle, &delay );
247 this_frame_time = jack_frame_time(client);
248 this_soundcard_time = soundcard_frames + delay;
251 time_smoother_put( smoother, this_frame_time, this_soundcard_time );
253 // subtract jack_frames_since_cycle_start, to compensate for
254 // cpu jitter.
255 //absolute_delay = delay;
256 //delay = delay - jack_frames_since_cycle_start( client );
258 //output_new_delay = (int) delay;
260 // Do it the hard way.
261 // this is for compensating xruns etc...
263 if( delay > (target_delay+max_diff) ) {
264 ALSASAMPLE *tmp = alloca( (delay-target_delay) * sizeof( ALSASAMPLE ) * num_channels );
265 snd_pcm_readi( alsa_handle, tmp, delay-target_delay );
266 soundcard_frames += (delay-target_delay);
267 output_new_delay = (int) delay;
268 dont_adjust_resampling_factor = 1;
269 delay = target_delay;
270 // XXX: at least set it to that value.
271 current_resample_factor = (double) jack_sample_rate / (double) sample_rate;
273 if( delay < (target_delay-max_diff) ) {
274 snd_pcm_rewind( alsa_handle, target_delay - delay );
275 soundcard_frames -= (target_delay-delay);
276 output_new_delay = (int) delay;
277 dont_adjust_resampling_factor = 1;
278 delay = target_delay;
279 // XXX: at least set it to that value.
280 current_resample_factor = (double) jack_sample_rate / (double) sample_rate;
283 if( 1 ) {
284 double resamp_rate = (double)jack_sample_rate / (double)sample_rate; // == nframes / alsa_samples.
285 double request_samples = nframes / resamp_rate; //== alsa_samples;
287 double offset = delay - target_delay;
289 double frlen = request_samples + offset;
290 double compute_factor = (double) nframes / frlen;
292 double diff_value = pow(current_resample_factor - compute_factor, 3) / (double) catch_factor;
294 current_resample_factor -= diff_value;
296 // clamp...
297 current_resample_factor = current_resample_factor < 0.25 ? 0.25 : current_resample_factor;
299 output_resampling_factor = (float) current_resample_factor;
300 output_offset = offset;
301 output_diff = diff_value;
303 else
305 time_smoother_get_linear_params( smoother, this_frame_time, this_soundcard_time, jack_get_sample_rate(client)/4,
306 &a, &b );
308 if( !dont_adjust_resampling_factor )
309 current_resample_factor = b - a/(double)nframes/(double)catch_factor;
310 else
311 current_resample_factor = b;
313 double offset = a;
314 double diff_value = b;
317 output_resampling_factor = (float) current_resample_factor;
318 output_diff = (float) diff_value;
319 output_offset = (float) offset;
322 if( current_resample_factor < 0.25 ) current_resample_factor = 0.25;
323 if( current_resample_factor > 4 ) current_resample_factor = 4;
324 rlen = ceil( ((double)nframes) / current_resample_factor )+20;
325 assert( rlen > 10 );
328 * now this should do it...
331 outbuf = alloca( rlen * sizeof( ALSASAMPLE ) * num_channels );
333 floatbuf = alloca( rlen * sizeof( float ) );
334 resampbuf = alloca( nframes * sizeof( float ) );
336 // get the data...
337 again:
338 err = snd_pcm_readi(alsa_handle, outbuf, rlen);
339 if( err < 0 ) {
340 printf( "err = %d\n", err );
341 if (xrun_recovery(alsa_handle, err) < 0) {
342 //printf("Write error: %s\n", snd_strerror(err));
343 //exit(EXIT_FAILURE);
345 goto again;
347 soundcard_frames += err;
348 if( err != rlen ) {
349 //printf( "read = %d\n", rlen );
353 * render jack ports to the outbuf...
356 int chn = 0;
357 JSList *node = capture_ports;
358 JSList *src_node = capture_srcs;
359 while ( node != NULL)
361 int i;
362 jack_port_t *port = (jack_port_t *) node->data;
363 float *buf = jack_port_get_buffer (port, nframes);
365 SRC_STATE *src_state = src_node->data;
366 SRC_DATA src;
368 for (i=0; i < rlen; i++) {
369 resampbuf[i] = (float) outbuf[chn+ i*num_channels] / 32767;
372 src.data_in = resampbuf;
373 src.input_frames = rlen;
375 src.data_out = buf;
376 src.output_frames = nframes;
377 src.end_of_input = 0;
379 //src.src_ratio = (float) nframes / frlen;
380 src.src_ratio = current_resample_factor;
382 //src_set_ratio( src_state, src.src_ratio );
383 src_process( src_state, &src );
385 put_back_samples = rlen-src.input_frames_used;
388 if( src.output_frames_gen != nframes ) {
389 printf( "did not fill jack_buffer... %ld\n", nframes-src.output_frames_gen );
390 printf( "rlen=%d ratio=%f... nframes=%d\ninputused=%d\n", rlen, current_resample_factor, nframes, src.input_frames_used );
395 src_node = jack_slist_next (src_node);
396 node = jack_slist_next (node);
397 chn++;
400 //printf( "putback = %d\n", put_back_samples );
401 snd_pcm_rewind( alsa_handle, put_back_samples );
402 soundcard_frames -= put_back_samples;
404 return 0;
409 * Allocate the necessary jack ports...
412 void alloc_ports( int n_capture, int n_playback ) {
414 int port_flags = JackPortIsOutput;
415 int chn;
416 jack_port_t *port;
417 char buf[32];
419 capture_ports = NULL;
420 for (chn = 0; chn < n_capture; chn++)
422 snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);
424 port = jack_port_register (client, buf,
425 JACK_DEFAULT_AUDIO_TYPE,
426 port_flags, 0);
428 if (!port)
430 printf( "jacknet_client: cannot register port for %s", buf);
431 break;
434 capture_srcs = jack_slist_append( capture_srcs, src_new( SRC_SINC_FASTEST, 1, NULL ) );
435 capture_ports = jack_slist_append (capture_ports, port);
438 port_flags = JackPortIsInput;
440 playback_ports = NULL;
441 for (chn = 0; chn < n_playback; chn++)
443 snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);
445 port = jack_port_register (client, buf,
446 JACK_DEFAULT_AUDIO_TYPE,
447 port_flags, 0);
449 if (!port)
451 printf( "jacknet_client: cannot register port for %s", buf);
452 break;
455 playback_srcs = jack_slist_append( playback_srcs, src_new( SRC_SINC_FASTEST, 1, NULL ) );
456 playback_ports = jack_slist_append (playback_ports, port);
461 * This is the shutdown callback for this JACK application.
462 * It is called by JACK if the server ever shuts down or
463 * decides to disconnect the client.
466 void jack_shutdown (void *arg) {
468 exit (1);
472 * be user friendly.
473 * be user friendly.
474 * be user friendly.
477 void printUsage() {
478 fprintf(stderr, "usage: alsa_out [options]\n"
479 "\n"
480 " -j <jack name> - reports a different name to jack\n"
481 " -d <alsa_device> \n"
482 " -c <channels> \n"
483 " -p <period_size> \n"
484 " -n <num_period> \n"
485 " -r <sample_rate> \n"
486 " -m <max_diff> \n"
487 " -t <target_delay> \n"
488 " -f <catch_factor> \n"
489 "\n");
494 * the main function....
498 int main (int argc, char *argv[]) {
499 char jack_name[30] = "alsa_in";
500 char alsa_device[30] = "hw:0";
502 extern char *optarg;
503 extern int optind, optopt;
504 int errflg=0;
505 int c;
507 while ((c = getopt(argc, argv, ":j:r:c:p:n:d:m:t:f:")) != -1) {
508 switch(c) {
509 case 'j':
510 strcpy(jack_name,optarg);
511 break;
512 case 'r':
513 sample_rate = atoi(optarg);
514 break;
515 case 'c':
516 num_channels = atoi(optarg);
517 break;
518 case 'p':
519 period_size = atoi(optarg);
520 break;
521 case 'n':
522 num_periods = atoi(optarg);
523 break;
524 case 'd':
525 strcpy(alsa_device,optarg);
526 break;
527 case 't':
528 target_delay = atoi(optarg);
529 break;
530 case 'm':
531 max_diff = atoi(optarg);
532 break;
533 case 'f':
534 catch_factor = atoi(optarg);
535 break;
536 case ':':
537 fprintf(stderr,
538 "Option -%c requires an operand\n", optopt);
539 errflg++;
540 break;
541 case '?':
542 fprintf(stderr,
543 "Unrecognized option: -%c\n", optopt);
544 errflg++;
547 if (errflg) {
548 printUsage();
549 exit(2);
552 // Setup target delay and max_diff for the normal user, who does not play with them...
554 if( !target_delay )
555 target_delay = num_periods*period_size / 2;
557 if( !max_diff )
558 max_diff = period_size / 2;
560 smoother = time_smoother_new( 100 );
561 if( !smoother ) {
562 fprintf (stderr, "no memory\n");
563 return 10;
567 if ((client = jack_client_new (jack_name)) == 0) {
568 fprintf (stderr, "jack server not running?\n");
569 return 1;
572 /* tell the JACK server to call `process()' whenever
573 there is work to be done.
576 jack_set_process_callback (client, process, 0);
578 /* tell the JACK server to call `jack_shutdown()' if
579 it ever shuts down, either entirely, or if it
580 just decides to stop calling us.
583 jack_on_shutdown (client, jack_shutdown, 0);
586 // alloc input ports, which are blasted out to alsa...
587 alloc_ports( num_channels, 0 );
589 // get jack sample_rate
591 jack_sample_rate = jack_get_sample_rate( client );
593 if( !sample_rate )
594 sample_rate = jack_sample_rate;
596 current_resample_factor = (double) jack_sample_rate / (double) sample_rate;
597 //// now open the alsa fd...
599 alsa_handle = open_audiofd( alsa_device, 1, sample_rate, num_channels, period_size, num_periods);
600 if( alsa_handle < 0 )
601 exit(20);
604 /* tell the JACK server that we are ready to roll */
606 if (jack_activate (client)) {
607 fprintf (stderr, "cannot activate client");
608 return 1;
611 while(1) {
612 usleep(500000);
613 if( output_new_delay ) {
614 printf( "delay = %d\n", output_new_delay );
615 output_new_delay = 0;
617 printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset );
618 output_offset = 0.0;
622 jack_client_close (client);
623 exit (0);