Introduction to soundscript concepts
Overview of a typical soundscript
Below is an example soundscript,
in a very small font. We will go over the various codes and sections in chapters
to follow. For now, examine the following code and orient yourself to the
general layout.
When someone is in
the driver seat, this sound is played.
|
|
newPatch
####################
### Engine Start ###
####################
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Start.wav
minDistance 1
dopplerOff
priority -2
*** Distance Volume ***
Sound
pathname with relative references for mod name and
sound quality
|
|
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 50
param 100
param 1
param -1
endEffect
Sound played at low
engine output.
|
|
##############
### Lo RPM ###
##############
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Low.wav
Sound
begins fading naturally 2m from source.
|
|
loop
volume 1
minDistance 2
relativePosition 0/0/0
priority 8
***
Engine start ***
Sound
fades from silence to full volume between 0.2 and 0.8
seconds after engine start.
|
|
beginEffect
controlDestination Volume
controlSource Time
envelope Ramp
param 0.2
param 0.8
param 0
param 1
endEffect
*** Engine Pitch ***
beginEffect
controlDestination Pitch
controlSource Default
envelope Linear
param 0.9
param 0.8
endEffect
*** Distance Volume ***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 15
param 65
param 1
param -1
endEffect
*** Engine Volume ***
beginEffect
controlDestination Volume
controlSource Default
envelope Ramp
param 0
param .9
param 1
param -1
endEffect
Sound
fades so silence and terminates 0.2 seconds after after engine
stops.
|
|
*** Engine stop ***
beginEffect
controlDestination Volume
controlSource TimeRelease
envelope Ramp
param 0
param 0.2
param 1
param -1
Sound played after
engine picks up speed.
|
|
endEffect
################
### Hi RPM 1 ###
################
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Medium.wav
Sound
origin is centered on vehicle. Values are x/y/z.
|
|
loop
minDistance 8
relativePosition 0/0/0
priority 8
*** Engine start ***
beginEffect
controlDestination Volume
controlSource Time
envelope Ramp
param 0.2
param 0.8
param 0
param 1
endEffect
|
|
Sound pitch is set relative to vehicle speed.
|
|
*** Engine Pitch ***
beginEffect
controlDestination Pitch
controlSource Speed
envelope Linear
param 0.4
param 0.01
endEffect
*** Distance Volume ***
Volume
ramp that fades sound from full to zero between 25
and 150m.
|
|
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 25
param 150
param 1
param -1
endEffect
*** Engine Volume ***
beginEffect
controlDestination Volume
controlSource Default
envelope Ramp
param 0
param .2
param 0
param 1
endEffect
*** Engine stop ***
beginEffect
controlDestination Volume
controlSource TimeRelease
envelope Ramp
param 0
param 0.2
param 1
param -1
Sound played while
engine is at high output.
|
|
endEffect
################
### Hi RPM 2 ###
################
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_High.wav
Chosen
.wav will loop forever until terminated.
|
|
volume 1
loop
minDistance 2
relativePosition 0/0/0
priority 8
|
|
|
|
|
On a scale of –10 to 10, this sound has a priority of 8
when competing for sound channel use with other overlapping
sounds.
|
|
|
This is a short range sound that only modifies the current
engine sound playing in HiRPM1.
|
|
|
*** Engine start ***
beginEffect
controlDestination Volume
controlSource Time
envelope Ramp
param 0.2
param 0.8
param 0
param 1
endEffect
*** Engine Pitch ***
beginEffect
controlDestination Pitch
controlSource Default
envelope Linear
param 0.75
param 0.25
endEffect
*** Distance Volume ***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 25
param 65
param 1
param -1
endEffect
*** Engine Volume ***
Engine
sound is silent at engine idle and fades to full volume
when engine output is at 50%.
|
|
beginEffect
controlDestination Volume
controlSource Default
envelope Ramp
param 0
param .5
param 0
param 1
endEffect
*** Engine stop ***
beginEffect
controlDestination Volume
controlSource TimeRelease
envelope Ramp
param 0
param 0.2
param 1
param -1
endEffect
|
|
Sound played while engine is idling.
|
|
############
### Idle ###
############
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Idle.wav
loop
minDistance 2
relativePosition 0/0/0
priority 8
*** Engine start ***
beginEffect
controlDestination Volume
controlSource Time
envelope Ramp
param 0.2
param 0.8
param 0
param 1
endEffect
*** Engine Pitch ***
beginEffect
controlDestination Pitch
controlSource Default
envelope Ramp
param 0
param 0.25
param 1
param 0.2
endEffect
*** Engine Volume ***
Idle
sound begins at full volume and fades to silence as
engine approaches 90% output.
|
|
beginEffect
controlDestination Volume
controlSource Default
envelope Ramp
param 0
param 0.9
param 1
param -1
endEffect
*** Distance Volume ***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 5
param 50
param 1
param -1
endEffect
*** Engine stop ***
beginEffect
controlDestination Volume
controlSource TimeRelease
envelope Ramp
param 0
param 0.2
param 1
param -1
endEffect
Sound played when drivers seat
is abandoned.
|
|
###################
### Engine Stop ###
###################
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Stop.wav
minDistance 2
trigger Release
Sound
waits to be played until the vehicle is “released”
|
|
dopplerOff
priority -2
*** Distance Volume ***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 50
param 100
param 1
param -1
endEffect
Soundscript titles
Consider the following code:
###################
### Engine Stop ###
###################
load @ROOT/Sound/@RTD/DesertCombat/Humvee/Humvee_Stop.wav
minDistance 2
The area set in ### is a soundscript title.
They are used throughout the soundscript to identify
the sections both to the scripter and to the engine itself. These titles
are a subject of considerable angst to the soundscripter,
as their role is often unclear. Sometimes they tell the sound engine where
to look when a specific event is called for. Other times they act merely
as labels. In some cases using your own custom labels will work without problems.
Other times it will cause an error and the particular section will be skipped.
My suggestion is to start with a soundscript from
the original BF1942 files and work from there. Use only titles defined in
those soundscripts. As we will see later, there
is a way to add comments to your soundscripts,
which will never interfere with the flow or function of the script. So in
my experience it is best to consider soundscript titles
a necessary evil. Just use them as they appear in the original files and
use your own comments to label the sections as you need.
Soundscript structure
As you can see from the example soundscript above,
there is a specific structure that is usually adhered to. A soundscript section will always be initiated by the declaration
of a sound, using the load command. If it is an entirely new section, the
command newPatch preceeds the
load command. Then, sound parameters follow, such as
the declaration of loops, stereo, and volume properties. Finally,
adjustment ramps are declared, which modify the sound further in accordance
to the behavior of the vehicle.
Here is an example layout of a soundscript section:
-
NewPatch
-
Load the .wav using the proper path
-
Declarations section. Define the priority, master
volume, looping, stereo, etc.
-
Adjustment ramps. Apply adjustments to pitch and volume according to time,
vehicle speed, engine rpms, distance, etc.
You will notice in the example soundscript provided
at the beginning, that there can be several sounds loaded under one newPatch command. Keep in mind that newPatch is
used to speak to the soundscript interpreter,
and defines the functional sections of the soundscript.
It separates out a reload section from a firing section, for instance.
Loading a sound also has a functional action, and all commands
that follow the loading of a sound are applied to that sound only. Remember
that newPatch separates different functional
sections within a soundscript, so you may load
several sounds within a newPatch section. There
is no known limit to the number of sounds you may load for each section.
There is no set rule as to where commands such as stereo,
loop, mindistance, etc. must be stated following
the load command. For organization’s sake, they are usually all declared
immediately following the use of the load command.
As a final note, the location of soundscript sections,
separated by newPatch commands, does not seem
to be pre-ordained. You should have freedom over placement of the
primary soundscript sections. However, it is
usually wise to copycat original BF1942 soundscript structure.
Soundscript commands
newPatch Using this command alerts the script interpreter
that a new sound section has begun. Use of this command is more important
for some sounds than others. For some soundscripts,
using many newPatch commands to separate out
sections is essential. For others, there is only a need for one of these
commands. You need not declare a newPatch for
every sound that you load. If you want sounds to be played simultaneously
or sequentially, you will usually group them together under one newPatch.
The command newPatch is only used to communicate
with the interpreter, so it may recognize different sections of the soundscript.
load <path>: The load command calls forth
a sound to be played from a given path. Once a sound
is loaded, all code that follows will affect that sound, until another load
command is issued. The load command can use relative pathnames to
automatically pick from a certain path. Here are some examples:
@Root: The root directory of the current mod
@RTD: The sound quality chosen by the player
@Language: The language chosen by the player
stereo: If
the sound you are going to use is in stereo, you must alert the script of
this. Use of stereo sounds negates any directional quality of the sound.
If you are in range to hear it, the sound will always sound as though it
occurred at your position.
minDistance <#>: Mindistance is
a greatly speculated upon and misunderstood command. In my experience, mindistance is the distance at which the sound begins to
naturally lose volume. If you use no volume commands on your sound, the game
will still cause it to lose volume over distance. Setting a high mindistance increases the radius at which the sound will
maintain high volume on its own.
dopplerOff: Doppler
is the raising / lowering of pitch according to the speed at which an object
is approaching / departing. The engine assumes that doppler is active unless you deactivate it through
use of this command.
priority <#>: Depending on your sound card, you
can only have 32-64 sounds playing at one time. In the middle of a firefight
there are definitely more sounds being called for than the sound card can
handle. Therefore priorities must be set as to which sounds will be heard
while others are not. All overlapping sounds are in constant competition
for being heard. You assign every sound a priority number ranging from –10
to 10, 10 being highest. There is a priority 11 but that is reserved only
for radio commands. Good decisions made on sound priorities are essential
for an effective sound environment.
loop: If
you want your sound to be played on an infinite loop, you will want to add
this command. You can still control the audibility of the sound using other
commands and especially with volume ramps and time delays. There is no command
to loop a sound a selected number of times. However, with smart use of time
/ volume parameters you can still have good control over how a sound is played.
relativePosition <x/y/z>: You can define where on the vehicle the sound will originate from.
The format of the position is x/y/z (left/right, above/below, forwards/backwards).
Care must be taken in the positioning of the sound, as a soundscript is often called from a specific component of
the vehicle and not the vehicle itself. For example, a jet engine soundscript is called from the engine, and therefore a
position of 0/0/0 will place the sound origin on the center of the engine
object.
volume <#>: You
may set the sound’s master volume peak directly using this command. The volume
value ranges from zero (silent) to one (full volume). All further volume
adjustments to the sound will be made relative to the master volume adjustment.
So, for example, if a sound’s master volume is set to 0.5, and then is later
modified to fade to 0.5 volume in a volume ramp,
the end volume will be 0.25.
randomStartPitch<min/max>: With
this command, you may set the sound to be played at a randomly selected pitch
every time it is used. The first parameter is the minimum pitch value, the second is the maximum pitch value. It is difficult
to explain the mathematics of the pitch parameters, as each follows its own
set of rules. But as an example: randomStartPitch 0.75
/ 0.25 sets a pitch range from 0.75 of the normal pitch to 1.25 of the normal
pitch. The first is a raw factor to be multiplied, the second is to be added
to 1 and then multiplied.
stop finishSample: This command is only used in conjunction
with looping sounds. It tells the sound to play through the .wav completely
before ending, even if the sound source ceases its activity. This is commonly
used in automatic firearms so that quick taps of the trigger do not cause “half-shots” to
be heard.
randomPlay: This
command requires the use of newPatch and at least
two loaded sounds. It allows the section to randomly pick between all sounds
within.
triggerVolume: This
command is only used in conjunction with a time-volume ramp. It prevents
a sound from being played immediately upon the execution of a soundscript.
Instead, the sound is begun at the defined moment the time-volume ramp is
set to raise its volume above zero. If you did not use the triggerVolume command
in a time-volume ramp, the sound would begin the moment the soundscript is run, regardless of when it is meant to be
played. You would end up with the sound volume being raised from zero in
the middle of a playing sound, which in most cases is undesirable.
#include: This command is used to load another soundscript,
which is run in parallel with the current script. It’s a great way to save
time and effort when multiple soundscripts will be expected to contain identical sections.
It also allows for the execution of special soundscript commands
that do not work well together. Here is an example of
the #include command used for ejected shell cases:
####################
### Shell Bounce ###
####################
newPatch
#include
../../../Common/Sounds/ShellBounce.ssc
***: Use
three subsequent asterisks to begin a comment. These are ignored by the interpreter
and are a great way to organize your soundscripts.
Ramps:
Ramps
are methods of controlling a sound’s properties in accordance to a specified
control entity. You can adjust a sound’s pitch according to the speed of
the vehicle, for instance. Or adjust a sound’s volume according to the
observer’s distance. Some ramp controls are set and unchanging. Others
are dynamic and vary according to vehicle performance or other conditions.
A ramp definition
consists of a parameter definition and a parameter set. Consider
the following code excerpt:
*** Start Distance Volume
***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 50
param 100
param 0
param 1
endEffect
-
Parameter definition:
In this area, you specify the source of control and the method of sound adjustment
according to that control. In this excerpt you can see the source of control
is Distance, which is the method of adjustment for the destination Volume.
So as distance changes, volume changes accordingly. Below this section is
the parameter set, which defines two points where the control source and
control destination coincide. An adjustment ramp is then created using these
points as a reference.
-
Parameter set:
In this area, you specify two points at which you will define the exact values
for the control source and control destination. The order of the parameters
is:
Param1 : control
source point 1
Param2 : control
source point 2
Param3 : control
destination point 1
Param4 : control
destination point 2
So verbally, the code excerpt is saying: at 50m the sound
volume is zero, at 100m the sound volume is 1 (full volume).
Using this information, the soundscript creates
an adjustment ramp to modify the sound according to its parameters. For points
outside of the parameter set, the points assume the last stated value in
the parameter set. In other words, the angle of the ramp does not continue
beyond the defined start and end points, but rather maintains the same value
as the end points. So, in this example, an observer closer than 50m to the
sound origin will experience a zero volume level, and an observer beyond
100m will experience a full volume level. The ramp angle does not continue,
but rather remains level according to the last stated value in the parameter
set.
Now consider the next set of code which immediately follows
the above code:
*** Distance Volume ***
beginEffect
controlDestination Volume
controlSource Distance
envelope Ramp
param 200
param 300
param 1
param -1
endEffect
This ramp continues full folume out
to 200m. Then, the volume diminishes to zero at 300m. Note the use of –1
instead of zero to end the sound. This is called terminating the sound. It
tells the sound engine that no sound will occur outside of the designated
range. This is different than telling the engine that volume is zero beyond
the designated range. Without terminating the sound, it will continue to
infinity and occupy sound channels throughout the map.
IMPORTANT NOTE: You
must terminate all sounds. Failure to do this will result in loss of available
sound channels across the map. If enough active sounds are not given termination
commands, you will experience massive loss of sound channels in-game.
Here is a description of the many sound ramps that occur
in BF1942. This is just a sampling of the more common ramp codes. Others
may exist and it seems that many in-game variables may be used to control
a ramp.
Time delay:
*** Time Volume ***
beginEffect
controlDestination Volume
controlSource Time
envelope Ramp
param 0.77
param 0.77
param 0
param 1
endEffect
trigger Volume
This ramp is used when a sound should not be played until
a designated amount of time has passed. In this example, the sound will be
played 0.77 seconds after the sound triggering event has occurred.
Note the use of trigger Volume immediately after
the ramp. This command is used in conjunction with time delay ramps. It forces
the sound to start when the given time has passed, instead of letting the
sound start immediately. If this ramp was missing the trigger Volume command,
you would not hear the sound from the beginning, but rather from the 0.77
second mark of the .wav. This command will almost always be used in a time
delay ramp.
Engine activity volume
ramp:
*** Engine Volume ***
beginEffect
controlDestination Volume
controlSource Default
envelope Ramp
param 0
param 0.75
param 0.25
param 1
endEffect
This ramp is used when a sound should be louder / quieter
according to a vehicle’s engine performance. Many vehicle soundscripts use
an array of sounds with such volume ramps, each sound crossfading with
another as the engine power picks up.
Note the controlSource is listed
as Default. While there is no absolute documentation on the exact
meaning of Default, it seems to be a combination of engine RPM and vehicle
speed. The range is from 0 (an idle vehicle) to 1 (a vehicle at maximum power
and speed).
This specific ramp tells the sound to play at 25% when the
vehicle is stopped, and increase to full volume when the vehicle engine reaches 75% of it’s
full power.
Engine RPM pitch ramp:
*** Engine Pitch ***
beginEffect
controlDestination Pitch
controlSource Extern
#map<Engine::Rpm>
envelope Ramp
param .2
param .6
param 0.70
param 0.30
endEffect
This ramp is used primarily for aircraft to increase / decrease
a sound’s pitch according to engine RPM. This ramp is commonly used to adjust
an aircraft engine’s pitch as the pilot increases throttle.
Note the controlSource is listed
as Extern
#map<Engine::Rpm>. This control
source is a variable taken directly from the vehicle’s engine properties.
It ranges from 0 (at zero throttle) to 1 (full
throttle).
Pitch ramps have parameters that are a bit difficult to
interpret. The two parameters are offsets from the standard value of 1 (which
is normal pitch). It is best to think of the pitch parameters graphically,
as they make little sense mathematically. Let me demonstrate:
This particular ramp is set to param3: 0.7 and param4: 0.3.
This means that when the vehicle is at .2 throttle,
the pitch will be at 70% of normal. When the vehicle is at .6 throttle, the pitch will be at 130% of normal. Parameter
3 is the actual multiplier of the pitch when the control source is at parameter
1. Parameter 4 is the multiplier above normal pitch when the control
source is at parameter 2. So you would consider a parameter 4 value of 0.3
to mean the pitch is multiplied by 1.3.
Soundscript tips
Here are some important soundscripting tips
to bear in mind.
-
All soundscript commands are CASE SENSITIVE!
Never forget this. Sound paths need not be in the proper case. Everything
else in your soundscript must be properly capitalized.
-
Priority is god in soundscripting. Reserve high
priorities for sounds that should always be heard over others. Do not let
distant sounds have high priorities. Break up a sound into several different
priorities according to distance.
-
As mentioned before, always terminate your sounds. Doublecheck your soundscript for
termination errors before deeming it complete.
-
Stereo sounds have their use, but they are of limited worthiness. The best
time to use a stereo sound is when you want to ensure a sound is always centered
on the player’s ears. They are used for 1st person view in many
weapons for this reason, to disregard slight variance in positioning. Don’t
forget that a stereo sound is twice the file size as a mono. Use them sparingly.
-
If two of the same sound overlap, they will cause
a phaser effect that is usually unwanted. Keep
in mind all the sound radii for each .wav, and try to avoid overlapping the
same .wav. For some vehicles, the phaser effect
is desirable. Multiple propeller planes fall into this category.
-
Remember that mindistance has its own inherit
volume / distance ramp that you have no control over. If your sound is too
quiet at a distance, even if your volume ramp is not set to reduce volume,
consider increasing the mindistance value.
-
A soundscripter is always dependant on the coder
to include his soundscripts in the object he
is preparing his scripts for. Work with the coder to determine what components
of a vehicle need a soundscript attached to them.
-
Be wary of multiple engined vehicles if you only
want a single soundscript to handle the engine
sound. The coder must ensure only one soundscript is
called for.
-
If you want a sound to follow a projectile, you will call for a soundscript in
the projectile’s physics.con file. Looping sounds behave better for projectiles.
Even if a sound is long and will not loop properly, still set it to loop.
Otherwise the soundscript distance properties
will only be calculated once and not be updated as the projectile moves.
If a sound does not loop well and you want to deactivate it as soon as it
reaches the end of the .wav, use a time / volume ramp to terminate it.
-
For vehicle engines, consider using a single engine sound set for a broad
pitch range depending on the engine power. Then overlay several smaller looping
sounds that activate at different RPM levels. You can conserve considerable
file size by using this method. Reserve a unique sound for engine idle.