Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan

Games and SDL
SDL Installation
SDL for Embedded
SDL API
SDL Events
 SDL Graphics
SDL Threads
Thread Example
SDL Animation
SDL Sound
 Raw Video Player
Video Formats
Video Compression
 Game Trees
About The Author
@Copyright by Fore June, 2006
SDL Sound
1 2
  1. Introduction

    Sound programming is a crucial component in game programming. Without sound effects, many popular games may become bore and uninterested.

    Digital Audio Formats

    There exists many different digital audio formats, many of which are created by commercial organizations. Industrial groups like MPEG have created open standards and the most well-known one may be the MP3 audio format. The SDL sound library does not support MP3 format and a user cannot play an MP3 file using only the SDL sound library, which actually only supports Microsoft's WAV format. To play sound files other than WAV, one has to use the SDL mixer library.

    PCM

    Sound is produced by the vibration of a media like air or water. Audio refers to the sound within the range of human hearing. Naturally, a sound signal is analog, which is continuous in both time and amplitude. To store and process sound information in a computer or to transmit it through a computer network, we must first convert the analog signal to digital form using an analog-to-digital converter ( ADC ); the conversion involves two steps: (1) sampling, and (2) quantization. Different encoding schemes can be used to quantize the sound data. PCM ( Pulse Code Modulation ) is the simplest and most fundamental method of representing the quantized data in digital format.

    Sampling is the process of examining the value of a continuous function at regular intervals ( see Figure below ). We might measure the voltage of an analog waveform every millisecond, or measure the brightness of a photograph every millimeter, horizontally and vertically. Sampling usually occurs at uniform intervals, which are referred to as sampling intervals. The reciprocal of sampling interval is referred to as the sampling frequency or sampling rate. If the sampling is done in time domain, the unit of sampling interval is second and the unit of sampling rate is Hz, which means cycles per second. A higher sampling rate usually allows for a better representation of the original sound wave. However, when the sampling rate is increased up to a certain value ( twice as fast as the highest frequecy of the signal ), no further improvement can be made by further increasing the sampleing rate and at this value, the original sound wave can be completely reconstructed from the samples. This is known as the Nyquist Theorem.

    Quantization is the process of limiting the value of a sample of a continuous function to one of a predetermined number of allowed values, which can then be represented by a finite number of bits in the digital world. The following figure shows the quantization of the same signal shown above. The dashed curve is the original signal and the vertical bars show the quantized values. As shown in the figure, the height of each vertical bar can only take on certain values, shown by horizontal dashed lines. In the figure, 11 quantization levels are used and thus 4 bits are required to encode each sample. In PCM, the height of each bar is translated into a digital number. The difference between a quantized representation and an original analog signal is referred to as the quantization noise.

    In the gaming environment, a PCM sample is usally 8 or 16 bits for each channel ( one channel for mono, two channeles for stereo ) and the data are sampled at a rate of 22,050 or 44,100 Hz. The CD-quality audio use 44,100 Hz sampling rate and 16 bits amplitude. Thus, the resulting bit rate of a stereo ( 2 channels ) CD-audio stream will be

    One second of such sound data will consume about 176 kilobytes of storage.

    Just as raw pixel data are often saved in .bmp format, raw PCM sound samples are often saved in .wav format. SDL can read a .wav file with the SDL_LoadWAV() function.

  2. SDL Sound APIs

    Currently, there are two popular sets of competing Linux sound system drivers. The Open Sound System ( OSS ) consists of a set of kernel modules to provide a common interface to different kinds of sound cards; some of the modules are distributed along with the Linux kernel. The Advanced Linux Sound Architecture ( ALSA ) provides an alternate set of Linux sound drivers. On the other hand, higher-level libraries such as SDL and OpenAL ( Open Audio Library ) provide higher-level APIs for users to utilize Linux sound features. To produce sound in the SDL environment, you have to install the SDL_sound-* package. However, the SDL_sound library only supports Microsoft's .wav format and only has a limited number of functions. Practically, to integrate sound inot your application, you also need the mixer library of the package SDL_mixer-*. To distinguish functions from SDL_sound-* and those from SDL_mixer-*, the former start with prefix SDL_ while the latter starts with Mix_.

    To use the SDL sound library, you have to include in your program the header file "SDL_sound.h" by adding the statment,

    The following table lists all the functions provided by the SDL_sound library.

    Listed below are some of the functions that are used more often.

    Synopsis     #include "SDL.h"
    SDL_AudioSpec *SDL_LoadWAV(const char *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len);
    Description     Loads a WAVE file into memory. If succeeds, it returns the given SDL_AudioSpec, filled with the audio data format of the wave data, and sets audio_buf to a malloc'd buffer containing the audio data, and sets audio_len to the length of that audio buffer, in bytes. You need to free the audio buffer with SDL_FreeWAV when you are done with it.
    Returns     This function returns NULL and sets the SDL error message if the wave file cannot be opened, of if it uses an unknown data format, or is corrupt. Currently raw, MS-ADPCM and IMA-ADPCM WAVE files are supported. If succeeds, it returns the given SDL_AudioSpec.

    Synopsis     #include "SDL.h"
    void SDL_MixAudio(Uint8 *dst, Uint8 *src, Uint32 len, int volume);
    Description     This function takes two audio buffers of len bytes each of the playing audio format and mixes them, performing addition, volume adjustment, and overflow clipping. The volume ranges from 0 to SDL_MIX_MAXVOLUME and should be set to the maximum value for full audio volume. Note this does not change hardware volume.
    Returns     None.

  3. Audio Examples

    The following section presents some examples on using the SDL_sound library to process audio data; some of them are adopted from the SDL site: http://www.libsdl.org/cgi/docwiki.cgi/Audio_20Examples

    Opening Audio Device
    The following piece of code opens the audio device and sets the desired audio parameters.

       SDL_AudioSpec wanted;
        
    
        // Set the audio format 
        wanted.freq = 22050;
        wanted.format = AUDIO_S16SYS;
        wanted.channels = 2;    // 1 = mono, 2 = stereo 
        wanted.samples = 1024;  // Good low-latency value for callback 
        wanted.callback = fill_audio;
        wanted.userdata = NULL;
    
        // Open the audio device, forcing the desired format 
        if ( SDL_OpenAudio(&wanted, NULL) < 0 ) {
            fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
            return(-1);
        }
        return(0);
       

    Playing Audio

        static Uint8 *audio_chunk;
        static Uint32 audio_len;
        static Uint8 *audio_pos;
    
        /* The audio function callback takes the following parameters:
           stream:  A pointer to the audio buffer to be filled
           len:     The length (in bytes) of the audio buffer
        */
        void fill_audio(void *udata, Uint8 *stream, int len)
        {
            // Only play if we have data left 
            if ( audio_len == 0 )
                return;
    
            // Mix as much data as possible 
            len = ( len > audio_len ? audio_len : len );
            SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
            audio_pos += len;
            audio_len -= len;
        }
    
        // Load the audio data ... 
    
        ;;;;;
    
        audio_pos = audio_chunk;
    
        // Let the callback function play the audio chunk 
        SDL_PauseAudio(0);
    
        /* Do some processing */
    
        ;;;;;
    
        // Wait for sound to complete 
        while ( audio_len > 0 ) {
            SDL_Delay(100);         // Sleep 100 ms 
        }
        SDL_CloseAudio(); 
      

    The SDL_sound-xxx package has some sample programs that come with the package; the programs demonstrate how to use the SDL sound library.

Next