Hammer/Source SDK Soundscripts

Started by
5 comments, last by Olliepm 10 years, 11 months ago

First off, I know very, VERY little about programming. I'm an audio person, but my latest ambitions seem to be taking me into the realms of the unknown. I'm hoping I've found the right section of the forum get some help.

In the most basic sense, I am trying to mod Portal 2 using Hammer. I need to be able to have full control of the audio assets, and their potions within the 3d space, and also their behaviors. I would also be importing new sounds, particularly ambient ones, and implementing them into the game. While there is plenty of information on this subject at the Valve Dev Community website, it is rather scattered about the place. Some kind of code/script (possibly Squirrel?) is frequently referenced where sounds entities are relevant. (Here is an example > https://developer.valvesoftware.com/wiki/Soundscripts). I'm wondering whether to be able to implement new sounds, and events into Portal 2, I will have to create similar scripts myself. If this is the case, I'm basically asking where to start with code/scripting, and what I need to know?

Note that in the above link, I do understand what the script is saying i.e parameters of a sound, and their values. What I do not understand is how important the actual files containing the script are, how they are created, how they are referenced. I don't even know the basic commands. <string>,<integer> etc are terms that frequently pop up, and I don't know what to do with them. I'm sorry my question is a little vague, but it just goes to show why I had to ask it.

Advertisement

By playing around with the scripts that already exist, you can pick it up fairly easily, and work more quickly toward your goals.

The knowledge required to program in general takes quite some time to pick up, but the knowledge required for the specific thing you asked probably isn't that much to learn.

A string is a block of text. "My name is bob" is a string. "adfasrt4wt345352" is a string. It's a group of characters/symbols (like letters, and punctuation, and numbers).

An integer is a number. 500 is an integer. -21 is an integer.

A boolean is something that is either True or False.

Learning programming entirely takes time, and will distract you from your current actual goal.

What you are wanting to do (replace the sound files) doesn't require a multi-year pursuit of programming (unless you are wanting that, which is awesome, and I'd give entirely different advice).

My suggestion: Find examples of the files that Portal 2 is already using, and post them here, and we'll explain them. I *think* they are using them more as a "markup" language rather than a full-blown programming language, when it comes to the sound files. (But they probably use it for full-on programming when it comes to enemy AI and things like that).

Post a few of the exact files you are wanting to replace (and not just the examples shown on the wiki), and I'll try and explain them.

A multi-year pursuit of programming? As you say, I think this would interfere too much with my development in audio related areas. My goal is to be a sound designer, however, I do frequently see jobs advertised called "Audio Programmer". Not knowing how much an audio programmer would need to know, I don't know if programming is something I should add to my skill set. The whole point of this Portal mod is to create an audio implementation/sound design demo, that will demonstrate that I can do a sound design job. I still find the programming subject tempting, though. It must be quite rewarding!

I did find a tutorial video last night, which helped me understand things a bit more, but for the sake of posting something code-ish...

Here is something I do understand, except for a few minor things; There is a file path for the sound file, yet I cannot find this sound file in my windows explorer. It is apparently a WAV file, so it should not be hidden. Also, I'd like to know what the very first line represents ("Portal.Glados..." , and also the significance of the quotation marks. Is this the name that Hammer references the sound file + properties by? This came from a script .txt file, and only consists of what I've shown below, repeated for different sound files, so there are no introductory instructions. I'm wondering how the game/Hammer will know it has to read this file?

"Portal.Glados_core.Crazy_19"
{
"channel" "CHAN_VOICE"
"volume" "1.0"
"soundlevel" "SNDLVL_70DB"
"wave" "vo/aperture_ai/escape_02_sphere_cakemix-19.wav"
}
______________________________________________________________
If that wasn't enough of a challenge, this nearly gave me a heart attack. All I know here is that "//" means comments. From a text file called "Soundmixers", and there is no page on Valve explaining it. If I had to guess, I'd say this details some way of determining which sounds are played over others, such as when Glados speaks, and all other sounds are reduced. In audio, this could be called 'ducking'. There is, as you can see, some instructions listed as comments, but it's got me too confused, at this point:
// Halflife 2 custom sound mixers.
// These Sound Mixers are referenced by name from Soundscapes, and are used to provide
// custom volume control over various sound categories, called 'mix groups'
// "GROUPRULES" specifies the rules for inclusion of a sound in a mix group.
// Rules are checked sequentially (from top to bottom). All fields must match
// in a row in order for a sound to match the group. A sound my be included
// in up to 8 mix groups.
// LIMITS:
// up to 64 unique mix groups
// up to 76 group rules entries
// up to 32 sound mixers
// all strings are limited to 31 characters!
// NOTE2: at runtime, you can display the classname of the sound source by
// setting snd_showclassname 1 in the console.
// NOTE3: main character dialog during critical scenes is ducked using a separate code path which, when
// active, temporarilly disables mixer ducking (prevent double ducking).
// Lower priority sounds are ducked by higher priority sounds, if "is ducked" is enabled.
// Only sounds with "causes ducking" enabled can cause a lower priority sound to be ducked.
"MixGroups"
{
// NOTE: order these from least general to most general
// directory or .wav classname Causes Duck to Ducker
// group name name substring substring chan sndlvl_min sndlvl_max priority Is Ducked Ducking Percent Threshold
// --------- ------------------ --------- ----------- ---------- ---------- -------- -------- ------- ------- ---------
"voip" "?VoiceSfx" "" "" "" "" "60" "0" "0" "100" "40"
"UI" "ui/" "" "" "" "" "60" "0" "0" "100" "40"
"commentary" "commentary/" "" "" "" "" "60" "0" "0" "100" "40"
"mstr" "mstr/" "" "" "" "" "60" "0" "0" "100" "40"
"noDSP" "nodsp" "" "" "" "" "60" "0" "0" "100" "40"
"potatosVO" "vo/glados/potatos" "" "" "" "" "60" "0" "0" "100" "40"
"gladosVO" "vo/glados/" "" "" "" "" "60" "0" "0" "100" "40"
"announcerVO" "vo/announcer/" "" "" "" "" "60" "0" "0" "100" "40"
"wheatleyVO" "vo/wheatley/" "" "" "" "" "60" "0" "0" "100" "40"
"caveVO" "vo/cavejohnson/" "" "" "" "" "60" "0" "0" "100" "40"
"coreVO" "vo/core" "" "" "" "" "60" "0" "0" "100" "40"
"inTBeam" "player_enter_tbeam_lp" "" "" "" "" "60" "0" "0" "100" "40"
"gelBounce" "player_bounce_jump_paint" "" "" "" "" "60" "0" "0" "100" "40"
"epilogueMusic" "music/sp_a5_x1" "" "" "" "" "60" "0" "0" "75" "40"
"Music" "music/" "" "" "" "" "60" "0" "0" "75" "40"
"beep" "xray/beep" "" "" "" "" "60" "0" "0" "75" "40"
"bullethit" "impact_bullet" "" "" "" "" "60" "0" "0" "100" "40"
"bulletmiss" "nearmiss" "" "" "" "" "60" "0" "0" "100" "40"
"Explosions" "explo" "" "" "120" "" "60" "0" "0" "100" "40"
"Player_Fall" "fall_whoosh" "" "" "" "" "60" "0" "0" "100" "40"
"Portalgun" "portalgun" "" "" "" "" "60" "0" "0" "100" "40"
"Player_Weapons_Loud" "weapon" "Player" "" "140" "" "60" "0" "0" "100" "40"
"Player_Weapons" "weapon" "Player" "" "" "" "60" "0" "0" "100" "40"
"Player" "player/" "Player" "" "" "" "60" "0" "0" "100" "40"
"turrets" "npc/turret" "" "" "" "" "60" "0" "0" "100" "40"
"defective_turrets" "vo/turret" "" "" "" "" "60" "0" "0" "100" "40"
"NPC_Voice" "" "NPC" "CHAN_VOICE" "" "" "60" "0" "0" "100" "40"
"NPC_Weapons_Loud" "" "NPC" "CHAN_WEAPON" "140" "" "60" "0" "0" "100" "40"
"NPC_Weapons" "" "NPC" "CHAN_WEAPON" "" "" "60" "0" "0" "100" "40"
"NPC_Body" "" "NPC" "CHAN_BODY" "" "" "60" "0" "0" "100" "40"
"NPC_Looping" "" "NPC" "CHAN_STATIC" "" "" "60" "0" "0" "100" "40"
"NPC" "" "NPC" "" "" "" "60" "0" "0" "100" "40"
"Ambient" "ambien" "" "" "" "" "60" "0" "0" "100" "40"
"Container" "container" "" "" "" "" "60" "0" "0" "100" "40"
"Robot" "robot_parts/" "" "" "" "" "60" "0" "0" "100" "40"
"Trains" "plats/" "" "" "" "" "60" "0" "0" "100" "40"
"Doors" "doors/" "" "" "" "" "60" "0" "0" "100" "40"
"Buttons" "buttons/" "" "" "" "" "60" "0" "0" "100" "40"
"Items" "items/" "" "" "" "" "60" "0" "0" "100" "40"
"Beams" "beams/" "" "" "" "" "60" "0" "0" "100" "40"
"Vehicles" "vehicles/" "" "" "" "" "60" "0" "0" "68" "40"
"Vehicles_Looping" "vehicles/" "" "CHAN_STATIC" "" "" "60" "0" "0" "68" "40"
"Physics" "physics/" "" "" "" "" "60" "0" "0" "100" "40"
"Dialog" "combined/" "" "" "" "" "60" "0" "0" "100" "20"
"Combat" "explo" "" "" "110" "" "60" "0" "0" "100" "40"
"Weapons" "weapon" "" "" "120" "" "60" "0" "0" "100" "40"
"Quiet" "" "" "" "0" "70" "60" "0" "0" "100" "40"
"Medium" "" "" "" "71" "90" "60" "0" "0" "100" "40"
"Loud" "" "" "" "91" "100" "60" "0" "0" "100" "40"
"VeryLoud" "" "" "" "101" "149" "60" "0" "0" "100" "40"
"SuperLoud" "" "" "" "150" "" "60" "0" "0" "100" "40"
"All" "" "" "" "" "" "60" "0" "0" "100" "40"
"Claw" "asdfasdf" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingSm" "asdfxxx" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingMd" "asdfwww" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingLg" "asdfyyy" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingXl" "asdfbbb" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingXxl" "asdfhhh" "" "" "" "" "60" "0" "0" "100" "40"
"ReducedDuckingMstr" "asdfqqd" "" "" "" "" "60" "0" "0" "100" "40"
"testTBin" "asdfaef" "" "" "" "" "60" "0" "0" "100" "40"
"testGelBounce" "asxdrf" "" "" "" "" "60" "0" "0" "100" "40"
"testGelSpeed" "asxdrf" "" "" "" "" "60" "0" "0" "100" "40"
"unduckedMusic" "music/" "" "" "" "" "60" "0" "0" "75" "40"
"unTBeam" "untbeam" "" "" "" "" "60" "0" "0" "100" "40"
"xLoud" "xloud" "" "" "" "" "60" "0" "0" "100" "40"
}
Thanks a lot for your time!smile.png

"Portal.Glados_core.Crazy_19"
{
"channel" "CHAN_VOICE"
"volume" "1.0"
"soundlevel" "SNDLVL_70DB"
"wave" "vo/aperture_ai/escape_02_sphere_cakemix-19.wav"
}

It's just a way to format certain information. This would be a "markup language"-type usage.

The quotation marks are optional, but are required when certain symbols that might confuse the program reading the file are used. Any spaces or tabs or symbols for example. "If a value has a space or tab character within it, wrap it in "quote marks"." (from the wiki)

My guess would be:
"Portal.Glados_core.Crazy_19"	//The name the game uses to load this.
{
	//<key>		<value>
	"channel"	"CHAN_VOICE"	//What sound channel to play the sound on.
	//There's usually about 8 or 16, but all of them might not be used. Valve here seems to have dedicated
	//certain channels for certain purposes. This channel is for voiceovers (almost all of Glados' dialog
	//is voiceovers, but that probably changes when she's a potato).
	
	"volume"	"1.0"	//The volume to use to adjust the sound file. 0.0 is silent, 1.0 is the
	//default volume. You can only decrease the volume here (if it's too loud), you can't increase it.
	//The sound volume is later modified by dozens of other things (how far you are from the sound in-game,
	//how high the player has his speaker/headphone volume adjusted, and so on). According to the wiki,
	//certain sound channels in Portal 2 aren't affected by distance. CHAN_VOICE (for voiceovers) are
	//probably one of those.
	
	"soundlevel"	"SNDLVL_70DB" //The wiki says it's preset levels of 'attenuation' - which, me not
	//being a audio guy, you'd understand better than me. The wiki lists the different options.
	
	"wave"		"vo/aperture_ai/escape_02_sphere_cakemix-19.wav" //The actual sound file.
}
The game internally reads these files, and looks specifically for certain names, like 'channel', 'volume', 'soundlevel', and so on. If you added a new name, like this:
myname	myvalue
In some circumstances, the game will entirely ignore unknown names and be blind to it, because it's not already looking for that value. Other times, it's expecting you to provide your own names, because you're creating new objects for the engine. It completely depends on what the engine is expecting - so the documentation has to be looked up on a case-by-case basis.

The 'name' here, is usually called a 'key', and the name and the value together is called a 'key-value pair'.
The game already has keys in mind, so it already knows about keys called 'soundlevel', and so uses the key to find and load the value from the file. It doesn't know what the value is ahead of time, and the point of the file is to provide the value so it doesn't have to be hard-coded into the game, and can be modified by developers (and modders) easier and faster during development.

The point of these files is primarily so that the audio and art people can add and modify the content of the game without having to learn programming, as well as so even the programmers can modify stuff without waiting for a dozen minutes for the game to 'recompile' before the change can be visible. It's for rapid changes for more flexible development, as well as allowing the artists and musicians and game designs to make changes without having to depend on the programmers. Programming itself is super fun though! (it often is an acquired taste and might not seem fun at first) But it's an entire project in itself - well worth pursuing, but perhaps after you've finished your Portal 2 mod.

The wiki says about the filepath of the sound file (identified by the "wave" key):
"All filepaths within a soundscript are relative to the sound folder."

However, it might be located in a special archive file where multiple folders and files are combined into a single file (similar to .zip files in Microsoft Windows). See here and here.

About the key-value thing: The value can be a collection of more key-value pairs.
The key "Portal.Glados_core.Crazy_19", is the identifier for the value that begins with '{' and contains more key-value pairs and ends with '}'. This is sometimes called a 'structure' or 'object'.

This would be valid:
key
{
    key value
    key value

    key
    {
        key value
    }

    key value
}
An real example of this would be where they talk about rndwave.

Keys can also have more than one value:
key value1 value2 value3 etc...
Depending on how the engine handles it, only certain keys should have multiple values. The order of the values matter, so you have to look up in the documentation what each value represents.
Example:
//position x y z
position 50 150 100
If 'position' is the key, then x,y, and z are the location in 3D space. You can't mix up the orders of them, or you'd be putting it in the wrong 3D location. In this specific case, the individual multiple values are often called 'arguments'.

So in your second file:
"MixGroups" //Key
{
   //Key		//Multiple values
   "potatosVO"		"vo/glados/potatos" ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
   "gladosVO"		"vo/glados/"        ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
   "announcerVO"	"vo/announcer/"	    ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
   "wheatleyVO"		"vo/wheatley/"      ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
   "caveVO"		"vo/cavejohnson/"   ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
   
   //...and more stuff...
}
So in this case, the engine is looking specifically for a key named "MixGroups".
Inside MixGroups, it actually is expecting the developers to provide their own keys.
The keys then take a specific fixed number of values/arguments, each argument having a specific purpose/meaning.
You'll have to look up the documentation or ask on Portal 2 modding forums for the meanings of each argument.
"gladosVO"  "vo/glados/"  ""  ""  ""  ""  "60"  "0"  "0"  "100"  "40"
Here, the key (gladosVO, the quotes are optional) has 10 arguments. The order of the arguments matter and each means something different.
Because they are fine with the default values for four of the arguments, they left them empty. I'm guessing that in this specific case, an empty argument means 'use the default'. The reason why they are quoted, is because this:
"gladosVO"  "vo/glados/"                  "60"  "0"  "0"  "100"  "40"
...makes it look to the engine like there are only 6 arguments, and puts them in the wrong locations (putting "60" as argument 2 instead of the correct place at position 6).
Quoting nothing is a way of providing nothing as an argument (and thus using the defaults) while not confusing the engine about the number or positions of arguments.

Yikes, what a mind bender! SND_LEVEL is attenuation level? I've seen a seperate parameter called "attenuation", so that's confusing. Attenuation normally refers to how sound gets quieter as you move away from it's source, which has an omni_directional radius. UDK allows for the sound designer to adjust properties of the fall-off curve, but this suggests that Valve's attenuation properties are somewhat set in stone. I can't actually move onto this yet, as I'm stuck on creating an env_soundscape that actually plays. I believe they can be triggered, but I'm unsure how to create a trigger area. Which tool in Hammer would be used to create trigger-able entities?

It's been a long time since I've played with Hammer. You're likelier to find people capable of answering that kind of question on a Source Engine modding forum - there's alot of tutorials for Hammer floating around the 'net as well. Maybe this helps?

The Source Engine has alot of different trigger brushes, for when you touch, look-at, or use the activate key, on a piece of the level. There's also trigger_soundscape, which I've never used but looks promising, and other sound-specific triggers.

Yeah, trigger soundscape is what I need. You're clearly a forum guru! Really appreciate your help =] I'm going to ask, in the sound section, about audio programmers, and then I may return asking for beginners programming advice. :)

This topic is closed to new replies.

Advertisement