The recommended format for audio playback in HPL3 is the FMOD sound bank format. This is a special format that allows a number of sound files to be bundled together into a single library package as well as technical settings (such as reverb) to be easily accessible by the game engine. To create files in this format, download the FMOD Ex Designer software.
Also, to understand exactly how audio is handled in HPL3, you should go and read through Sound, as it covers the technical side in much greater detail than can be accomplished here.
Replacing the .snt file format used in HPL2, an FMOD soundbank file is the preferred method of storing audio files for your mod. It allows sound to be played from within the game world, letting the player hear it in relation to where they are and where they are facing. It also lets you fine tune your audio in a number of different ways as well as define a number of game-engine specific properties.
This guide will show you how to create a very basic sound bank for use in your mod. First, start up FMOD Designer and create a new project. You can name it whatever you like, but it is recommended to give it a name that lets you and others know what kinds of audio files will be inside it.
When you first create the project, it will show you the following screen. (There will also be an event group created by default called “untitled”. Delete this event group for now via “Right Click > Delete”.)
The first thing we need to do is create an event group. An event group is a way to organize the sound events within your sound bank, similarly to how files are stored on your computer. You can create as many groups as you want, as well as creating groups within a group, but for now, let's just create a single group. Name it whatever you want, within reason.
Following this, we want to create the sound event itself. An event in FMOD represents a sound or sounds being played, and they contain most of the properties that you would want to set to a sound. (When you play a sound from within the game, you will be using the name of this event.)
Our event is currently empty, so we want to add a sound file to the playlist. This controls what sounds will be played when the event is triggered.
Our events are good for now, so next we want to create a sound definition. A sound definition represents the sound file itself. Click on the “Sound Defs” tab, right-click the window on the left, and select “Add sound def(s) from sound files…”. In the dialog box, select the sound file you chose for your event. All the relevant properties will be set for you, so that's all you need to do here.
When you created the project, a soundbank was created for you, but it is likely named something obnoxiously obtuse like “YourProjectName_001”. For the sake of clarity, you might want to rename it to something more helpful. Click on the “Banks” tab, select the soundbank from the list (of one) on the left, and rename it in the properties window on the right in the “Name” box. (This step is optional but recommended.)
Your soundbank is now complete (don't forget to save), but you still need to generate the files that HPL3 is actually going to use. To do this, go to the Project menu and select “Build…”. In the dialog, check the box next to your soundbank, then press “Build”.
You are now ready to use your newly-created soundbank within your mod. After all is said and done, the files in your sounds folder should look like this.
Most of these files are development or temporary files generated for you by FMOD Designer, but when you release your mod you only need the files ending in “.fdp” (the project file), “.fev” (the event-definition file), and “.fsb” (the soundbank file).
There are a number of functions provided by HPL3 to create and manage sounds played within the game. The game-related information relevant to the sound is either stored within the soundbank files or generated at run-time using Soundscape areas, so the functions themselves are relatively simple to use.
These functions are as follows:
//////////////////////////////////////////////////////////////////////////////// // Remember to add "#include <helpers/helper_audio.hps>" to the top of your // script file before using these functions. // Basic playback functions void Sound_CreateAtEntity(const tString &in asSoundName, const tString &in asSoundFile, const tString &in asEntity, float afFadeTime = 0.0f, bool abSaveSound = false, float afTargetVolume = 1.0f) void Sound_Play(const tString &in asSoundName, float afFadeTime, bool abResetVolMul = false) void Sound_Stop(const tString &in asSoundName, float afFadeTime) void Sound_Fade(const tString &in asSoundName, float afVolumeDest, float afFadeTime) bool Sound_Exists(const tString &in asSoundName) // Advanced playback functions Sound_CreateAtEntity_UsePrefix(const tString &in asSoundName, const tString &in asSoundFile, const tString &in asEntity, float afFadeTime, bool abSaveSound, float afTargetVolume = 1.0f)
This function creates a sound dynamically, positioned at the specified entity, and plays the sound immediately. Sounds created in this way will be given a name, which can be used in other functions to affect a sound without creating a new one. (Useful for loops or sound effects.)
Using this function to create a sound from an FMOD soundbank requires that the sound file name is given in the following format: “SoundbankFileName/Event/Group/Names/EventName”.
// Example Usage Sound_CreateAtEntity("speaker_beep", "level_sounds/speaker/beep", "intro_speaker");
This function makes an existing sound object begin playing. The sound object can be placed in the level editor or have been created by a previous call to Sound_CreateAtEntity.
// Example Usage Sound_Play("explosion_bomb_*", 0.1);
This function stops the playing of a currently playing sound.
// Example Usage Sound_Stop("interrupting_cow", 0); === Sound_Fade === This function gradually changes the volume of a sound from its current volume to a new one. * **asSoundName**: The name of the sound. (Supports wildcard characters (*) for affecting many sounds at once.) * **afVolumeDest**: The target volume to fade to. (0.0 - 1.0) * **afFadeTime**: The time in seconds to fade from the old volume to the new one. <code>// Example Usage Sound_Fade("ominous_noises_*", 0.25, 3.0);
This function checks whether a sound object exists.
// Example Usage if (Sound_Exists("horse_noise_*")) { // Magic happens here... }
This function works similarly to Sound_CreateAtEntity with one major difference. If the sound object is created within a soundscape, this function will look for any specialized sound events in the soundbank for use within that soundscape. For example, if a sound with the event path “groupname/footstep” is created within the “smallroom” soundscape, this function will try to use the sound event named “groupname/smallroom/footstep”.
Using this function to create a sound from an FMOD soundbank requires that the sound file name is given in the following format: “SoundbankFileName/Event/Group/Names/EventName”.
// Example Usage Sound_CreateAtEntity_UsePrefix("footstep", "level_sounds/player/footstep", "player");
WIP
Voice files are a specially handled form of audio in HPL3. Their main purpose is to represent the sound played from character voices, either in audio logs or in an active dialogue (such as the conversation with Dr. Munshi). They are also used to represent character barks (e.g. random sounds from monsters).
Unlike FMOD soundbanks, voice file audio sources are stored in a raw audio format, usually in a designated lang folder. The voice files themselves are special XML files that detail dialogue trees, handle subtitles, and generally manage the playback of audio files in character interactions.
Like FMOD soundbanks, voice files need some setup before they can be used in-game. The way they are created is with the VoiceHandler utility program that comes bundled with SOMA.
1. Set up a standalone mod if you haven't already done so
2. Record voice lines and save them as .ogg
3. Create a .voice file (see “Creating a .voice file, step-by-step” below)
4. Create a “lang” folder in your mod directory, with the following path pattern:
SOMA\mods\[ExampleMod]\lang\eng\voices\[YourMapName]\[YourDialogFile].ogg
5. Add these two lines to your mod's “resources.cfg” file:
... <Directory Path="/lang/eng" AddSubDirs="true"/> <Directory Path="/voices" AddSubDirs="true"/> ...
6. Rename each .ogg file of dialog to match the “File Name” in each voice handler line entry
7. In your map's .hps script file, trigger the “Subject” from your map's .voice file by adding this line (replacing “SubjectName” with the Subject that dialog line is located in when you made a .voice file):
Voice_Play("SubjectName");
8. (optional) Get “Test Voice Over” button to work
To start, we will need to open that program and create a new project.
For the purposes of this tutorial, I will be making a voice file dialogue out of this free audio clip, featuring a short one-sided conversation between an NPC in a game and a ghost. In order to use it in our dialogue, however, the clip must be split into a number of distinct audio files, each representing a particular line of dialogue. I won't be covering this step in detail, but using a free utility like Audacity this process is relatively straightforward.
Before we can create our dialogue, we need to create the scenes that the dialogue will be a part of, as well as any characters who participate in it. For this tutorial, we only have one scene, and our conversation only has one vocal participant.
Click on the “Voice Settings” tab and create a new voice scene and character. The scene only needs a name, and that can be whatever you like. The character has two fields that we care about: “Name” and “Display Name”. The Name is the name of the character that the voice file will use when deciding who is talking at the moment while the Display Name is the name that will appear in the subtitles.
Heading back to the “Subjects” tab, it's time to create our dialogue. In voice file vernacular, every chunk of dialogue is called a “Subject”, and each is handled as its own branch of conversation. Click the “Add Subject” button at the bottom-left of the window.
There are a lot of text boxes that pop-up with a new subject, but most of these aren't necessary for what we are currently doing, so ignore those for now. If you want, clicking the “Hide Options” box in the top-right will hide most of these boxes. (Don't do this now, however, as some of these boxes we will need later.)
The subject's name by default is “Subject0”, but we want to rename that into something a bit more useful. We are also going to want to select the “Scene” drop-down menu and select the scene that we created earlier.
Now it's time to create the dialogue itself. In the drop-down menu called “Select Character”, choose the character we created for this dialogue. Then in the box next to it, type out the text that subtitles the first line of the dialogue.
When that's finished, press the enter key to add a second line. Repeat this for all the lines in the dialogue.
Next, we need to hook up the lines of dialogue with the actual audio files. To do this, click the arrow button next to each line, and under “File Name” type the name of the audio file to be played. Do this for every line of dialogue.
That's all we need. Now it's time to save the voice file.
The most common place to save a voice file is in the same directory as the map files the voices will be played on. When doing this, name the voice file the same name as the map (for example, if your map is named “scary_map.hpm”, name the voice file “scary_map.voice”). This ensures that the voice file and the map will be paired correctly when the game is launched.
(This section is currently a work in progress.)
The easiest way to play a voice file is to use the Voice_Play function.
bool Voice_Play(const tString&in asSubject, int alSpecificLineIdx=-1, const tString&in asCallback="", int alPrio=0)
This function starts the playback of a voice subject. Only one subject may be playing at any given time.
// Example Usage Voice_Play("OldMan_01", -1, "OldMan_SubjectComplete");
The simplest way to play an audio file is to do so directly. This has the benefit of having the most straight-forward implementation (just drop your audio files into your mod folder and you're done), but it comes with the drawback of not being able to position the sound in the world. This could be the preferred method for audio playback during mod testing or in times when player position relative to the sound is unnecessary, such as when playing sound from a terminal or when the audio source is right in front of the player.
The relevant functions to achieve this are the following:
//////////////////////////////////////////////////////////////////////////////// // Remember to add "#include <helpers/helper_audio.hps>" to the top of your // script file before using these functions. // Basic playback functions void Sound_PlayGui(const tString &in asSoundFile, float afVolume, eSoundEntryType aEntryType = eSoundEntryType_Gui) void Sound_FadeInGui(const tString &in asSoundFile, float afVolume, float afFadeTime) void Sound_StopGui(const tString &in asSoundFile, float afFadeTime, bool abPlayEnd = true) bool Sound_GuiIsPlaying(const tString &in asSoundFile) // Advanced playback functions void Sound_FadeGuiVolume(const tString &in asSoundFile, float afVolumeDest, float afFadeTime) void Sound_FadeGuiSpeed(const tString &in asSoundFile, float afSpeedDest, float afFadeTime)
This is the base function for your audio-playing needs. It plays a sound from an FMOD sound bank, a .snt file, or a raw audio file. (.wav, .ogg, .mp3)
// Example usage Sound_PlayGui("sounds/button_beep.ogg", 1.0);
Functionally similar to Sound_PlayGui, except it allows the option to specify a fade-in timer to your audio.
// Example Usage Sound_PlayGui("sounds/building_tremor.ogg", 1.0, 3.5);
This function allows you to manually stop the playback of an audio file. It also allows the option to specify a fade-out timer.
// Example Usage Sound_StopGui("sounds/sudden_noises.ogg", 0.0);
This function lets you check to see if a sound file is currently playing or not.
// Example Usage if (Sound_GuiIsPlaying("sound/quizzical_music.ogg)) { // Some magic happens here... }
This function allows you to change the volume of a currently playing sound file.
// Example Usage Sound_FadeGuiVolume("sound/be_quiet.ogg", 0.25, 0.75);
This function lets you change the playback speed of a currently playing sound file. This operation does affect the pitch of the sound.
// Example Usage Sound_FadeGuiSpeed("sound/helium_talking.ogg", 2.0, 0.5);