Custom ambient sounds using cvars
Posted: Sun Jan 08, 2012 3:34 am
Ok, this is a small tutorial from some code I am working ATM. This will add cvars to change (and even mute) the hardcoded default sounds Quake uses when there are visible water or sky brushes. As a bonus, you will be able to also set sounds for when lava or slime are visible. I am assuming FitzQuake 0.85 without any changes as the base code, but this can be converted to a number of other engines.
1) Open up snd_dma.c, and somewhere on the top of file let's declare our cvars:
2) Above S_Init (), let's declare our function to set those sounds with the values in our just created cvars:
The ambient_sfx array holds references to the precached sounds that play when sky or water is visible to the player. The idea here is quite simple: every time this function is called, it stops any sound in execution, and redefines the ambient_sfx array with the sounds defined in the cvars (provided, of course, the corresponding cvar has any string value defined).
3) After this, find and comment these 2 lines in S_Init ():
The code above originally initializes ambient_sfx. Note that only 2 sounds are being defined (water and sky): the array itself can support more 2 sounds (for slime and lava brushes), but they are left empty in vanilla Quake (and in FitzQuake, too). But not anymore. Note also that, for the sake of retrocompatibility, we will assume by default the null sound to be played when lava or slime is visible. Therefore, the game default behavior is preserved.
4) After the 2 lines we just commented out, let's place our call to S_UpdateContentSounds:
5) And finally, after the following line:
Let's place our cvar registering code:
Note that we are passing the S_UpdateContentSounds() function to the cvar registering. This way, every time one of these 4 cvars is changed S_UpdateContentSounds() is executed, and the change reflects immediately. This is a interesting (although not standard) feature the FitzQuake engine has. If you're trying to port this to vanilla Quake I suggest to create a console command that encapsulates the function call instead. The final result will be the same, although with one more step.
And that's it. To test what we did, let's grab a looping sound for replacement (for example, the bubbling lava sound from Quake 2 will fit nicely) and copy it to the <your_quake_dir>id1/sound/ambience folder (create it if you dont have it yet). You'll need to precache the file, so you'll need to fiddle (a little bit) with QuakeC. Just open world.qc and find the line that says:
And below this line add this:
I won't enter in more details about how to do the QuakeC stuff (not the subject of the tutorial). But is really easy, trust me. 
Run your modified engine, start a new game, bring down the console and type:
sfx_lava "ambience/lava1.wav"
Now just get a bit close of the hard skill gate lava pit and hear the lava bubbling.
The ability of not only changing the existing sound effects for water and outdoor areas but also setting similar effects for lava and slime is a great resource for mappers and modders to set the environment mood. And it's easy enough to even the begginer engine coder to add.Well, that's it. Enjoy!
1) Open up snd_dma.c, and somewhere on the top of file let's declare our cvars:
Code: Select all
cvar_t sfx_water = {"sfx_water", "ambience/water1.wav"};
cvar_t sfx_wind = {"sfx_wind", "ambience/wind2.wav"};
cvar_t sfx_slime = {"sfx_slime","misc/null.wav"};
cvar_t sfx_lava = {"sfx_lava","misc/null.wav"};
Code: Select all
void S_UpdateContentSounds (void)
{
S_StopAllSounds (true);
if (sfx_water.string) {ambient_sfx[AMBIENT_WATER] = S_PrecacheSound (sfx_water.string);}
if (sfx_wind.string) {ambient_sfx[AMBIENT_SKY] = S_PrecacheSound (sfx_wind.string);}
if (sfx_slime.string) {ambient_sfx[AMBIENT_SLIME] = S_PrecacheSound (sfx_slime.string);}
if (sfx_lava.string) {ambient_sfx[AMBIENT_LAVA] = S_PrecacheSound (sfx_lava.string);}
}
3) After this, find and comment these 2 lines in S_Init ():
Code: Select all
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
4) After the 2 lines we just commented out, let's place our call to S_UpdateContentSounds:
Code: Select all
// ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
// ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
S_UpdateContentSounds ();
Code: Select all
Cvar_RegisterVariable(&_snd_mixahead, NULL);
Code: Select all
Cvar_RegisterVariable(&sfx_water, S_UpdateContentSounds);
Cvar_RegisterVariable(&sfx_wind, S_UpdateContentSounds);
Cvar_RegisterVariable(&sfx_slime, S_UpdateContentSounds);
Cvar_RegisterVariable(&sfx_lava, S_UpdateContentSounds);
And that's it. To test what we did, let's grab a looping sound for replacement (for example, the bubbling lava sound from Quake 2 will fit nicely) and copy it to the <your_quake_dir>id1/sound/ambience folder (create it if you dont have it yet). You'll need to precache the file, so you'll need to fiddle (a little bit) with QuakeC. Just open world.qc and find the line that says:
Code: Select all
W_Precache (); // get weapon precaches
Code: Select all
precache_sound ("ambience/lava1.wav");
Run your modified engine, start a new game, bring down the console and type:
sfx_lava "ambience/lava1.wav"
Now just get a bit close of the hard skill gate lava pit and hear the lava bubbling.
The ability of not only changing the existing sound effects for water and outdoor areas but also setting similar effects for lava and slime is a great resource for mappers and modders to set the environment mood. And it's easy enough to even the begginer engine coder to add.Well, that's it. Enjoy!