Soundscripts: Difference between revisions
SirYodaJedi (talk | contribs) (→Sound characters: not only WAV) |
|||
(80 intermediate revisions by 30 users not shown) | |||
Line 1: | Line 1: | ||
{{LanguageBar}} | |||
{{TabsBar|main=Soundscripts}} | |||
{{toc-right}} | {{toc-right}} | ||
'''Soundscripts''' contain ''sound entries'' or ''game sounds'' that are used to wrap {{src|4}}-specific playback instructions around [[WAV]] or [[MP3]] files. A ''sound entry'' or ''game sound'' can define the meaning of a sound to NPCs, its pitch and volume, how far away it can be heard from (attenuation), and can be used to randomize which precise sound file is played. [[#Operator Stacks|Operator stacks]] {{portal2|since}} can be used to define even more complex behaviors. | |||
'''Soundscripts''' contain | |||
A sound entry can define the meaning of a sound to NPCs, its pitch and volume, how far away it can be heard from (attenuation), and can be used to | |||
Soundscripts are loaded ''on the server only'' from: | Soundscripts are loaded ''on the server only'' from: | ||
*{{path|scripts/game_sounds_manifest|txt}} | |||
*{{path|maps/<mapname>_level_sounds|txt}} {{csgo|not}} | |||
All filepaths within a soundscript are relative to the game or mod's {{path|sound/}} folder. | |||
{{cmd|playgamesound|<entry>}} is a console command that one can "browse" and play the available ''sound entries'' of a game with. | |||
==Example | == Example == | ||
<pre> | |||
entry.name | |||
{ | |||
channel CHAN_AUTO | |||
volume VOL_NORM | |||
pitch PITCH_NORM | |||
soundlevel SNDLVL_NORM | |||
wave common/null.wav | |||
} | |||
</pre> | |||
If a value has a space or tab character within it, it ''must'' be wrapped in "quote marks". | |||
== Commands == | |||
=== Wave / Rndwave === | |||
Filename of the sound to play. All file paths can be preceeded with one or two sound characters, see [[#Sound characters|below]]. | |||
<pre> | |||
wave common/blah1.wav | |||
</pre> | |||
You can also have the engine pick from a list of random files. A given sound won't repeat until all of the others have played. Note that the random choice is decided by the server, not the client. | |||
<pre> | |||
rndwave | |||
{ | |||
wave common/blah1.wav | |||
wave common/blah2.wav | |||
wave common/blah3.wav | |||
} | |||
</pre> | |||
{{note|The sound file MUST be in a folder within the {{path|sound\}} folder. So {{path|sound\folder\sound|wav}} will work, while {{path|sound\sound|wav}} will not.}} | |||
== | === Volume === | ||
A number between 0 and 1, where 1 is the sound's original volume. <code>VOL_NORM</code> will insert your mod's default volume, which will probably be <code>1</code>. | |||
To have a random numeric value chosen every time the sound plays, type a lower bound and a higher bound, separated by a comma. Example: <code>volume 0.4,0.6</code>. | |||
=== Pitch === | |||
Any number between 0 and 255, where 100 is the sound's original pitch and 255 is very high. | |||
*<code>PITCH_LOW = 95</code> | |||
*<code>PITCH_NORM = 100</code> | |||
*<code>PITCH_HIGH = 120</code> | |||
To have a random numeric value chosen every time the sound plays, type a lower bound and a higher bound, separated by a comma. Example: <code>pitch 90,110</code>. | |||
=== Channel === | |||
Channels are used to categorize sounds in a way that NPCs, and game logic in general, can understand. | |||
{{confirm|There is a limit of 256 channels total: 224 Static, 32 Dynamic that can play at any given time.}} | |||
:: '' Exceeding this will result in a channel allocation error, preventing sounds from playing. '' | |||
{| class=wikitable | |||
! Value for <code>channel</code> | |||
! Description | |||
|- | |||
| <code>CHAN_AUTO</code> | |||
| Default, generic channel. | |||
|- | |||
| <code>CHAN_WEAPON</code> | |||
| Player and NPC weapons. | |||
|- | |||
| <code>CHAN_VOICE</code> | |||
| Voiceover dialogue. Used for regular voice lines, etc. {{note|If sound with this channel is emit by an entity that has the "mouth" [[$attachment|attachment]], the sound comes from it.}} | |||
|- | |||
| <code>CHAN_VOICE2</code> | |||
| Additional voice channel. Used in {{tf2}} for the announcer. | |||
|- | |||
| <code>CHAN_ITEM</code> | |||
| Generic physics impact sounds, health/suit chargers, {{Command|+use}} sounds. | |||
|- | |||
| <code>CHAN_BODY</code> | |||
| Clothing, ragdoll impacts, footsteps, knocking/pounding/punching etc. | |||
|- | |||
| <code>CHAN_STREAM</code> | |||
| Sounds that can be delayed by an ''async'' load, i.e. aren't responses to particular events. {{confirm|This won't make the sound actually stream; use the <code>*</code> path prefix for that, see [[#Sound characters|below]].}} | |||
|- | |||
| <code>CHAN_REPLACE</code> | |||
| Used when playing sounds through console commands. | |||
|- | |||
| <code>CHAN_STATIC</code> | |||
| A constant/background sound that doesn't require any reaction. | |||
|- | |||
| <code>CHAN_VOICE_BASE</code> | |||
| Network voice data (online voice communications) | |||
|- | |||
| <code>CHAN_USER_BASE+<number></code> | |||
| Custom channels can be defined here. Allocates a channel for the desired sound entry. | |||
|} | |||
Channels can also be specified by a number, corresponding to the [https://github.com/ValveSoftware/source-sdk-2013/blob/0565403b153dfcde602f6f58d8f4d13483696a13/src/public/soundflags.h#L21 enum in the engine]. For example -1 will be <code>CHAN_REPLACE</code>. | |||
=== | === Soundlevel === | ||
The sound's [[w:Attenuation|attenuation]]; how fast it drops away. The engine starts running into trouble below 60dB. | |||
The following list contains all default sound levels, their attenuation value, real world examples, and in-game examples. All values and real world examples were taken from {{path|src\public\soundflags|h}}. | |||
It is possible to pass a literal number value ("150" as opposed to "SNDLVL_150") and freely choose any number between 0 and 255. Games tested: {{hl2|5}} {{hl2ep1|5}} {{hl2ep2|5}} {{p2|5}} | |||
{| class=wikitable | |||
! Value for <code>soundlevel</code> | |||
{| class= | ! Attenuation<br>Value | ||
! | !width=350| Real World | ||
!Value | !width=700| In Game | ||
!Real World | |||
!In Game | |||
|- | |- | ||
| SNDLVL_NONE | | <code><span style=color:white>SNDLVL_NONE</span></code> | ||
| 0 | | align="middle" | 0 | ||
| Everywhere | | Everywhere | ||
| {{l4d2}}: Music disconnected from environment (Ex: checkpoint music, credit music, mob music) | | {{l4d2}}: Music disconnected from environment (Ex: checkpoint music, credit music, mob music) | ||
|- | |- | ||
| SNDLVL_20dB | | <code>SNDLVL_20dB</code> | ||
| | | | ||
| Rustling leaves | | Rustling leaves | ||
| | | | ||
|- | |- | ||
| SNDLVL_25dB | | <code>SNDLVL_25dB</code> | ||
| | | | ||
| Whispering | | Whispering | ||
| | | | ||
|- | |- | ||
| SNDLVL_30dB | | <code>SNDLVL_30dB</code> | ||
| | | | ||
| Library | | Library, dishwasher | ||
| | | | ||
|- | |- | ||
| SNDLVL_35dB | | <code>SNDLVL_35dB</code> | ||
| | | | ||
| | | | ||
| | | | ||
|- | |- | ||
| SNDLVL_40dB | | <code>SNDLVL_40dB</code> | ||
| | | | ||
| Moderate rainfall | |||
| | | | ||
|- | |- | ||
| SNDLVL_45dB | | <code>SNDLVL_45dB</code> | ||
| | | | ||
| Refrigerator | | Refrigerator | ||
| | | | ||
|- | |- | ||
| SNDLVL_50dB | | <code>SNDLVL_50dB</code> | ||
| 3.9 | | align="middle" | 3.9 | ||
| Average home | | Average home, heavy rainfall | ||
| | | | ||
|- | |- | ||
| SNDLVL_55dB | | <code>SNDLVL_55dB</code> | ||
| 3.0 | | align="middle" | 3.0 | ||
| | | | ||
| {{l4d2}}: Digital alarm clock in C8M1_Apartment. | |||
|- | |- | ||
| SNDLVL_IDLE | | <code>SNDLVL_60dB</code><br><code><span style=color:white>SNDLVL_IDLE</span></code> | ||
| 2.0 | | align="middle" | 2.0 | ||
| Normal conversation, clothes dryer | | Normal conversation, clothes dryer | ||
| | | | ||
|- | |- | ||
| SNDLVL_65dB | | <code>SNDLVL_65dB</code> | ||
| 1.5 | | align="middle" | 1.5 | ||
| Washing machine, dishwasher | | Washing machine, dishwasher | ||
| | | | ||
|- | |- | ||
| SNDLVL_STATIC | | <code><span style=color:white>SNDLVL_STATIC</span></code> | ||
| 1.25 | | align="middle" | 1.25 | ||
| | | | ||
| | | | ||
|- | |- | ||
| SNDLVL_70dB | | <code>SNDLVL_70dB</code> | ||
| 1.0 | | align="middle" | 1.0 | ||
| Car, vacuum cleaner, mixer, electric sewing machine | | Car, vacuum cleaner, mixer, electric sewing machine | ||
| {{l4d2}}: Moustachio whack smash and pop-up | | {{l4d2}}: Moustachio whack smash and pop-up, tv static, whacked piano | ||
|- | |- | ||
| | | <code>SNDLVL_75dB</code><br><code><span style=color:white>SNDLVL_NORM</span></code> | ||
| 0.8 | | align="middle" | 0.8 | ||
| Busy traffic | | Busy traffic | ||
| {{l4d2}}: Lilpeanut audible | | {{l4d2}}: Various doors, swarm of flies, Lilpeanut audible, bullet impact on wood. | ||
|- | |- | ||
| SNDLVL_80dB | | <code>SNDLVL_80dB</code> | ||
| 0.7 | |rowspan=2 align="middle" | 0.7 | ||
| Mini-bike, alarm clock, noisy restaurant, office tabulator, outboard motor, passing snowmobile | | Mini-bike, alarm clock, noisy restaurant, office tabulator, outboard motor, passing snowmobile, police siren | ||
| {{l4d2}}: Jukebox, music spitter spit pile as source | | {{l4d2}}: Jukebox, music spitter spit pile as source. | ||
|- | |- | ||
| | | <code><span style=color:white>SNDLVL_TALKING</span></code> | ||
| | | | ||
| Valve's chosen dialogue attenuation | | Valve's chosen dialogue attenuation | ||
|- | |- | ||
| SNDLVL_85dB | | <code>SNDLVL_85dB</code> | ||
| 0.6 | | align="middle" | 0.6 | ||
| Average factory, electric shaver | | Average factory, electric shaver | ||
| {{l4d2}}: Moustachio strength attract | | {{l4d2}}: Moustachio strength attract, big fire after airliner crash in C11M5_runway | ||
|- | |- | ||
| SNDLVL_90dB | | <code>SNDLVL_90dB</code> | ||
| 0.5 | | align="middle" | 0.5 | ||
| Screaming child, passing motorcycle, convertible ride on freeway | | Screaming child, passing motorcycle, convertible ride on freeway, hair dryer | ||
| {{l4d2}}: Moustachio strength attract | | {{l4d2}}: Moustachio strength attract, gas can bursting | ||
|- | |- | ||
| SNDLVL_95dB | | <code>SNDLVL_95dB</code> | ||
| | | | ||
| | | | ||
|{{l4d2}}: Mounted Machine Gun | |||
|- | |- | ||
| SNDLVL_100dB | | <code>SNDLVL_100dB</code> | ||
| 0.4 | | align="middle" | 0.4 | ||
| Subway train, diesel truck, woodworking shop, pneumatic drill, boiler shop, jackhammer | | Subway train, diesel truck, woodworking shop, pneumatic drill, boiler shop, jackhammer | ||
| {{l4d2}}: Music coop player in danger AKA tags (ledge hanging, pinned down by SI) | | {{l4d2}}: Music coop player in danger AKA tags (ledge hanging, pinned down by SI), Elevators. | ||
|- | |- | ||
| SNDLVL_105dB | | <code>SNDLVL_105dB</code> | ||
| | | | ||
| Helicopter, power mower | | Helicopter, power mower | ||
| | | | ||
|- | |- | ||
| SNDLVL_110dB | | <code>SNDLVL_110dB</code> | ||
| | | | ||
| Snowmobile (drivers seat), inboard motorboat, sandblasting | | Snowmobile (drivers seat), inboard motorboat, sandblasting, chainsaw | ||
| {{l4d2}}: Boomer alert close | | {{l4d2}}: Boomer alert close, Van in C11M4_Terminal. | ||
|- | |- | ||
| SNDLVL_120dB | | <code>SNDLVL_120dB</code> | ||
| | | | ||
| Car horn, propeller aircraft | | Car horn, propeller aircraft, concert | ||
| {{l4d2}}: Boomer alert | | {{l4d2}}: Boomer alert, Indoor fire in C1M1_Hotel, Fireworks in C2M5_Concert, Rain in "Hard Rain" campaign. | ||
|- | |- | ||
| SNDLVL_125dB | | <code>SNDLVL_125dB</code> | ||
| | | | ||
| | | | ||
| {{l4d2}}: Boomer alert far | | {{l4d2}}: Boomer alert far | ||
|- | |- | ||
| SNDLVL_130dB | | <code>SNDLVL_130dB</code> | ||
| | | | ||
| Air raid siren | | Air raid siren, fireworks | ||
| {{l4d2}}: Carousel music during crescendo event | | {{l4d2}}: Carousel music during crescendo event, C5M2_park perimeter alarm. | ||
|- | |- | ||
| | | <code><span style=color:white>SNDLVL_GUNFIRE</span></code> | ||
| 0.27 | | align="middle" | 0.27 | ||
| Threshold of pain, gunshot, jet engine | | Threshold of pain, gunshot, jet engine | ||
| | | | ||
|- | |- | ||
| SNDLVL_140dB | | <code>SNDLVL_140dB</code> | ||
| 0.2 | | align="middle" | 0.2 | ||
| | | Airplane taking off, jackhammer | ||
| | | {{l4d2}}: Flock of crows, Lowering bridge in C5m5_Bridge, APC engine. | ||
|- | |- | ||
| SNDLVL_145dB | | <code>SNDLVL_145dB</code> | ||
| | | | ||
| | | | ||
| {{l4d2}}: Wandering witch music ("lost little witch") | | {{l4d2}}: Wandering witch music ("lost little witch") | ||
|- | |- | ||
| SNDLVL_150dB | | <code>SNDLVL_150dB</code> | ||
| 0.2 | | align="middle" | 0.2 | ||
| | | Smithing hammer | ||
| {{l4d2}}: Concert music, parade music, zombie choir | | {{l4d2}}: Concert music, parade music, zombie choir, Boat Horn | ||
|- | |- | ||
| SNDLVL_180dB | | <code style=color:white>SNDLVL_180dB</code> | ||
| | | | ||
| Rocket launching | | Rocket launching | ||
Line 248: | Line 272: | ||
== Operator stacks == | == Operator stacks == | ||
{{main|Soundscripts/Operator Stacks}} | |||
{{p2branch|4}} introduced '''Operator Stacks''', which are a system used to add complex behavior to sounds, extending soundscripts. | |||
Outside {{p2|2}}, they are supported in: {{csgo}} {{dota2}} {{doi}} {{insurgency}} | |||
< | The keyvalues <code>soundentry_version 2</code> and <code>operator_stacks</code> are characteristic. Example: | ||
<syntaxhighlight lang=php <!--highlight=14,16--> | |||
VFX.LightFlickerEnd | VFX.LightFlickerEnd | ||
{ | { | ||
Line 268: | Line 285: | ||
rndwave | rndwave | ||
{ | { | ||
wave | wave "vfx/light_flicker/light_flicker_end_01.wav" | ||
wave | wave "vfx/light_flicker/light_flicker_end_02.wav" | ||
wave | wave "vfx/light_flicker/light_flicker_end_03.wav" | ||
wave | wave "vfx/light_flicker/light_flicker_end_04.wav" | ||
} | } | ||
Line 282: | Line 299: | ||
import_stack "P2_exclusion_time_blocker_start" // defined in scripts/sound_operator_stacks.txt | import_stack "P2_exclusion_time_blocker_start" // defined in scripts/sound_operator_stacks.txt | ||
// We are now extending/configuring P2_exclusion_time_blocker_start | // We are now extending/configuring "P2_exclusion_time_blocker_start" | ||
// which contains an operator with the exact name "block_entries" whose values we will now override: | |||
block_entries // prevents another sound from playing | block_entries // prevents another sound from playing | ||
{ | { | ||
input_duration 0.25 // seconds to block for | input_duration 0.25 // seconds to block for | ||
match_entry "World.LightFlickerEnd" // the sound entry to block | match_entry "World.LightFlickerEnd" // the sound entry to block | ||
match_entity false // only on the same entity that this sound is playing from? | match_entity false // only on the same entity that this sound is playing from? | ||
} | } | ||
} | } | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
== | == Sound characters == | ||
The first two characters of a sound's filename are scanned for the following: | |||
{{todo| | {| class=wikitable | ||
! width=3em| Symbol | |||
==== | ! Name | ||
!style=white-space:nowrap| Game/branch | |||
! Purpose / Notes | |||
|- | |||
| align=middle | <code style=font-size:125%>*</code> | |||
| '''CHAR_STREAM''' | |||
| align=middle | ''all'' | |||
| Streams from the disc, get flushed soon after. Use for one-off dialogue files or music. | |||
|- | |||
| align=middle | <code style=font-size:125%>#</code> | |||
| '''CHAR_DRYMIX''' | |||
| align=middle | ''all'' | |||
| Bypasses [[DSP]], becomes affected by the user's music volume setting ({{cmd|snd_musicvolume}}). The latter part also requires the sound to be non directional (soundlevel of 0). | |||
{{Note|{{since|{{portal2}}}} Operator stacks can achieve this, too, making this character not necessary, see [[Soundscripts/Operator Stacks#Music]].}} | |||
{{Warning|Using this character on a sound entry utilizing an ''operator stack'' with an <code>update_stack</code> where the volume is zeroed out, whether by the <code>update_stack</code> or by the sound entry itself (<code>volume 0.0</code>), will cause an <code>update_stack</code> loop. Not only does this have negative performance implications, the sound will consume an audio channel until the loop is interrupted or the sound is stopped. {{inline note|name=Confirm}}}} | |||
|- | |||
| align=middle | <code style=font-size:125%>@</code> | |||
| '''CHAR_OMNI''' | |||
| align=middle | ''all'' | |||
| Non-directional sound; plays "everywhere", similar to <code>SNDLVL_NONE</code>, except it fades with distance from its source based on its soundlevel. | |||
|- | |||
| align=middle | <code style=font-size:125%>></code> | |||
| '''CHAR_DOPPLER''' | |||
| align=middle | ''all'' | |||
| Doppler encoded stereo: left for heading towards the listener and right for heading away. | |||
|- | |||
| align=middle | <code style=font-size:125%><</code> | |||
| '''CHAR_DIRECTIONAL''' | |||
| align=middle | ''all'' | |||
| Stereo with direction: left channel for front facing, right channel for rear facing. Mixed based on listener's direction. {{todo|Relationship with <code>CHAR_DIRSTEREO</code> in {{csgo|2.bold}}?}} | |||
|- | |||
| align=middle | <code style=font-size:125%>^</code> | |||
| '''CHAR_DISTVARIANT''' | |||
| align=middle | ''all'' | |||
| Distance-variant stereo. Left channel is close, right channel is far. {{note|Transition distance is hard-coded, see [[#Distance variance|below]]. | |||
|- | |||
| align=middle | <code style=font-size:125%>)</code> | |||
| '''CHAR_SPATIALSTEREO''' | |||
| align=middle | ''all'' | |||
| Spatializes both channels, allowing them to be placed at specific locations within the world; [[Soundscripts#Spatial stereo|see below]]. {{note|Sometimes <code>(</code> must be used instead, see [[#Spatial stereo|below]].}} | |||
|- | |||
| align=middle | <code style=font-size:125%>}</code> | |||
| '''CHAR_FAST_PITCH''' | |||
| align=middle | ''all'' | |||
| Forces low quality, non-interpolated pitch shift. | |||
|- | |||
| align=middle | <code style=font-size:125%>$</code> | |||
| '''CHAR_CRITICAL''' | |||
| align=middle | Up to {{src06}} | |||
| Forces sound to be cached at a fixed point in memory. {{note|Only affects {{xbox|2.bold}}, which streams all audio regardless of <code>*</code> unless marked as critical. {{src07|removed}}}} | |||
|- | |||
| align=middle | <code style=font-size:125%>!</code> | |||
| '''CHAR_SENTENCE''' | |||
| align=middle | Since {{src09}} | |||
| An NPC [[sentence]]. | |||
|- | |||
| align=middle | <code style=font-size:125%>?</code> | |||
| '''CHAR_USERVOX''' | |||
| align=middle | ''all'' | |||
| Voice chat data. You shouldn't ever need to use this. | |||
|- | |||
| align=middle | <code style=font-size:125%>&</code> | |||
| '''CHAR_HRTF_FORCE''' | |||
| align=middle | {{csgo}} | |||
| Indicates wav should use HRTF spatialization for all entities (including owners). | |||
|- | |||
| align=middle | <code style=font-size:125%>~</code> | |||
| '''CHAR_HRTF''' | |||
| align=middle | {{csgo}} | |||
| Indicates wav should use HRTF spatialization for non-owners. | |||
|- | |||
| align=middle | <code style=font-size:125%>`</code> | |||
| '''CHAR_HRTF_BLEND''' | |||
| align=middle | {{csgo}} | |||
| Indicates wav should use HRTF spatialization for non-owners, blended with stereo for sounds sufficiently close. | |||
|- | |||
| align=middle | <code style=font-size:125%>+</code> | |||
| '''CHAR_RADIO''' | |||
| align=middle | {{csgo}} | |||
| Indicates a 'radio' sound -- should be played without spatialization. | |||
|- | |||
| align=middle | <code style=font-size:125%>$</code> | |||
| '''CHAR_SUBTITLED''' | |||
| align=middle | {{csgo}} | |||
| Indicates the subtitles are forced. | |||
|- | |||
| align=middle | <code style=font-size:125%>%</code> | |||
| '''CHAR_MUSIC''' | |||
| align=middle | {{csgo}} | |||
| Indicates main menu music. | |||
|- | |||
| align=middle | <code style=font-size:125%>(</code> | |||
| '''CHAR_DIRSTEREO''' | |||
| align=middle | {{csgo}} {{l4d2}} | |||
| Indicates directional stereo wav (like doppler). | |||
|} | |||
< | For example: <!-- "sound/" is omitted here (and henceforth) as it is historically omitted in contexts where sound characters are present. This should, however, be sufficient. --> | ||
*{{path|)weapons/m4a1/m4_shoot|wav}} | |||
*{{path|*@npc/vo/announcer/specialoffer|wav}} | |||
=== Spatial stereo === | |||
{ | Adding <code>)</code> in front of a stereo sound name in the soundscript such as {{path|)weapons/m4a1/m4_shoot|wav}} tells the sound engine that it is a ''spatialized'' sound; this allows the sound to emit from a specific location within the world. When not used, stereo sounds play in a fixed 2-channel orientation and cannot be panned to simulate a location. Single-channel files do not require <code>)</code> before the filename and will be ''spatialized'' automatically. | ||
</ | |||
=== | === Soundscapes === | ||
[[Soundscape]]s have special needs. Stereo wave files used in <code>PlayRandom</code> require that <code>(</code> is placed before the filename. <code>PlayLooping</code> still uses <code>)</code> but <code>(</code> will spatialize the two channels separately for an alternate effect; <code>(</code> sounds more environmental, but the exact nature of this behavior is unknown. Generic soundscripts can sometimes use <code>(</code> to gain the same stereo spatialization that occurs in <code>PlayLooping</code>. | |||
{{Confirm|Is this <code>(</code> stereo-spatialization behavior present in all engine branches? Some preliminary testing reveals it may be absent from {{gmod|4}}.}} | |||
{{expand|title=Example | |||
| | |||
<syntaxhighlight lang=php> | |||
{ | |||
{ | |||
= | |||
< | |||
wave ")ambient/stereo_alarm.wav" // Typical usage in a standard soundscript | wave ")ambient/stereo_alarm.wav" // Typical usage in a standard soundscript | ||
</ | </syntaxhighlight> | ||
But in soundscapes: | But in soundscapes: | ||
< | <syntaxhighlight lang=php> | ||
playrandom | playrandom | ||
{ | { | ||
Line 413: | Line 450: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
< | <syntaxhighlight lang=php> | ||
PlayLooping | PlayLooping | ||
{ | { | ||
Line 424: | Line 461: | ||
//wave "(ambient/stereo_siren.wav" // stereo spatialization; one of the channels is spatialized alternatively | //wave "(ambient/stereo_siren.wav" // stereo spatialization; one of the channels is spatialized alternatively | ||
} | } | ||
</ | </syntaxhighlight> | ||
}} | |||
=== Distance variance | === Distance variance === | ||
Adding <code>^</code> in front of a sound name, such as {{path|^weapons/explode3|wav}} tells the sound engine that it is a distance based sound. The left channel of the sound file is the 'near' sound that will play when the sound originates close to you, and the right channel is the 'far' sound that will play when the sound originates far from you. If the <code>^</code> mark is not used in the soundscript, the sound is treated as stereo with no directionality or distance. This is a different feature than the <code>soundlevel</code> property to control attenuation. This distant variant feature allows you to play ''two different sounds'' (but using only one file) and crossfading between the two depending on how far away the sound originates. | |||
The fade distances are hardcoded to begin at 240 world units and end at 1320 world units, and cannot be changed in custom maps or mods. | |||
== See also == | == See also == | ||
*{{ent|ambient_generic}} | |||
*[[Soundscape]] | |||
*[[L4D_Soundscripts|Left 4 Dead Soundscripts]] | |||
*[https://web.archive.org/web/20210925115735/http://podcast17.com/interviews/audio/mike-morasky/ Podcast 17 Mike Morasky Interview] - Discussion about audio production and insight into the evolution of the sound system. Archived from the original. | |||
* src | ---- | ||
* src | *{{path|src\public\soundflags|h}} | ||
* scripts | *{{path|src\public\soundchars|h}} | ||
* scripts | *{{path|scripts\game_sounds_header|txt}} | ||
*{{path|scripts\game_sounds|txt}} | |||
[[Category:Source]] | |||
[[Category:Sound System]] | [[Category:Sound System]] | ||
[[Category:Plain text formats]] | |||
[[Category:Plain text files]] <!-- due to scripts\game_sounds_manifest.txt and maps\<mapname>_level_sounds.txt --> |
Latest revision as of 12:59, 8 May 2025


Soundscripts contain sound entries or game sounds that are used to wrap Source-specific playback instructions around WAV or MP3 files. A sound entry or game sound can define the meaning of a sound to NPCs, its pitch and volume, how far away it can be heard from (attenuation), and can be used to randomize which precise sound file is played. Operator stacks (in all games since
) can be used to define even more complex behaviors.
Soundscripts are loaded on the server only from:
All filepaths within a soundscript are relative to the game or mod's sound/
folder.
playgamesound <entry> is a console command that one can "browse" and play the available sound entries of a game with.
Example
entry.name { channel CHAN_AUTO volume VOL_NORM pitch PITCH_NORM soundlevel SNDLVL_NORM wave common/null.wav }
If a value has a space or tab character within it, it must be wrapped in "quote marks".
Commands
Wave / Rndwave
Filename of the sound to play. All file paths can be preceeded with one or two sound characters, see below.
wave common/blah1.wav
You can also have the engine pick from a list of random files. A given sound won't repeat until all of the others have played. Note that the random choice is decided by the server, not the client.
rndwave { wave common/blah1.wav wave common/blah2.wav wave common/blah3.wav }


sound\
folder. So 
sound\folder\sound.wav
will work, while 
sound\sound.wav
will not.Volume
A number between 0 and 1, where 1 is the sound's original volume. VOL_NORM
will insert your mod's default volume, which will probably be 1
.
To have a random numeric value chosen every time the sound plays, type a lower bound and a higher bound, separated by a comma. Example: volume 0.4,0.6
.
Pitch
Any number between 0 and 255, where 100 is the sound's original pitch and 255 is very high.
PITCH_LOW = 95
PITCH_NORM = 100
PITCH_HIGH = 120
To have a random numeric value chosen every time the sound plays, type a lower bound and a higher bound, separated by a comma. Example: pitch 90,110
.
Channel
Channels are used to categorize sounds in a way that NPCs, and game logic in general, can understand.

- Exceeding this will result in a channel allocation error, preventing sounds from playing.
Value for channel
|
Description |
---|---|
CHAN_AUTO
|
Default, generic channel. |
CHAN_WEAPON
|
Player and NPC weapons. |
CHAN_VOICE
|
Voiceover dialogue. Used for regular voice lines, etc. ![]() |
CHAN_VOICE2
|
Additional voice channel. Used in ![]() |
CHAN_ITEM
|
Generic physics impact sounds, health/suit chargers, +use sounds. |
CHAN_BODY
|
Clothing, ragdoll impacts, footsteps, knocking/pounding/punching etc. |
CHAN_STREAM
|
Sounds that can be delayed by an async load, i.e. aren't responses to particular events. ![]() * path prefix for that, see below. |
CHAN_REPLACE
|
Used when playing sounds through console commands. |
CHAN_STATIC
|
A constant/background sound that doesn't require any reaction. |
CHAN_VOICE_BASE
|
Network voice data (online voice communications) |
CHAN_USER_BASE+<number>
|
Custom channels can be defined here. Allocates a channel for the desired sound entry. |
Channels can also be specified by a number, corresponding to the enum in the engine. For example -1 will be CHAN_REPLACE
.
Soundlevel
The sound's attenuation; how fast it drops away. The engine starts running into trouble below 60dB.
The following list contains all default sound levels, their attenuation value, real world examples, and in-game examples. All values and real world examples were taken from src\public\soundflags.h
.
It is possible to pass a literal number value ("150" as opposed to "SNDLVL_150") and freely choose any number between 0 and 255. Games tested:
Operator stacks
Portal 2 engine branch introduced Operator Stacks, which are a system used to add complex behavior to sounds, extending soundscripts.
Outside
Portal 2, they are supported in:
The keyvalues soundentry_version 2
and operator_stacks
are characteristic. Example:
VFX.LightFlickerEnd
{
channel CHAN_AUTO
soundlevel SNDLVL_105db
volume 1.0
rndwave
{
wave "vfx/light_flicker/light_flicker_end_01.wav"
wave "vfx/light_flicker/light_flicker_end_02.wav"
wave "vfx/light_flicker/light_flicker_end_03.wav"
wave "vfx/light_flicker/light_flicker_end_04.wav"
}
soundentry_version 2
operator_stacks
{
start_stack // applied when the sound begins
{
import_stack "P2_exclusion_time_blocker_start" // defined in scripts/sound_operator_stacks.txt
// We are now extending/configuring "P2_exclusion_time_blocker_start"
// which contains an operator with the exact name "block_entries" whose values we will now override:
block_entries // prevents another sound from playing
{
input_duration 0.25 // seconds to block for
match_entry "World.LightFlickerEnd" // the sound entry to block
match_entity false // only on the same entity that this sound is playing from?
}
}
}
}
Sound characters
The first two characters of a sound's filename are scanned for the following:
Symbol | Name | Game/branch | Purpose / Notes |
---|---|---|---|
*
|
CHAR_STREAM | all | Streams from the disc, get flushed soon after. Use for one-off dialogue files or music. |
#
|
CHAR_DRYMIX | all | Bypasses DSP, becomes affected by the user's music volume setting (snd_musicvolume). The latter part also requires the sound to be non directional (soundlevel of 0).
![]() ![]() ![]() update_stack where the volume is zeroed out, whether by the update_stack or by the sound entry itself (volume 0.0 ), will cause an update_stack loop. Not only does this have negative performance implications, the sound will consume an audio channel until the loop is interrupted or the sound is stopped. [Confirm] |
@
|
CHAR_OMNI | all | Non-directional sound; plays "everywhere", similar to SNDLVL_NONE , except it fades with distance from its source based on its soundlevel.
|
>
|
CHAR_DOPPLER | all | Doppler encoded stereo: left for heading towards the listener and right for heading away. |
<
|
CHAR_DIRECTIONAL | all | Stereo with direction: left channel for front facing, right channel for rear facing. Mixed based on listener's direction. Todo: Relationship with
CHAR_DIRSTEREO in ![]() |
^
|
CHAR_DISTVARIANT | all | Transition distance is hard-coded, see below. |
)
|
CHAR_SPATIALSTEREO | all | Spatializes both channels, allowing them to be placed at specific locations within the world; see below. ![]() ( must be used instead, see below. |
}
|
CHAR_FAST_PITCH | all | Forces low quality, non-interpolated pitch shift. |
$
|
CHAR_CRITICAL | Up to ![]() |
Forces sound to be cached at a fixed point in memory. ![]() ![]() * unless marked as critical. (removed since ![]() |
!
|
CHAR_SENTENCE | Since ![]() |
An NPC sentence. |
?
|
CHAR_USERVOX | all | Voice chat data. You shouldn't ever need to use this. |
&
|
CHAR_HRTF_FORCE | ![]() |
Indicates wav should use HRTF spatialization for all entities (including owners). |
~
|
CHAR_HRTF | ![]() |
Indicates wav should use HRTF spatialization for non-owners. |
`
|
CHAR_HRTF_BLEND | ![]() |
Indicates wav should use HRTF spatialization for non-owners, blended with stereo for sounds sufficiently close. |
+
|
CHAR_RADIO | ![]() |
Indicates a 'radio' sound -- should be played without spatialization. |
$
|
CHAR_SUBTITLED | ![]() |
Indicates the subtitles are forced. |
%
|
CHAR_MUSIC | ![]() |
Indicates main menu music. |
(
|
CHAR_DIRSTEREO | ![]() ![]() |
Indicates directional stereo wav (like doppler). |
For example:
Spatial stereo
Adding )
in front of a stereo sound name in the soundscript such as )weapons/m4a1/m4_shoot.wav
tells the sound engine that it is a spatialized sound; this allows the sound to emit from a specific location within the world. When not used, stereo sounds play in a fixed 2-channel orientation and cannot be panned to simulate a location. Single-channel files do not require )
before the filename and will be spatialized automatically.
Soundscapes
Soundscapes have special needs. Stereo wave files used in PlayRandom
require that (
is placed before the filename. PlayLooping
still uses )
but (
will spatialize the two channels separately for an alternate effect; (
sounds more environmental, but the exact nature of this behavior is unknown. Generic soundscripts can sometimes use (
to gain the same stereo spatialization that occurs in PlayLooping
.

(
stereo-spatialization behavior present in all engine branches? Some preliminary testing reveals it may be absent from 
wave ")ambient/stereo_alarm.wav" // Typical usage in a standard soundscript
But in soundscapes: playrandom
{
time 33,68
volume .6,1
pitch 90,105
position 0
rndwave
{
wave "ambient/mono_siren.wav" // Mono files are always spatialized properly
wave ")ambient/stereo_alarm.wav" // WRONG; sound will not be spatialized
wave "(ambient/stereo_siren.wav" // Correct; sound will be spatialized normally
}
}
PlayLooping
{
volume .6
pitch 100
position 0
wave ")ambient/stereo_siren.wav" // standard spatialization; both channels originate at same location
//wave "(ambient/stereo_siren.wav" // stereo spatialization; one of the channels is spatialized alternatively
}
|
Distance variance
Adding ^
in front of a sound name, such as ^weapons/explode3.wav
tells the sound engine that it is a distance based sound. The left channel of the sound file is the 'near' sound that will play when the sound originates close to you, and the right channel is the 'far' sound that will play when the sound originates far from you. If the ^
mark is not used in the soundscript, the sound is treated as stereo with no directionality or distance. This is a different feature than the soundlevel
property to control attenuation. This distant variant feature allows you to play two different sounds (but using only one file) and crossfading between the two depending on how far away the sound originates.
The fade distances are hardcoded to begin at 240 world units and end at 1320 world units, and cannot be changed in custom maps or mods.
See also
- ambient_generic
- Soundscape
- Left 4 Dead Soundscripts
- Podcast 17 Mike Morasky Interview - Discussion about audio production and insight into the evolution of the sound system. Archived from the original.