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

### DirectSound on the Mic

DirectSound is composed of a number of components or interfaces, just like DirectDraw. However, this is a book on game programming, so we only have time to look at the most important ones. Hence, I won’t be discussing the 3D sound component, DirectSound3D, or the sound capturing interface, DirectSoundCapture. I’m going to focus on the primary interfaces of DirectSound and that’s it. Believe me, that’s enough to keep you busy.

Figure 10.7 illustrates the relationship of DirectSound to the rest of the Windows subsystems. Notice that it is very similar to DirectDraw. However, DirectSound has a really cool feature that DirectDraw doesn’t—if you don’t have a DirectSound driver for your sound card, DirectSound will still work, but it will use emulation and the Windows DDI instead. So as long as you ship your product with the DirectSound `.DLL`s, your code will work even if the user doesn’t have DirectSound drivers for his card. It won’t be as fast, but it will still work. This is very cool.

Figure 10.7 DirectSound’s place in Windows.

DirectSound has two components as far as we are concerned:

  • A run-time `.DLL` that is loaded when you use DirectSound.
  • A compile-time library and header named `DSOUND.LIB` and `DSOUND.H`, respectively.

To create a DirectSound application, all you need to do is include these files in your application and everything should be fine.

To use DirectSound, you must create a DirectSound COM object and then request the various interfaces from the main object. Figure 10.8 illustrates the main interfaces of DirectSound:

  • IUnknown—The base COM object of all COM objects.
  • IDirectSound—The main COM object of DirectSound. This represents the audio hardware itself. If you have one or more sound cards in your computer, you’ll need a DirectSound object for each of them.
  • IDirectSoundBuffer—This represents the mixing hardware and actual sounds. There are two kinds of DirectSound buffers: primary and secondary (see how DirectSound is similar to DirectDraw?). There is only a single primary buffer, and it represents the sound that is currently playing and is mixed either by hardware (hopefully) or software. Secondary buffers represent sounds that are stored for playback. They may exist in system memory or SRAM (sound RAM) on the sound card. In either case, you can play as many secondary buffer sounds as you want as long as you have the horsepower and memory to do so. Figure 10.9 represents the relationship between the primary sound buffer and secondary sound buffers.
  • IDirectSoundCapture—You’re not going to use this interface, but like I said, it’s used to record and capture sounds. You could use it to allow the player to record his name, or, if you’re more of a techno-freak, it can be used to capture speech in real-time for voice recognition.
  • IDirectSoundNotify—This interface is used to send messages back to DirectSound. You might need this in a game with a complex sound system, but you can get along without it.

Figure 10.8 The interfaces of DirectSound.

Figure 10.9 Sound buffers.

To use DirectSound, you first create the main DirectSound object, create one or more secondary sound buffers, load them with sounds, and then play any sound you want. DirectSound will take care of the details, such as mixing. So let’s start with creating the main DirectSound object itself.

### Starting Up DirectSound

The main DirectSound object represents a sound card(s). If you have more than one sound card, you’ll have to enumerate, detect, and request their GUIDs (Globally Unique Identifiers). But if you just want to connect to the default sound device, you don’t have to mess with detection; you can simply create a DirectSound object that represents the main sound card. Here’s the interface pointer that represents a DirectSound object:

    LPDIRECTSOUND  lpds; // directsound interface pointer

To create a DirectSound object, you must make a call to `DirectSoundCreate()`, prototyped here:

    HRESULT DirectSoundCreate(

            LPGUID lpGuid, // guid of sound card

                           // NULL for default device

            LPDIRECTSOUND *lpDS,     // interface ptr to object

            IUnknown FAR *pUnkOuter) // always NULL

The preceding call is very similar to the one used to create the main DirectDraw object. In general, this stuff all looks alike; once you’ve mastered one part of DirectX, you’ve mastered them all. The problem is that Microsoft keeps adding new interfaces as fast as you can learn them! Anyway, to create a DirectSound object, do this:

    LPDIRECTSOUND lpds; // pointer to directsound object

    // create DirectSound object

    if (DirectSoundCreate(NULL, &lpds, NULL)!=DS_OK)

       { /* error */ }

Notice that the success value is now `DS_OK` (DirectSound OK) rather than `DD_OK` (DirectDraw OK). However, that was just an example to show you the new OK code. Check for success/failure like you’ve been doing using the `FAILURE()` and `SUCCESS()` macros, like this:

    // create DirectSound object

    if (FAILED(DirectSoundCreate(NULL, &lpds, NULL)))

       { /* error */ }

And of course, when you’re done with the DirectSound object, you must release it like this:

    lpds->Release();

This step occurs during the shutdown stage of your application.

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.