Rendering Sounds
Once you've created all your sound buffers and loaded them with sounds, you're ready to rock. (Of course, you're allowed to create and destroy sounds on-the-fly if you want.) DirectSound has a number of control functions to play sounds and alter their parameters as they play. You can change the volume, frequency, stereo panning, and so forth.
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 */ }
|