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

#### Playing a Sound

To play a sound buffer, use the `Play()` function as prototyped here:

    HRESULT Play(

      DWORD dwReserved1, DWORD dwReserved2,   // both 0

      DWORD dwFlags); // control flags to play

The only flag that is defined is `DSBPLAY_LOOPING`. Setting this value will cause the sound to loop. If you want it to play only once, set `dwFlags` to 0. Here’s an example of playing a sound over and over:

    if (FAILED(lpdsbuffer->Play(0,0,DSBPLAY_LOOPING)))

       { /* error */ }

Use looping for music and other stuff you want to repeat.

#### Stopping a Sound

Once you’ve started a sound, you may want to stop it before it’s finished playing. The function to do this is `Stop()`. Here’s its prototype:

    HRESULT Stop(); // that’s easy enough

Here’s how you would stop the sound you just started in the previous example:

    if (FAILED(lpdsbuffer->Stop()))

       { /* error */ }

Now you have enough for a complete demo of DirectSound. Check out `DEMO10_2.CPP|EXE` on the CD. It creates a DirectSound object and a single secondary sound buffer, and then loads the buffer with a synthesized sine wave and plays it. It’s simple, but it effectively shows you everything you need to know to play a sound.

#### Controlling the Volume

DirectSound lets you manipulate the volume or amplitude of a sound. However, this isn’t free. If your hardware doesn’t support volume changes, DirectSound will have to remix the sound with the new amplitude. This can require a little more processing power. In any case, here’s the prototype:

    HRESULT SetVolume(LONG lVolume); // attenuation in decibels

`SetVolume()` works differently than you would expect. Instead of instructing DirectSound to increase or decrease the amplitude, `SetVolume()` controls the attenuation (or anti-gain, if you will). If you send a 0, which is equal to `DSBVOLUME_MAX`, the sound will be played without attenuation—that is, at full volume. A value of -10,000 or `DSBVOLUME_MIN` will set the attenuation to maximum -100dB (decibels) and you won’t hear a thing.

The best thing to do is create a wrapper function around this so you can send a value from 0-100 or something more natural. The following macro transformation will do the job:

    #define DSVOLUME_TO_DB(volume) ((DWORD)(-30*(100 - volume)))

Here, volume is from 0-100, with 100 being full volume and 0 being totally silent. Here’s an example that will play sound at 50 percent of full volume:

    if (FAILED(lpdsbuffer->SetVolume(DSVOLUME_TO_DB(50))))

        { /* error */ }

> Note: If you’re wondering what a decibel is, it’s a measure of sound or power based on the bel, named after Alexander Graham Bell. In electronics, many things are measured logarithmically, and the decibel scale is one example. In other words, 0 dB means no attenuation, -1 dB means the sound is 1/10 its original value, -2 dB means it’s 1/100 the original value, and so on. Therefore, a sound that’s attenuated -100 dB couldn’t be heard by an ant!

> Note that on some scales, dB is also scaled by a factor of 10 (or even 2). So -10 dB would be 1/10 and -20 dB would be 1/100. It’s one of those things that everybody has their own version of: engineers, mathematicians, physicists...

#### Freaking with the Frequency

One of the coolest manipulations you can apply to a sound is to change its playback frequency. This changes the sound’s pitch (sort of), and you can make it slow and evil or fast and happy (yuck). You can make yourself sound like a chipmunk or Darth Vader in real-time! To change the frequency of playback, use the `SetFrequency()` function as shown below:

    HRESULT SetFrequency(

       DWORD dwFrequency); // new frequency from 100-100,000Hz

Here’s how you would make a sound play faster:

    if (FAILED(lpdsbuffer->SetFrequency(22050)))

        { / * error */ }

If the original sound was sampled at 11,025Hz (11KHz), the new sound would play twice as fast and have twice the pitch and play for half as long. Get it? Got it? Then get rid of it!

#### Panning in 3D

The next killer thing you can do with a sound is change the stereo pan, or the amount of power coming from each speaker. For example, if you play a sound at the same volume in both speakers (or headphones), it will seem like it’s right in front of you. But if you shift the volume to the right speaker, the sound will seem like it’s moving to the right. This is called panning and can help you create localized 3D sounds (in a crude manner).

The function to set the stereo panning is called `SetPan()`, and here’s its prototype:

    HRESULT SetPan(LONG lPan); // the pan value -10,000 to 10,000

The pan value is logarithmic again: A value of 0 is dead center, a value of -10,000 means the right channel is attenuated by -100 dB, and a value of 10,000 means that the left channel is attenuated by -100 dB. Stupid, huh? Anyway, here’s how you would attenuate the right channel by -5 dB:

    if (FAILED(lpdsbuffer->SetPan(-500)))

       { /* error */ }

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.