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

Here we finally address how special effects are applied to wave files.

In the description of the OnTimer function in the last chapter, we left out the following two calls that come before the function Set3DSoundProperties .

soundEffect[i].getSpecialEffectsArray(rSFX); FXData = soundEffect[i].getSpecialEffectsData(); Set3DSoundProperties( .); play3DSoundBuffer(soundEffect[i].getSoundIndex(), soundEffect[i].getBufferIndex(), true, rSFX, FXData);

The getSpecialEffectsArray method simply returns an array of ones or zeros (flags) indicating whether a special effect is to be applied or not. The code for this method is written as follows .

void getSpecialEffectsArray(int rSFX[max_specialeffects]) { int i; for (i=sfx_chorus; i< sfx_chorus + max_specialeffects; i++) { rSFX[ i - sfx_chorus ] = setting[i]; } }

The rSFX array has nine elements, so it includes a flag for the environmental effect. The defines starting with sfx_chorus are the positions of these flags in the settings array of the cSoundEffect class (for example, sfx_chorus is 16). However, in the rSFX array, the ESFXType enumeration is used to determine the location of the flags.

Following the retrieval of this array of flags is the retrieval of the parameter data itself, with the following line.

FXData = soundEffect[i].getSpecialEffectsData();

The getSpecialEffectData method treats the environmental flag differently from the rest, because the Rumpus tool supports all the preset environmental locations but does not adjust the parameters for these locations (this task is left as an exercise for the reader).

CSoundFXData* getSpecialEffectsData() { // Load in environmental data if required. if (setting[sfx_environment] == 1) { CopyMemory(&SoundFXData -> m_paramsEnvironment, &envValues[ setting[sfx_enviroReverb] ], sizeof(DSFXI3DL2Reverb)); } return SoundFXData; }

The parameters for a CopyMemory call are destination , source , and then the number of bytes to copy. The envValues structure has been defined in order to make it easy for you to add your own environment, which we will do later in this chapter. For the moment, this structure supports the environments that are pre-defined in DirectSound.

struct _DSFXI3DL2Reverb envValues[max_environments] = { I3DL2_ENVIRONMENT_PRESET_DEFAULT, I3DL2_ENVIRONMENT_PRESET_GENERIC, I3DL2_ENVIRONMENT_PRESET_PADDEDCELL, I3DL2_ENVIRONMENT_PRESET_ROOM, I3DL2_ENVIRONMENT_PRESET_BATHROOM, I3DL2_ENVIRONMENT_PRESET_LIVINGROOM, I3DL2_ENVIRONMENT_PRESET_STONEROOM, I3DL2_ENVIRONMENT_PRESET_AUDITORIUM, I3DL2_ENVIRONMENT_PRESET_CONCERTHALL, I3DL2_ENVIRONMENT_PRESET_CAVE, I3DL2_ENVIRONMENT_PRESET_ARENA, I3DL2_ENVIRONMENT_PRESET_HANGAR, I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY, I3DL2_ENVIRONMENT_PRESET_HALLWAY, I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR, I3DL2_ENVIRONMENT_PRESET_ALLEY, I3DL2_ENVIRONMENT_PRESET_FOREST, I3DL2_ENVIRONMENT_PRESET_CITY, I3DL2_ENVIRONMENT_PRESET_MOUNTAINS, I3DL2_ENVIRONMENT_PRESET_QUARRY, I3DL2_ENVIRONMENT_PRESET_PLAIN, I3DL2_ENVIRONMENT_PRESET_PARKINGLOT, I3DL2_ENVIRONMENT_PRESET_SEWERPIPE, I3DL2_ENVIRONMENT_PRESET_UNDERWATER, I3DL2_ENVIRONMENT_PRESET_SMALLROOM, I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM, I3DL2_ENVIRONMENT_PRESET_LARGEROOM, I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL, I3DL2_ENVIRONMENT_PRESET_LARGEHALL, I3DL2_ENVIRONMENT_PRESET_PLATE };

You will find the definition of these defines in dsound .h; as an example, here is the definition for the underwater environment.

#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER -1000,-4000, 0.0f, 1.49f, 0.10f, -449, 0.007f, 1700, 0.011f, 100.0f, 100.0f, 5000.0f

Note how the preset is simply a list of values, each corresponding to one data member of a DSFXI3DL2Reverb structure. This structure is listed here with its range of allowable values and defaults given as comments.

typedef struct _DSFXI3DL2Reverb { LONG lRoom; // [-10000, 0] default: -1000 mB LONG lRoomHF; // [-10000, 0] default: 0 mB FLOAT flRoomRolloffFactor;// [0.0, 10.0] default: 0.0 FLOAT flDecayTime; // [0.1, 20.0] default: 1.49s FLOAT flDecayHFRatio; // [0.1, 2.0] default: 0.83 LONG lReflections; // [-10000, 1000] default: -2602 mB FLOAT flReflectionsDelay; // [0.0, 0.3] default: 0.007 s LONG lReverb; // [-10000, 2000] default: 200 mB FLOAT flReverbDelay; // [0.0, 0.1] default: 0.011 s FLOAT flDiffusion; // [0.0, 100.0] default: 100.0 % FLOAT flDensity; // [0.0, 100.0] default: 100.0 % FLOAT flHFReference; // [20.0, 20000.0] default: 5000.0 Hz } DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb;

We will come back to the use of these define statements when we explain how to add your own environment. Also, the individual data members ( lRoom , for example) are discussed in detail in Chapter 7. For now, however, the getSpecialEffectData method adds the environmental values to the SoundFXData object, and then returns a pointer to that object.

All that happens next in the OnTimer function is that this information is passed to the Play3DSoundBuffer function.

play3DSoundBuffer(soundEffect[i].getSoundIndex(), soundEffect[i].getBufferIndex(), true, rSFX, FXData);

Note that both the array of flags and the FXData object containing all the parameter settings are passed in. Play3DSoundBuffer then makes the following call.

g_pSound[iS] -> activateSFX(iB, rSFX, FXData);

The code for the activateSFX method first checks to see if any special effects have been set, and if so, calls the SetFXEnable method on the CSoundFXManager object that is created for each CSound object.

HRESULT CSound::activateSFX(int iB, int rSFX[max_specialeffects], CSoundFXData* FXData) { int i; int anyFX = false; for (i=0; i<max_specialeffects; i++) { if (rSFX[i] == 1) { pFXManager[iB] -> SetFXEnable(i); anyFX = true; } } if (anyFX) { pFXManager[iB] -> ActivateFX(); pFXManager[iB] -> CopyAllData(FXData); pFXManager[iB] -> LoadCurrentFXParameters(); } return true; }

Note that the SetFXEnable call is made for each special effect that applies; if any apply, then one call is made to the ActivateFX , CopyAllData and LoadCurrentFXParameter methods, which are also methods of the CSoundFXManager class.

That s all you need to do. The special effects should now be loaded, ready to edit, and ready to run.

Категории