Page 1 of 1

Custom ambient sounds using cvars

Posted: Sun Jan 08, 2012 3:34 am
by frag.machine
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:

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"};
2) Above S_Init (), let's declare our function to set those sounds with the values in our just created cvars:

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);}
}
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 ():

Code: Select all

ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
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:

Code: Select all

  // ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
  // ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
  S_UpdateContentSounds ();
5) And finally, after the following line:

Code: Select all

Cvar_RegisterVariable(&_snd_mixahead, NULL);
Let's place our cvar registering code:

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);
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:

Code: Select all

W_Precache ();                              // get weapon precaches
And below this line add this:

Code: Select all

precache_sound ("ambience/lava1.wav");
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!

Re: Custom ambient sounds using cvars

Posted: Sun Jan 08, 2012 4:29 am
by Baker
fragmachine ++

In the middle of July, I was investigating what sounds and models were hardcoded into the engine (like "dland.wav" ... the fiend sound).

The environmental effects hardcoded into the engine. [So are the basic particle effects like bolt.mdl and so forth].

Re: Custom ambient sounds using cvars

Posted: Sun Jan 08, 2012 3:03 pm
by frag.machine
Yeah, hardcoded stuff like menu sounds and models are a nuisance to mappers/modders and worth a bit of effort from engine coders to become easier to work. Besides the environment sounds I am working on "cvarizing" the remaining stuff (land and water splash sounds, which models should be drawn fullbright and models used by the beam-like entities such bolts and grappling hook). Once I am sure everything works and no bugs were inserted I'll put another tut.

Re: Custom ambient sounds using cvars

Posted: Sun Jan 08, 2012 7:51 pm
by revelator
could maybe be interresting to implement the sound shader system from doom3 ? :)

Re: Custom ambient sounds using cvars

Posted: Fri Jan 13, 2012 2:44 pm
by hogsy
That's certainly not a bad idea though I think using cvars is a tad bit cleaner way of doing it, especially considering that if you were to switch over to some script based system you would obviously need to provide them along with the client, and when it's simply just an engine modification it makes things seem a bit messy to me.