LINUX GAZETTE
[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


CSL, The Common Sound Layer

By Jeff Tranter


The Problem

Imagine you're writing a cool new game for Linux, and like any modern game, it has to support sound. There are a number of sound toolkits out there, but if you're like many game programmers, you just talk directly to the audio device, /dev/dsp, which gives you maximum flexibility and performance.

Your game is looking good, so you pass a copy to a friend to try out. Strangely, the sound doesn't work. It turns out your friend runs the GNOME desktop, and under GNOME the sound device is taken over by the esd sound server. GNOME applications are supposed to talk to esd, not directly to the sound device. So you go back, learn the esd API, and add an option to your program to work with esd.

You now pass the game over to a second friend to test, and again sound doesn't work for her. She likes to run the KDE desktop, and under KDE the sound device is managed by the artsd sound server. So you spend a couple more evenings learning the artsd sound API and adding support to your game so it can work with KDE too.

A third friend has heard about this great game and wants to try it too. He is running Solaris on a Sun workstation, but that's okay, he can just recompile the code for his architecture. Unfortunately sound does not work properly, because the Solaris sound device and APIs are not the same as on Linux. You could work on adding support for Solaris too (if you had access to a Solaris machine), but what about the friend who runs AIX, and the one who uses the Network Audio Server (NAS), and the one who uses the ALSA kernel drivers? Just providing basic support for sound is getting to be a lot of work. It's too bad you can't just write the program once and have it work on all platforms.

Enter CSL, the Common Sound Layer.

What is CSL?

CSL is intended to solve just this problem. CSL is the Common Sound Layer, a C-based API for sound programming. CSL is intended to address the problem of providing sound support in applications independently of the underlying sound drivers. It also hopes to become the common library for sound support under the KDE and GNOME projects.

It currently works on Linux systems using the OSS sound drivers and the aRts sound library (which runs on both KDE and GNOME desktop environments). Applications that use CSL have no further dependencies on any libraries or other components.

CSL was designed to provide similar performance to platform-specific code, with support for latency management and full duplex. This makes it particularly suitable for real-time type applications such as games.

CSL is somewhat unique in that, despite all the talk of "desktop wars" between KDE and GNOME, it is being co-operatively developed by Stefan Westerfeld, a KDE developer, and Tim Janik, a GNOME developer.

Features

CSL is currently available as preview version 0.1.2 which includes:

CSL has some limitations, mostly by design: it is a C API only, so don't expect an object-oriented interface. It is a low-level API for digital audio only (no MIDI, no mixer, no codecs for complex formats like MP3). If you want features like 3D sound, you should look at something like OpenAL.

Currently, it supports only the OSS sound drivers or the aRts sound server. (aRts ships with KDE, and there is a GNOME version. Many multimedia applications like xmms and the RealVideo player will work under aRts as well).

While CSL is not finished yet, the API is quite stable and most of the functionality is there.

Obtaining and Installing CSL

In order to use CSL, you need a Linux system with working sound drivers (either OSS or something compatible with it like OSS/4Front or ALSA with OSS emulation). If you want aRts support, you need aRts version 0.5.4 or later, which is included in KDE 2.2, or a standalone version can be obtained from http://www.arts-project.org. If you are running GNOME, there is a special version of aRts for GNOME available there are well. Other than that, you only need the usual development tools like gcc, gld, and the GNU auto tools.

CSL is currently only provided in source format. You need to download the tar archive from http://www.arts-project.org/download/csl-0.1.2.tar.gz (there may be a newer version available by the time you read this).

Building and installing CSL follows the usual GNU build procedure, documented in the file INSTALL. Briefly, you need to run the commands:

%./configure
% make
% make install

The last must be done as user root. To test CSL, you can run two of the included utility programs. The testsine program generates raw samples for a 440 Hertz sine wave and cslcat accepts raw sound sample from standard input and sends them to the audio output device. Piping them together like this

% tests/testsine | csl/cslcat

should produce one second of a 440 Hertz sine wave tone (the above command assumes you are in the main CSL source directory).

If you have any raw sound files, you can try playing one with the cslcat utility, for example:

% cslcat -r 44100 -w 8 -c 1 /usr/lib/games/koules/start.raw

You can also try the programs in the examples directory.

An Example

I'll go through a short but complete example program that uses CSL. This is based on the program cslpcm1.c that is included in the CSL release (I've removed comments and error checking code here for brevity). There are additional examples included with CSL that illustrate more of the API functions. A text version of the program is available here.

 1  #include <unistd.h>
 2  #include <stdio.h>
 3  #include <fcntl.h>
 4  #include <csl/csl.h>
 5
 6  int main (int argc, char **argv)
 7  {
 8      const int size = 1024;
 9      CslDriver *driver;
10      CslPcmStream *stream;
11      CslOptions options;
12      short buffer[size];
13      int i, j, fd;
14
15      options.n_channels = 2;
16      options.rate = 44100;
17      options.pcm_format = CSL_PCM_FORMAT_S16_LE;
18      csl_driver_init (NULL, &driver);
19      csl_pcm_open_output (driver, "cslpcm1", options.rate, options.n_channels, options.pcm_format, &stream);
20      fd = open("/dev/urandom", O_RDONLY);
21      for (i = 0; i < 500; i++)
22      {
23          read(fd, buffer, size);
24          for (j = 0; j < size; j++)
25              buffer[j] = CLAMP(buffer[j], -4000, 4000);
26              csl_pcm_write (stream, size, buffer);
27      }
28      csl_pcm_close (stream);
29      csl_driver_shutdown (driver);
30      return 0;
31  }

In line 4 we include <csl/csl.h>, the header file that defines all of the CSL API functions.

In lines 9-11 we declare variables to hold some of the important CSL data types. A CslDriver is a handle associated with a particular backend driver. A CslPcmStream is a PCM audio stream, associated with a CSLDriver, opened for either input or output, and with specific sampling parameters. It is used much like a file descriptor. The type CslOptions stores options for a CslPcmStream. For convenience, CSL can parse standard command line options for sampling parameters and put them in a CslOptions variable.

Lines 15-17 set the PCM options: number of channels, sampling rate, and data format. In this case two channels (stereo), at a 44100 sample per second rate, using 16-bit signed little-endian samples.

Line 18 obtains a handle to a CslDriver. We could have specified the backend to use (e.g. "oss" or "arts") but the special value of NULL instructs CSL to select a driver automatically. You can also ask CSL to return a list of available drivers.

In line 19, using the driver handle, we pass the sampling options and receive a handle to the CslPcmStream, in this case an output stream for sound playback. If we wanted to perform sound recording we would have opened an input stream.

In line 20 of the example we open the Linux random device. We are going to use it to obtain random numbers which we will send to the sound device.

Lines 22-27 form a loop in which we read data from /dev/urandom into a buffer and then write the data to the PCM stream using csl_pcm_write. Because the data is random, it can contain large sample values which may be quite loud. We use the convenience macro CLAMP provided by CSL to constrain the value within a smaller range (recall that here we are working with 16-bit signed values). The result of writing the random data to the sound device should be a hissing sound from the speaker. This white noise of no particular frequency confirms that the random number generator device is indeed a good source of random data.

In lines 28-29, after looping 500 times (which corresponds to about 3 seconds), we clean up by closing the stream and shutting down the driver.

By studying this and the other examples, and looking at the HTML API documentation, you should quickly get a feel for how to use the library.

Porting Applications to CSL

It is relatively straightforward to port applications that use the OSS sound drivers to CSL. You will then have an application that will work nicely under systems running aRts, and still work with the kernel sound drivers. As an example, I ported a sound application I had written (wave), which consisted of about 550 lines of C code, in about an hour. Many of the CSL API functions, like csl_pcm_write, are similar to the underlying C library functions commonly used for sound programming, like write.

Current Status and Future Plans

CSL is currently in a preview release. Work remains to finish some missing features, perform testing, and fix bugs. Possible work in the future includes implementing support for artsc (the C API for arts) and the esound API used by GNOME. Stable releases should also be made available as binary packages.

Conclusions

I believe CSL offers a solution to the problem of incompatible sound support, especially on Linux desktop environments, and therefore deserves attention from multimedia developers. I invite you to try CSL, consider using it in your existing or new applications, and maybe even help contribute to it.

References

  1. CSL HOWTO and FAQ (included in CSL source code)
  2. CSL API Documentation (included in CSL source code, generated using Doxygen)
  3. Source code for CSL 0.1.2
  4. Release announcement for CSL 0.1.2
  5. Release announcement for GNOME aRts 0.1.2
  6. Home page for the aRts Project

There is a mailing list for CSL. You can join the list by sending a message with the word subscribe as the message body to csl-request@space.twc.de. The mailing list is archived at http://www.mail-archive.com/csl@space.twc.de.

Jeff Tranter

Jeff Tranter has been using Linux since 1992. He is the author of the Linux Sound and CD-ROM HOWTOs and the O'Reilly book Linux Multimedia Guide. He has worked in a number of diverse areas of Linux, most recently on the KDE desktop environment focusing on multimedia. He is currently employed at a new Linux company, Xandros Corporation.


Copyright © 2001, Jeff Tranter.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 70 of Linux Gazette, September 2001

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]