Tricks of the Windows Game Programming Gurus:Sounding Off with DirectSound and DirectMusic

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

### Making DirectSound Talk Back

You may be wondering if there is any way to query DirectSound for information about the sound system or a sound that is playing, like finding out whether the sound is done. Of course there is! DirectSound has a number of functions to do stuff like that. First, here’s the general DirectSound capability function to determine the capabilities of your hardware:

    HRESULT GetCaps(LPDSCAPS lpDSCaps); // ptr to DSCAPS structure

The function simply takes a pointer to a `DSCAPS` structure and fills it in. Here’s the `DSCAPS` structure for your reference (you’ll have to refer to the DirectX SDK for more complete descriptions of these fields, but most of them are decipherable by their names):

    typedef {

        DWORD  dwSize;

        DWORD  dwFlags;

        DWORD  dwMinSecondarySampleRate;

        DWORD  dwMaxSecondarySampleRate;

        DWORD  dwPrimaryBuffers;

        DWORD  dwMaxHwMixingAllBuffers;

        DWORD  dwMaxHwMixingStaticBuffers;

        DWORD  dwMaxHwMixingStreamingBuffers;

        DWORD  dwFreeHwMixingAllBuffers;

        DWORD  dwFreeHwMixingStaticBuffers;

        DWORD  dwFreeHwMixingStreamingBuffers;

        DWORD  dwMaxHw3DAllBuffers;

        DWORD  dwMaxHw3DStaticBuffers;

        DWORD  dwMaxHw3DStreamingBuffers;

        DWORD  dwFreeHw3DAllBuffers;

        DWORD  dwFreeHw3DStaticBuffers;

        DWORD  dwFreeHw3DStreamingBuffers;

        DWORD  dwTotalHwMemBytes;

        DWORD  dwFreeHwMemBytes;

        DWORD  dwMaxContigFreeHwMemBytes;

        DWORD  dwUnlockTransferRateHwBuffers;

        DWORD  dwPlayCpuOverheadSwBuffers;

        DWORD  dwReserved1;

        DWORD  dwReserved2;

    } DSCAPS, *LPDSCAPS;

You would call the function like this:

    DSCAPS dscaps; // hold the caps

    if (FAILED(lpds->GetCaps(&dscaps)))

        { /* error */ }

Then you can test any of the fields you want and determine what capabilities your sound hardware has. There’s also a similar function for a DirectSound buffer that returns a `DSBCAPS` structure:

    HRESULT GetCaps(LPDSBCAPS lpDSBCaps); // ptr to DSBCAPS struct

Here, a `DSBCAPS` structure looks like this:

    typedef struct {

     DWORD dwSize;  // size of structure, you must set this

     DWORD dwFlags; // flags buffer has

     DWORD dwBufferBytes;        // size of buffer

     DWORD dwUnlockTransferRate; // sample rate

     DWORD dwPlayCpuOverhead;    // percentage of processor needed

                                 // to mix this sound

    } DSBCAPS, *LPDSBCAPS;

Here’s how you would check out the sound buffer `lpdsbuffer` that you’ve been using in the examples:

    DSBCAPS dsbcaps; // used to hold the results

    // set up the struct

    dsbcaps.dwSize = sizeof(DSBCAPS); // ultra important

    // get the caps

    if (FAILED(lpdsbuffer->GetCaps(&dsbcaps)))

       { /* error */ }

That’s all there is to it. Of course, there are functions to retrieve the volume, pan setting, frequency, etc. of any sound buffer, but I’ll let you look those up yourself.

The last `get` function I want to show you is used to determine the status of a playing sound buffer:

    HRESULT GetStatus(LPDWORD lpdwStatus); // ptr to result

Just call the function from the interface pointer of the sound buffer you’re interested in with a pointer to the `DWORD` where you want the status to be stored, like this:

    DWORD status; // used to hold status

    if (FAILED(lpdsbuffer->GetStatus(&status)))

      { / * error */ }

The data in the status will be one of the following:

  • `DSBSTATUS_BUFFERLOST`—Something happened to the buffer. Very bad.
  • `DSBSTATUS_LOOPING`—The sound is playing in looped mode.
  • `DSBSTATUS_PLAYING`—The sound is currently playing. If this bit isn’t set, the sound is not playing at all.

### Reading Sounds from Disk

Unfortunately, DirectSound has no support for loading sound files. I mean no support. No `.VOC` loader, no `.WAV` loader, no nothing! It’s a darn shame. So, you’ll have to write one yourself. The problem is that sound files are extremely complex, and it would take half a chapter to do a good job of explaining them. So what I’m going to do is give you a `.WAV` loader and explain how it works in general.

> Tip: The guys at Microsoft got sick of writing their own `.WAV` loaders, along with a lot of other utility functions, so they wrote one that you can use if you want. The only problem is, the API isn’t standard and will probably change. But if you’re interested, check out all the goodies in `DDUTIL*.CPP|H`, located in one of the `SOURCE` directories of the SDK install, usually in the `SAMPLES` or `EXAMPLES` directory.

#### The .WAV Format

The `.WAV` format is a Windows sound format based on the `.IFF` format originally created by Electronic Arts. IFF stands for Interchange File Format. It’s a standard that allows many different file types to be encoded using a general header/data structure with nesting. The `.WAV` format uses this encoding, and although it’s very clean and logical, it’s a pain to read the files in. You must parse a lot of header information, which takes a lot of code, and then you have to extract the sound data.

The parsing is so difficult that Microsoft created a set of functions called the multimedia I/O interface (MMIO) to help you load `.WAV` files and other similar types. All the functions of this library are prefixed with `mmio*`. The moral of the story is that writing a `.WAV` file reader isn’t that easy, and it’s tedious programming that has nothing to do with game programming. So, I’m just going to give you a heavily commented `.WAV` loader and a little explanation. If you want more, find a good reference on sound file formats.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.