Fundamentals of Audio and Video Programming for Games (Pro-Developer)

To play 3-D sounds, the first thing that you may want to do is place the 3-D listener. The listener object has been created by the call to initConcertina , and all you have to do is provide the 3-D vectors containing their position, velocity and orientation.

The syntax for the call to set listener properties is shown.

void Set3DListenerProperties(D3DVECTOR* pvPosition, D3DVECTOR* pvVelocity, D3DVECTOR* pvOrient, bool fInitialize = false, float Doppler = 1.0f, float distance = 1.0f, float rolloff = 1.0f);

The first call to this function enables the Doppler factor, distance factor and rolloff factor to be changed from their defaults. For more details, see Chapter 3.

You could embed the following three structures in a listener class of your own.

D3DVECTOR vListenerPosition; D3DVECTOR vListenerVelocity; D3DVECTOR vListenerOrient;

These should be initialized with appropriate real-world coordinates (see the  Concertina.cpp file for an example), and if we wanted to exaggerate the Doppler effect, the first call to Set3DListenerProperties should be the following.

Concertina.Set3DListenerProperties(&vListenerPosition,&vListenerVelocity, &vListenerOrient,true,2.0f);

Note that the fInitialize flag is set to true, and the 2.0f value will double the Doppler effect; however, the defaults for distance factor and rolloff factor are not changed. All future calls to change the listener s position can drop any reference to the flag, as its default is to be set to false.

You would have a similar set of vectors for all your moving objects in the game, and initialize those properties with a call to Set3DSoundProperties .

bool Set3DSoundProperties(soundBufferRef* sID, D3DVECTOR* pvPosition, D3DVECTOR* pvVelocity, D3DVECTOR* pvCone, bool fChangeCone = false, int maxVradius = 1.0f, int insideCone = 360, int outsideCone = 360, int outsideVolume = 100);

For example, for a snowmobile class, that class might have the following three data members .

D3DVECTOR vSnowPosition; D3DVECTOR vSnowVelocity; D3DVECTOR vSnowOriententation;

The orientation vector is the orientation of the sound cone, so if you wanted a rear- facing cone, then this vector would be the opposite vector to the velocity. We are assuming that the sound cone is unlikely to change very often, so the fChangeCone flag should be set to true if you need to change the volume radius or the sound cone angles.

Set up the 3-D properties before calling play3DSoundBuffer , and then again at any time after that to change them.

bool play3DSoundBuffer(soundBufferRef* sID, bool loopit = false, bool fFreeOnCompletion = false);

This method obviously sets off a 3-D sound, taking the address of the soundBufferRef structure, and optional looping and free-on-completion flags.

To create the sound of a running engine, set the looping flag to true and the fFreeOnCompletion flag to false. However, for a breaking glass sound, the reverse is probably true, since you don t want it to loop but you do want the buffer to become free after it has played . For example, say we have a snowmobile with a soundBufferRef structure for its engine and another for wind noise.

// Place the snowmobile engine and wind noise correctly. Set3DSoundProperties(&sIDengine, vSnowPosition, vSnowVelocity, vSnowOriententation); Set3DSoundProperties(&sIDwindNoise, vSnowPosition, vSnowVelocity, vSnowOriententation); // Start playing the sounds. play3DSoundBuffer(&sIDengine,true); play3DSoundBuffer(&sIDwindNoise,true); // Add the sound of the snowmobile colliding with a tree. play3DSoundBuffer(&sIDcollision,false,true); // Stop the snowmobile's engine. stopSoundBuffer(&sIDengine);

You would obviously want to add code to change the frequency or volume of the engine and wind noise, depending on factors like the snowmobile s speed and exposure to the wind. This could be done by frequency and volume changes, or by adding special effects. The previous example shows that while many 3-D sounds loop, some do not (like the collision) so the fFreeOnCompletion flag should usually be set to true in the case of occasional non-looping sounds. Unless, of course, you plan to have a lot of collisions, and don t want to risk losing the sound buffer to another snowmobile driver.

The call to change volume is the same as for ambient sounds (see the setBufferVolume method in Step 8). To change frequency, use the following method.

bool set3DBufferFrequency(soundBufferRef* sID, DWORD dwFrequency);

Most frequency changes are likely to be multiplications or divisions of the recorded frequency, so you will need to get and store the recorded frequency before making any calls to change it, using the following call.

DWORD getSoundFrequency(soundBufferRef* sID);

For example, use the following to increase the frequency of a snowmobile engine sound referenced by snowID .

DWORD snowFrequency = getSoundFrequency(&snowID); Set3DBufferFrequency(&snowed, snowFrequency * 1.5f);

Note that the getSoundFrequency method always returns the original recorded frequency, not the frequency to which it may have been subsequently changed. It is possible to set different frequencies on different buffers containing the same sound.

Before any changes to 3-D sounds will take effect, you must call the following method.

void commitAllSettings();

Typically, this call would be at the end of your timing function. For an example, see the OnTimer function in the  Concertina.cpp file.

Performance Tip

If a sound no longer requires 3-D processing, it is a good idea to turn off this processing. An example might be where a player in an adventure game picks up an object emitting a sound. The object is then no longer moving in relation to the listener, and the listener is within the minimum distance for the sound produced by that object. To turn off 3-D processing, use the DirectSound SetMode method for a sound buffer, with the DS3DMODE_DISABLE flag as its first parameter. You may want to add a method to the Concertina framework that does this.

 

Категории