bump micro version
[jack.git] / tools / alsa_out.c
blob2101112cfdb5b646135c95b498404fc7a094895f
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 #define _ISOC99_SOURCE 1
8 #define _XOPEN_SOURCE 600
10 #include <stdio.h>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
16 #include <alloca.h>
17 #include <math.h>
19 #include <jack/jack.h>
20 #include <jack/jslist.h>
22 #define ALSA_PCM_OLD_HW_PARAMS_API
23 #define ALSA_PCM_OLD_SW_PARAMS_API
24 #include "alsa/asoundlib.h"
26 #include <samplerate.h>
27 #include "time_smoother.h"
29 #define SAMPLE_16BIT_SCALING 32767.0f
30 #define SAMPLE_16BIT_MAX 32767
31 #define SAMPLE_16BIT_MIN -32767
32 #define NORMALIZED_FLOAT_MIN -1.0f
33 #define NORMALIZED_FLOAT_MAX 1.0f
34 #define f_round(f) lrintf(f)
36 #define float_16(s, d)\
37 if ((s) <= NORMALIZED_FLOAT_MIN) {\
38 (d) = SAMPLE_16BIT_MIN;\
39 } else if ((s) >= NORMALIZED_FLOAT_MAX) {\
40 (d) = SAMPLE_16BIT_MAX;\
41 } else {\
42 (d) = f_round ((s) * SAMPLE_16BIT_SCALING);\
45 typedef signed short ALSASAMPLE;
47 // Here are the lists of the jack ports...
49 JSList *capture_ports = NULL;
50 JSList *capture_srcs = NULL;
51 JSList *playback_ports = NULL;
52 JSList *playback_srcs = NULL;
53 jack_client_t *client;
55 // TODO: make the sample format configurable soon...
56 snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
58 snd_pcm_t *alsa_handle;
60 int jack_sample_rate;
62 double current_resample_factor = 1.0;
63 int periods_until_stability = 10;
65 time_smoother *smoother;
67 // ------------------------------------------------------ commandline parameters
69 int sample_rate = 0; /* stream rate */
70 int num_channels = 2; /* count of channels */
71 int period_size = 1024;
72 int num_periods = 2;
74 int target_delay = 0; /* the delay which the program should try to approach. */
75 int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */
76 int catch_factor = 1000;
78 // Debug stuff:
80 int print_counter = 10;
82 volatile float output_resampling_factor = 0.0;
83 volatile int output_new_delay = 0;
84 volatile float output_offset = 0.0;
85 volatile float output_diff = 0.0;
88 // Alsa stuff... i dont want to touch this bullshit in the next years.... please...
90 static int xrun_recovery(snd_pcm_t *handle, int err) {
91 //printf( "xrun !!!....\n" );
92 if (err == -EPIPE) { /* under-run */
93 err = snd_pcm_prepare(handle);
94 if (err < 0)
95 printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
96 return 0;
97 } else if (err == -ESTRPIPE) {
98 while ((err = snd_pcm_resume(handle)) == -EAGAIN)
99 sleep(1); /* wait until the suspend flag is released */
100 if (err < 0) {
101 err = snd_pcm_prepare(handle);
102 if (err < 0)
103 printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
105 return 0;
107 return err;
110 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 ) {
111 int err, dir=0;
113 /* choose all parameters */
114 err = snd_pcm_hw_params_any(handle, params);
115 if (err < 0) {
116 printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
117 return err;
119 /* set the interleaved read/write format */
120 err = snd_pcm_hw_params_set_access(handle, params, access);
121 if (err < 0) {
122 printf("Access type not available for playback: %s\n", snd_strerror(err));
123 return err;
125 /* set the sample format */
126 err = snd_pcm_hw_params_set_format(handle, params, format);
127 if (err < 0) {
128 printf("Sample format not available for playback: %s\n", snd_strerror(err));
129 return err;
131 /* set the count of channels */
132 err = snd_pcm_hw_params_set_channels(handle, params, channels);
133 if (err < 0) {
134 printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
135 return err;
137 /* set the stream rate */
138 err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0);
139 if (err < 0) {
140 printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
141 return err;
143 if (err != rate) {
144 printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
145 return -EINVAL;
147 /* set the buffer time */
148 err = snd_pcm_hw_params_set_buffer_time_near(handle, params, 1000000*period*nperiods/rate, &dir);
149 if (err < 0) {
150 printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err));
151 return err;
153 if( snd_pcm_hw_params_get_buffer_size(params) != nperiods * period ) {
154 printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) snd_pcm_hw_params_get_buffer_size(params) );
156 /* set the period time */
157 err = snd_pcm_hw_params_set_period_time_near(handle, params, 1000000*period/rate, &dir);
158 if (err < 0) {
159 printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err));
160 return err;
162 int ps = snd_pcm_hw_params_get_period_size(params, NULL );
163 if( ps != period ) {
164 printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, ps );
166 /* write the parameters to device */
167 err = snd_pcm_hw_params(handle, params);
168 if (err < 0) {
169 printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
170 return err;
172 return 0;
175 static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period, int nperiods) {
176 int err;
178 /* get the current swparams */
179 err = snd_pcm_sw_params_current(handle, swparams);
180 if (err < 0) {
181 printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
182 return err;
184 /* start the transfer when the buffer is full */
185 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period );
186 if (err < 0) {
187 printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
188 return err;
190 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
191 if (err < 0) {
192 printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
193 return err;
195 /* allow the transfer when at least period_size samples can be processed */
196 err = snd_pcm_sw_params_set_avail_min(handle, swparams, 1 );
197 if (err < 0) {
198 printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
199 return err;
201 /* align all transfers to 1 sample */
202 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
203 if (err < 0) {
204 printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
205 return err;
207 /* write the parameters to the playback device */
208 err = snd_pcm_sw_params(handle, swparams);
209 if (err < 0) {
210 printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
211 return err;
213 return 0;
216 // ok... i only need this function to communicate with the alsa bloat api...
218 static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) {
219 int err;
220 snd_pcm_t *handle;
221 snd_pcm_hw_params_t *hwparams;
222 snd_pcm_sw_params_t *swparams;
224 snd_pcm_hw_params_alloca(&hwparams);
225 snd_pcm_sw_params_alloca(&swparams);
227 if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) {
228 printf("Capture open error: %s\n", snd_strerror(err));
229 return NULL;
232 if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) {
233 printf("Setting of hwparams failed: %s\n", snd_strerror(err));
234 return NULL;
236 if ((err = set_swparams(handle, swparams, period, nperiods)) < 0) {
237 printf("Setting of swparams failed: %s\n", snd_strerror(err));
238 return NULL;
241 //snd_pcm_start( handle );
242 //snd_pcm_wait( handle, 200 );
243 int num_null_samples = nperiods * period * channels;
244 ALSASAMPLE *tmp = alloca( num_null_samples * sizeof( ALSASAMPLE ) );
245 memset( tmp, 0, num_null_samples * sizeof( ALSASAMPLE ) );
246 snd_pcm_writei( handle, tmp, num_null_samples );
249 return handle;
252 jack_nframes_t soundcard_frames = 0;
255 * The process callback for this JACK application.
256 * It is called by JACK at the appropriate times.
258 int process (jack_nframes_t nframes, void *arg) {
260 ALSASAMPLE *outbuf;
261 float *floatbuf, *resampbuf;
262 int rlen;
263 int err;
264 snd_pcm_sframes_t delay;
265 jack_nframes_t this_frame_time;
266 jack_nframes_t this_soundcard_time;
267 int dont_adjust_resampling_factor = 0;
268 double a, b;
270 double offset;
271 double diff_value;
273 snd_pcm_delay( alsa_handle, &delay );
274 this_frame_time = jack_frame_time(client);
275 this_soundcard_time = soundcard_frames + delay;
277 time_smoother_put( smoother, this_frame_time, this_soundcard_time );
279 // Do it the hard way.
280 // this is for compensating xruns etc...
282 if( delay > (target_delay+max_diff) ) {
283 snd_pcm_rewind( alsa_handle, delay - target_delay );
284 soundcard_frames -= (delay-target_delay);
285 output_new_delay = (int) delay;
286 dont_adjust_resampling_factor = 1;
287 //snd_pcm_delay( alsa_handle, &delay );
288 delay = target_delay;
289 // XXX: at least set it to that value.
290 //current_resample_factor = (double) sample_rate / (double) jack_sample_rate;
291 current_resample_factor = (double) jack_sample_rate / (double) sample_rate;
292 periods_until_stability = 10;
294 if( delay < (target_delay-max_diff) ) {
295 ALSASAMPLE *tmp = alloca( (target_delay-delay) * sizeof( ALSASAMPLE ) * num_channels );
296 memset( tmp, 0, sizeof( ALSASAMPLE ) * num_channels * (target_delay-delay) );
297 snd_pcm_writei( alsa_handle, tmp, target_delay-delay );
298 soundcard_frames += (target_delay-delay);
299 output_new_delay = (int) delay;
300 dont_adjust_resampling_factor = 1;
301 //snd_pcm_delay( alsa_handle, &delay );
302 delay = target_delay;
303 // XXX: at least set it to that value.
304 //current_resample_factor = (double) sample_rate / (double) jack_sample_rate;
305 current_resample_factor = (double) jack_sample_rate / (double) sample_rate;
306 periods_until_stability = 10;
308 /* ok... now we should have target_delay +- max_diff on the alsa side.
310 * calculate the number of frames, we want to get.
313 //if( periods_until_stability ) {
314 if( 1 ) {
315 double resamp_rate = (double)jack_sample_rate / (double)sample_rate; // == nframes / alsa_samples.
316 double request_samples = nframes / resamp_rate; //== alsa_samples;
317 //double request_samples = nframes * current_resample_factor; //== alsa_samples;
319 offset = delay - target_delay;
321 //double frlen = request_samples - offset / catch_factor;
322 double frlen = request_samples - offset;
324 double compute_factor = frlen / (double) nframes;
325 //double compute_factor = (double) nframes / frlen;
327 diff_value = pow(current_resample_factor - compute_factor, 3) / (double) catch_factor;
328 current_resample_factor -= diff_value;
329 periods_until_stability -= 1;
331 else
333 time_smoother_get_linear_params( smoother, this_frame_time, this_soundcard_time, jack_get_sample_rate(client)/4,
334 &a, &b );
336 if( dont_adjust_resampling_factor ) {
337 current_resample_factor = 1.0/( b - a/(double)nframes/(double)catch_factor );
338 //double delay_diff = (double)delay - (double)target_delay;
339 //current_resample_factor = 1.0/( b + a/(double)nframes - delay_diff/(double)nframes/(double)catch_factor );
340 } else
341 current_resample_factor = 1.0/b;
343 offset = delay - target_delay;
344 diff_value = b;
348 output_resampling_factor = (float) current_resample_factor;
349 output_diff = (float) diff_value;
350 output_offset = (float) offset;
352 if( current_resample_factor < 0.25 ) current_resample_factor = 0.25;
353 if( current_resample_factor > 4 ) current_resample_factor = 4;
354 rlen = ceil( ((double)nframes) * current_resample_factor )+2;
355 assert( rlen > 10 );
357 * now this should do it...
360 outbuf = alloca( rlen * sizeof( ALSASAMPLE ) * num_channels );
362 floatbuf = alloca( rlen * sizeof( float ) );
363 resampbuf = alloca( nframes * sizeof( float ) );
365 * render jack ports to the outbuf...
368 int chn = 0;
369 JSList *node = playback_ports;
370 JSList *src_node = playback_srcs;
371 SRC_DATA src;
372 while ( node != NULL)
374 int i;
375 jack_port_t *port = (jack_port_t *) node->data;
376 float *buf = jack_port_get_buffer (port, nframes);
378 SRC_STATE *src_state = src_node->data;
380 src.data_in = buf;
381 src.input_frames = nframes;
383 src.data_out = resampbuf;
384 src.output_frames = rlen;
385 src.end_of_input = 0;
387 src.src_ratio = current_resample_factor;
389 src_process( src_state, &src );
391 for (i=0; i < rlen; i++) {
392 float_16( resampbuf[i], outbuf[chn+ i*num_channels] );
395 src_node = jack_slist_next (src_node);
396 node = jack_slist_next (node);
397 chn++;
400 // now write the output...
402 again:
403 err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
404 if( err < 0 ) {
405 printf( "err = %d\n", err );
406 if (xrun_recovery(alsa_handle, err) < 0) {
407 //printf("Write error: %s\n", snd_strerror(err));
408 //exit(EXIT_FAILURE);
410 goto again;
412 soundcard_frames += err;
414 // if( err != rlen ) {
415 // printf( "write = %d\n", rlen );
416 // }
421 return 0;
426 * Allocate the necessary jack ports...
429 void alloc_ports( int n_capture, int n_playback ) {
431 int port_flags = JackPortIsOutput;
432 int chn;
433 jack_port_t *port;
434 char buf[32];
436 capture_ports = NULL;
437 for (chn = 0; chn < n_capture; chn++)
439 snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);
441 port = jack_port_register (client, buf,
442 JACK_DEFAULT_AUDIO_TYPE,
443 port_flags, 0);
445 if (!port)
447 printf( "jacknet_client: cannot register port for %s", buf);
448 break;
451 capture_srcs = jack_slist_append( capture_srcs, src_new( SRC_SINC_FASTEST, 1, NULL ) );
452 capture_ports = jack_slist_append (capture_ports, port);
455 port_flags = JackPortIsInput;
457 playback_ports = NULL;
458 for (chn = 0; chn < n_playback; chn++)
460 snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);
462 port = jack_port_register (client, buf,
463 JACK_DEFAULT_AUDIO_TYPE,
464 port_flags, 0);
466 if (!port)
468 printf( "jacknet_client: cannot register port for %s", buf);
469 break;
472 playback_srcs = jack_slist_append( playback_srcs, src_new( SRC_SINC_FASTEST, 1, NULL ) );
473 playback_ports = jack_slist_append (playback_ports, port);
478 * This is the shutdown callback for this JACK application.
479 * It is called by JACK if the server ever shuts down or
480 * decides to disconnect the client.
483 void jack_shutdown (void *arg) {
485 exit (1);
489 * be user friendly.
490 * be user friendly.
491 * be user friendly.
494 void printUsage() {
495 fprintf(stderr, "usage: alsa_out [options]\n"
496 "\n"
497 " -j <jack name> - reports a different name to jack\n"
498 " -d <alsa_device> \n"
499 " -c <channels> \n"
500 " -p <period_size> \n"
501 " -n <num_period> \n"
502 " -r <sample_rate> \n"
503 " -m <max_diff> \n"
504 " -t <target_delay> \n"
505 " -f <catch_factor> \n"
506 "\n");
511 * the main function....
515 int main (int argc, char *argv[]) {
516 char jack_name[30] = "alsa_out";
517 char alsa_device[30] = "hw:0";
519 extern char *optarg;
520 extern int optind, optopt;
521 int errflg=0;
522 int c;
524 while ((c = getopt(argc, argv, ":j:r:c:p:n:d:m:t:f:")) != -1) {
525 switch(c) {
526 case 'j':
527 strcpy(jack_name,optarg);
528 break;
529 case 'r':
530 sample_rate = atoi(optarg);
531 break;
532 case 'c':
533 num_channels = atoi(optarg);
534 break;
535 case 'p':
536 period_size = atoi(optarg);
537 break;
538 case 'n':
539 num_periods = atoi(optarg);
540 break;
541 case 'd':
542 strcpy(alsa_device,optarg);
543 break;
544 case 't':
545 target_delay = atoi(optarg);
546 break;
547 case 'm':
548 max_diff = atoi(optarg);
549 break;
550 case 'f':
551 catch_factor = atoi(optarg);
552 break;
553 case ':':
554 fprintf(stderr,
555 "Option -%c requires an operand\n", optopt);
556 errflg++;
557 break;
558 case '?':
559 fprintf(stderr,
560 "Unrecognized option: -%c\n", optopt);
561 errflg++;
564 if (errflg) {
565 printUsage();
566 exit(2);
569 // Setup target delay and max_diff for the normal user, who does not play with them...
571 if( !target_delay )
572 target_delay = num_periods*period_size / 2;
574 if( !max_diff )
575 max_diff = period_size / 2;
577 smoother = time_smoother_new( 100 );
578 if( !smoother ) {
579 fprintf (stderr, "no memory\n");
580 return 10;
584 if ((client = jack_client_new (jack_name)) == 0) {
585 fprintf (stderr, "jack server not running?\n");
586 return 1;
589 /* tell the JACK server to call `process()' whenever
590 there is work to be done.
593 jack_set_process_callback (client, process, 0);
595 /* tell the JACK server to call `jack_shutdown()' if
596 it ever shuts down, either entirely, or if it
597 just decides to stop calling us.
600 jack_on_shutdown (client, jack_shutdown, 0);
603 // alloc input ports, which are blasted out to alsa...
604 alloc_ports( 0, num_channels );
606 // get jack sample_rate
608 jack_sample_rate = jack_get_sample_rate( client );
610 if( !sample_rate )
611 sample_rate = jack_sample_rate;
613 current_resample_factor = (double) sample_rate / (double) jack_sample_rate;
614 // now open the alsa fd...
616 alsa_handle = open_audiofd( alsa_device, 0, sample_rate, num_channels, period_size, num_periods);
617 if( alsa_handle < 0 )
618 exit(20);
621 /* tell the JACK server that we are ready to roll */
623 if (jack_activate (client)) {
624 fprintf (stderr, "cannot activate client");
625 return 1;
628 while(1) {
629 usleep(500000);
630 if( output_new_delay ) {
631 printf( "delay = %d\n", output_new_delay );
632 output_new_delay = 0;
634 printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset );
637 jack_client_close (client);
638 exit (0);