Any game that wants to play more than just a few sounds, or tie sounds to the game in an interesting way, needs some kind of audio engine. This can range from something as simple as an in-house sound manager with per-sample volume controls to the powerful fully dynamic sound engine that is FMOD. FMOD was recently made free for indie developers, but using it still takes someone familiar with true audio workstations and well-versed in sound design. So for the time being I will continue to use the basic audio engine I built on top of the ancient SDL_mixer. SDL_mixer is pretty bare bones, but it gets the job done.
Sounds are classified as one of four types for individual volume control and muting, enabling the player to disable only the UI sounds, for example. Notice the “GAME” designation in the image above--those are primary map-based/action-related sounds. The number range (10-20) and “LINEAR” are describing volume falloff as discussed in the earlier ambient sound post. (That post also covers terrain-based sound dampening.)
You can also see that a single “sound” (the name listed far left) may actually contain multiple possibilities (the samples listed on the right). Common sounds that you don’t want to sound too repetitive should have multiple variations to select from at play time. A Rocket Array fires a lot of rockets; it would be quite dull if they all sounded exactly the same. This is the kind of thing FMOD (and libraries like OpenAL) can do in the game itself, but I’m using the poor man’s solution: groups of similar sound samples pre-loaded and stored separately.
But it gets better!
After some testing I was dissatisfied with the general lack of variation when firing volleys. While there may be a huge number of different weapons, for at least some duration you’re firing a lot of the same ones again and again, and aside from those which absolutely must have more than one sound, most have only one. Thus you end up repeatedly hearing the same handful of sounds until you’re damn happy when the enemy finally blows off that gun that was already grating on your nerves.
A common solution in games is to randomly vary the pitch of sound effects by some amount. This is a staple feature of any decent audio engine, but unfortunately outside the scope of SDL_Mixer. Cogmind uses a memory-wasting workaround that’s better than nothing: Just copy the sound to a temporary buffer, modify the pitch, play it, then delete it… This feature was added after I took the screenshots above, so you don’t see the new data column which allows one to specify a maximum pitch deviation on a per-sound basis. Putting a value like “2” in that column would mean the sound is actually played at 98% to 102% of its original pitch. Note that pitch variation does not work for all sounds, nor is it desired in some cases--UI sounds should be static, for example.
If it’s still not good enough for you, or you prefer to blast your own music in the background anyway, the game can also run without any sound files at all (it just doesn’t play what it can’t find), making for a much slimmer download for those who will mute the audio anyway. Of course sound is still a highly recommended part of the experience.
Particle-SFX Interface
The highlight of Cogmind’s audio engine is the way many of the sounds are controlled: via particle scripts themselves.
Any particle can give any number of commands to the audio engine, the most simple of which is seen above: “PLAY.” Triggers are checked on each particle whenever applicable, such as at the BIRTH of a particle, or a certain DELAY after that birth. The example above shows that a Quantum Rifle projectile/particle plays its charging sound when it is created, then waits 600ms before playing the firing sound (not shown: the particle delays its movement for 600ms as well, to wait for the charging animation and sound to finish). The sounds are template variables because there are multiple Quantum Rifle variants.
Other commands include the ability to stop sounds, as for making a rocket flight sound continue until the moment of impact, or exert finer control by playing sounds only on certain script-defined channel groups.
By necessity many of the game’s sound effects are played and controlled through this system--after all, most are related to particles. Some are of course played internally, such as UI sounds.
Others use a separate script-based system:
Material-based SFX
Any game that tries to maintain at least a semblance of realistic audio experience must consider that objects hitting other objects make unique sounds. Metal on wood, stone on stone, wood on dirt…
Cogmind imports the material-based sound system used in X@COM, where it is far more extensive given the greater variety of terrain in that game and usage for everything from projectile impacts to chairs falling from windows. Here it’s only used for melee attacks and dropping items, which should sound different if dropped on dirt, stone, or metal. While these could all be the same sound, making them unique certainly reinforces the fact that you’re standing in a recently-excavated earthen tunnel, cave network, or military complex.
Every item specifies what “sound class” it belongs to, such as a “small device” or “heavy slashing melee weapon,” and whenever that item is dropped or used to hit a target, the sound system looks up the target’s material for that sound class and plays it.
This is the third of a four-part series on the subject of sound effects. The first one gave an overview of sound effects in roguelikes and Cogmind, the next covered weapon sound effects, and the last looks more specifically at the details of sound design.
2 Comments
You mentioned that “A common solution in games is to randomly vary the pitch of sound effects by some amount.” If I recall correctly, DOOM varied the playback speed of monster sounds, so you got a spectrum from fast, high screams to long, deep groans. Probably less computationally intensive than changing the pitch without affecting the speed, and it was brilliant for 1993. I was very impressed when I figured it out.
Quite right. I was surprised to learn that myself recently when working on this. Modern remakes of Doom use the pitch variation method, as seen in I_SDL_StartSound() here.