jack1 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

379 lines
11KB

  1. /** @file simple_client.c
  2. *
  3. * @brief This simple client demonstrates the basic features of JACK
  4. * as they would be used by many applications.
  5. */
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <alloca.h>
  12. #include <jack/jack.h>
  13. #define ALSA_PCM_OLD_HW_PARAMS_API
  14. #define ALSA_PCM_OLD_SW_PARAMS_API
  15. #include "alsa/asoundlib.h"
  16. #include <samplerate.h>
  17. typedef signed short OUTPUTSAMPLE;
  18. #define SAMPLE_RATE 48000
  19. #define PRIVATE static
  20. #define SAMPLE jack_default_audio_sample_t
  21. jack_port_t *input_port;
  22. jack_port_t *output_port1, *output_port2;
  23. jack_client_t *client;
  24. snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
  25. int rate = SAMPLE_RATE; /* stream rate */
  26. int channels = 2; /* count of channels */
  27. int buffer_time = 1000000*256 / SAMPLE_RATE; /* ring buffer length in us */
  28. int period_time = 1000000*128 / SAMPLE_RATE; /* period time in us */
  29. int target_delay = 150; /* the delay which the program should try to approach. */
  30. int max_diff = 32; /* the diff value, when a hard readpointer skip should occur */
  31. snd_pcm_sframes_t buffer_size;
  32. snd_pcm_sframes_t period_size;
  33. snd_output_t *output = NULL;
  34. snd_pcm_t *alsa_handle;
  35. SRC_STATE *src_state;
  36. static int xrun_recovery(snd_pcm_t *handle, int err)
  37. {
  38. //printf( "xrun !!!....\n" );
  39. if (err == -EPIPE) { /* under-run */
  40. err = snd_pcm_prepare(handle);
  41. if (err < 0)
  42. printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
  43. return 0;
  44. } else if (err == -ESTRPIPE) {
  45. while ((err = snd_pcm_resume(handle)) == -EAGAIN)
  46. sleep(1); /* wait until the suspend flag is released */
  47. if (err < 0) {
  48. err = snd_pcm_prepare(handle);
  49. if (err < 0)
  50. printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
  51. }
  52. return 0;
  53. }
  54. return err;
  55. }
  56. PRIVATE void audio_input_fragment(snd_pcm_t *handle, SAMPLE *left, SAMPLE *right, int length)
  57. {
  58. OUTPUTSAMPLE *outbuf;
  59. float *floatbuf, *resampbuf;
  60. int rlen;
  61. int i, err;
  62. snd_pcm_sframes_t delay;
  63. SRC_DATA src_data;
  64. if (length <= 0)
  65. return;
  66. snd_pcm_delay( handle, &delay );
  67. // Do it the hard way.
  68. // this is for compensating xruns etc...
  69. if ( delay > (target_delay + max_diff) ) {
  70. OUTPUTSAMPLE *tmp = alloca( (delay - target_delay) * sizeof( OUTPUTSAMPLE ) * 2 );
  71. snd_pcm_readi( handle, tmp, delay - target_delay );
  72. printf( "delay = %d\n", (int) delay );
  73. delay = target_delay;
  74. }
  75. if ( delay < (target_delay - max_diff) ) {
  76. snd_pcm_rewind( handle, target_delay - delay );
  77. printf( "delay = %d\n", (int) delay );
  78. delay = target_delay;
  79. }
  80. // ok... now to the resampling code...
  81. //
  82. rlen = length - target_delay + delay; //(target_delay/10) + (delay/10);
  83. outbuf = alloca( rlen * sizeof( OUTPUTSAMPLE ) * 2 );
  84. floatbuf = alloca( rlen * sizeof( float ) * 2 );
  85. resampbuf = alloca( length * sizeof( float ) * 2 );
  86. again:
  87. err = snd_pcm_readi(handle, outbuf, rlen);
  88. if ( err < 0 ) {
  89. //printf( "err = %d\n", err );
  90. if (xrun_recovery(handle, err) < 0) {
  91. //printf("Write error: %s\n", snd_strerror(err));
  92. //exit(EXIT_FAILURE);
  93. }
  94. goto again;
  95. }
  96. if ( err != rlen ) {
  97. printf( "read = %d\n", rlen );
  98. }
  99. for (i = 0; i < (rlen*2); i++) {
  100. floatbuf[i] = (float)outbuf[i] / (float)32767;
  101. }
  102. src_data.data_in = floatbuf;
  103. src_data.data_out = resampbuf;
  104. src_data.input_frames = rlen;
  105. src_data.output_frames = length;
  106. src_data.src_ratio = (double)length / (double)rlen;
  107. src_data.end_of_input = 0;
  108. src_set_ratio( src_state, src_data.src_ratio );
  109. src_process( src_state, &src_data );
  110. // for( i=0; i < length*2; i++ )
  111. // resampbuf[i] = floatbuf[i];
  112. for (i = 0; i < length; i++) {
  113. left[i] = resampbuf[i*2];
  114. right[i] = resampbuf[(i*2)+1];
  115. }
  116. //printf( "len=%d, err=%d state=%d\n", length, err, snd_pcm_state(handle) );
  117. }
  118. static int set_hwparams(snd_pcm_t *handle,
  119. snd_pcm_hw_params_t *params,
  120. snd_pcm_access_t access)
  121. {
  122. int err, dir;
  123. /* choose all parameters */
  124. err = snd_pcm_hw_params_any(handle, params);
  125. if (err < 0) {
  126. printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
  127. return err;
  128. }
  129. /* set the interleaved read/write format */
  130. err = snd_pcm_hw_params_set_access(handle, params, access);
  131. if (err < 0) {
  132. printf("Access type not available for playback: %s\n", snd_strerror(err));
  133. return err;
  134. }
  135. /* set the sample format */
  136. err = snd_pcm_hw_params_set_format(handle, params, format);
  137. if (err < 0) {
  138. printf("Sample format not available for playback: %s\n", snd_strerror(err));
  139. return err;
  140. }
  141. /* set the count of channels */
  142. err = snd_pcm_hw_params_set_channels(handle, params, channels);
  143. if (err < 0) {
  144. printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
  145. return err;
  146. }
  147. /* set the stream rate */
  148. err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0);
  149. if (err < 0) {
  150. printf("Rate %iHz not available for capture: %s\n", rate, snd_strerror(err));
  151. return err;
  152. }
  153. if (err != rate) {
  154. printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
  155. return -EINVAL;
  156. }
  157. /* set the buffer time */
  158. err = snd_pcm_hw_params_set_buffer_time_near(handle, params, buffer_time, &dir);
  159. if (err < 0) {
  160. printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
  161. return err;
  162. }
  163. buffer_size = snd_pcm_hw_params_get_buffer_size(params);
  164. /* set the period time */
  165. err = snd_pcm_hw_params_set_period_time_near(handle, params, period_time, &dir);
  166. if (err < 0) {
  167. printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
  168. return err;
  169. }
  170. period_size = snd_pcm_hw_params_get_period_size(params, &dir);
  171. /* write the parameters to device */
  172. err = snd_pcm_hw_params(handle, params);
  173. if (err < 0) {
  174. printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
  175. return err;
  176. }
  177. printf( "bs=%d, ps=%d\n", (int)buffer_size, (int)period_size );
  178. return 0;
  179. }
  180. static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
  181. {
  182. int err;
  183. /* get the current swparams */
  184. err = snd_pcm_sw_params_current(handle, swparams);
  185. if (err < 0) {
  186. printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
  187. return err;
  188. }
  189. /* start the transfer when the buffer is full */
  190. err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size );
  191. if (err < 0) {
  192. printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
  193. return err;
  194. }
  195. err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
  196. if (err < 0) {
  197. printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
  198. return err;
  199. }
  200. /* allow the transfer when at least period_size samples can be processed */
  201. err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size );
  202. if (err < 0) {
  203. printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
  204. return err;
  205. }
  206. /* align all transfers to 1 sample */
  207. err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
  208. if (err < 0) {
  209. printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
  210. return err;
  211. }
  212. /* write the parameters to the playback device */
  213. err = snd_pcm_sw_params(handle, swparams);
  214. if (err < 0) {
  215. printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
  216. return err;
  217. }
  218. return 0;
  219. }
  220. PRIVATE snd_pcm_t *open_audiofd( void )
  221. {
  222. int err;
  223. snd_pcm_t *handle;
  224. snd_pcm_hw_params_t *hwparams;
  225. snd_pcm_sw_params_t *swparams;
  226. snd_pcm_hw_params_alloca(&hwparams);
  227. snd_pcm_sw_params_alloca(&swparams);
  228. if ((err = snd_pcm_open(&(handle), "hw:0", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK )) < 0) {
  229. printf("Capture open error: %s\n", snd_strerror(err));
  230. return NULL;
  231. }
  232. if ((err = set_hwparams(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED )) < 0) {
  233. printf("Setting of hwparams failed: %s\n", snd_strerror(err));
  234. return NULL;
  235. }
  236. if ((err = set_swparams(handle, swparams)) < 0) {
  237. printf("Setting of swparams failed: %s\n", snd_strerror(err));
  238. return NULL;
  239. }
  240. snd_pcm_start( handle );
  241. snd_pcm_wait( handle, 200 );
  242. return handle;
  243. }
  244. /**
  245. * The process callback for this JACK application.
  246. * It is called by JACK at the appropriate times.
  247. */
  248. int
  249. process (jack_nframes_t nframes, void *arg)
  250. {
  251. jack_default_audio_sample_t *out1 = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port1, nframes);
  252. jack_default_audio_sample_t *out2 = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port2, nframes);
  253. //jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes);
  254. //memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);
  255. audio_input_fragment( alsa_handle, out1, out2, nframes );
  256. //sendto( sockfd, "x", 1, 0, &destaddr, sizeof( destaddr ) );
  257. return 0;
  258. }
  259. /**
  260. * This is the shutdown callback for this JACK application.
  261. * It is called by JACK if the server ever shuts down or
  262. * decides to disconnect the client.
  263. */
  264. void
  265. jack_shutdown (void *arg)
  266. {
  267. exit (1);
  268. }
  269. int
  270. main (int argc, char *argv[])
  271. {
  272. //const char **ports;
  273. // if (argc < 2) {
  274. // fprintf (stderr, "usage: udpsync_source desthost\n");
  275. // return 1;
  276. // }
  277. // sockfd = socket( PF_INET, SOCK_DGRAM, 0 );
  278. // init_sockaddr_in( &destaddr, argv[1], 3000 );
  279. /* try to become a client of the JACK server */
  280. src_state = src_new(SRC_SINC_FASTEST, 2, NULL);
  281. src_set_ratio( src_state, 1.0 );
  282. alsa_handle = open_audiofd();
  283. if ((client = jack_client_new ("alsa_unsynced_pcm")) == 0) {
  284. fprintf (stderr, "jack server not running?\n");
  285. return 1;
  286. }
  287. /* tell the JACK server to call `process()' whenever
  288. there is work to be done.
  289. */
  290. jack_set_process_callback(client, process, 0);
  291. /* tell the JACK server to call `jack_shutdown()' if
  292. it ever shuts down, either entirely, or if it
  293. just decides to stop calling us.
  294. */
  295. jack_on_shutdown(client, jack_shutdown, 0);
  296. /* display the current sample rate.
  297. */
  298. printf("engine sample rate: %" PRIu32 "\n",
  299. jack_get_sample_rate (client));
  300. /* create two ports */
  301. // input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
  302. output_port1 = jack_port_register(client, "output1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  303. output_port2 = jack_port_register(client, "output2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  304. /* tell the JACK server that we are ready to roll */
  305. if (jack_activate(client)) {
  306. fprintf (stderr, "cannot activate client");
  307. return 1;
  308. }
  309. while (1) sleep(1);
  310. jack_client_close(client);
  311. exit (0);
  312. }