LinuxDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


An Introduction to Linux Audio
Pages: 1, 2, 3, 4

JACK

If you listened to the podcast chat with Paul Davis, you'll have caught me saying something like: What do you think is the best way into Linux Audio programming, ALSA? And him saying that, actually, JACK would usually be the best way to go, for the reason that there's a higher level of abstraction, so dealing with the sound card stuff is easier and requires less code.



JACK Audio Connection Kit was put together by Paul Davis and others from the Linux Audio Dev mailing list. The primary ideas of the thing are to allow audio apps on POSIX-compliant operating systems (e.g., Linux, BSD, Mac OS X) to interchange data while running, and also to provide a higher level of abstraction so that developers can concentrate more on the core functionality of their programs. An added advantage is that porting from Linux to Mac OS X is trivial if you're using X11 or it's a command line app.

Here is a simple client that shows the basic features of JACK. The typical steps as listed on the JACK site are:

  • Calling jack_client_open() to connect to the JACK server.
  • Registering "ports" to enable data to be moved to and from your application.
  • Registering a "process callback" which will be called at the right time by the JACK server.
  • Telling JACK that your application is ready to start processing data.
The main interface is jack.h, which is the only call made in the following example (from this LXR project page on SourceForge). Needless to say, a thorough study of this in conjunction with existing code (code reuse!) is a good place to start.

/** @file simple_client.c
  *
  * @brief This is very simple client that demonstrates the basic
  * features of JACK as they would be used by many applications.
  */
   
  #include 
  #include 
  #include 
  #include 
  #include 
  #include 
  
  jack_port_t *input_port;
  jack_port_t *output_port;
  
  /**
   * The process callback for this JACK application.
   * It is called by JACK at the appropriate times.
   */
  int
  process (jack_nframes_t nframes, void *arg)
  {
       jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes);
       jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes);
  
       memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);
          
       return 0;      
  }
  
  /**
   * This is the shutdown callback for this JACK application.
   * It is called by JACK if the server ever shuts down or
   * decides to disconnect the client.
   */
  void
  jack_shutdown (void *arg)
  {
  
       exit (1);
  }
  
  int
  main (int argc, char *argv[])
  {
       jack_client_t *client;
       const char **ports;
  
       if (argc < 2) {
               fprintf (stderr, "usage: jack_simple_client \n");
               return 1;
       }
  
       /* try to become a client of the JACK server */
  
       if ((client = jack_client_new (argv[1])) == 0) {
               fprintf (stderr, "jack server not running?\n");
               return 1;
       }
  
       /* tell the JACK server to call `process()' whenever
          there is work to be done.
       */
  
       jack_set_process_callback (client, process, 0);
  
       /* tell the JACK server to call `jack_shutdown()' if
          it ever shuts down, either entirely, or if it
          just decides to stop calling us.
       */
  
       jack_on_shutdown (client, jack_shutdown, 0);
  
       /* display the current sample rate. 
       */
  
       printf ("engine sample rate: %" PRIu32 "\n",
               jack_get_sample_rate (client));
  
       /* create two ports */
  
       input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
       output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  
       /* tell the JACK server that we are ready to roll */
  
       if (jack_activate (client)) {
               fprintf (stderr, "cannot activate client");
               return 1;
       }
  
       /* connect the ports. Note: you can't do this before
          the client is activated, because we can't allow
          connections to be made to clients that aren't
          running.
       */
  
       if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == NULL) {
              fprintf(stderr, "Cannot find any physical capture ports\n");
              exit(1);
       }
 
       if (jack_connect (client, ports[0], jack_port_name (input_port))) {
              fprintf (stderr, "cannot connect input ports\n");
       }
 
       free (ports);
         
       if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) {
              fprintf(stderr, "Cannot find any physical playback ports\n");
              exit(1);
       }
 
       if (jack_connect (client, jack_port_name (output_port), ports[0])) {
              fprintf (stderr, "cannot connect output ports\n");
       }
 
       free (ports);
 
       /* Since this is just a toy, run for a few seconds, 
       then finish */
 
       sleep (10);
       jack_client_close (client);
       exit (0);
 }
 

Pages: 1, 2, 3, 4

Next Pagearrow




Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!


Linux Resources
  • Linux Online
  • The Linux FAQ
  • linux.java.net
  • Linux Kernel Archives
  • Kernel Traffic
  • DistroWatch.com


  • Sponsored by: