Skip to content
Mgamerz edited this page Sep 29, 2024 · 5 revisions

Required tools

For LE1 audio editing, you will need multiple tools:

  • Audacity (or a way to make your audio into .wav)
  • ISACT 1.64
    • We have found that you need to close most programs to have the installation run due to some internal issues in the installer.
    • Your primary screen on your computer needs to be around 1080p or smaller, or the application seems to crash on launch.
    • You may need to copy a 32-bit OpenAL32.dll next to the application (ips.exe) - you can find a copy in Mass Effect’s (2008) Binaries folder.
  • Legendary Explorer Nightly 6.3+ (available through ME3Tweaks Mod Manager's tools menu)

This page currently shows how to replace LE1's streaming audio, we are still working on tooling for non-streaming audio. This informational guide is still a work in progress. While this may work on ME1, the OT scene is effectively dead, and I did not attempt to try this on OT, nor will I expend effort to make it work with it if it doesn't.

Audio concepts for LE1

Audio editing in LE1 is time consuming and pretty tedious. If you mess it up, it will break various parts of audio in the game.

First, we must explain the two different types of audio in the game: streaming and non-streaming audio.

Streaming audio

Streaming audio is audio that is streams (is read in short chunks over time) directly out of the ISB files located in the ISACT (and DLC mod) folders of the game. Streamed audio is typically a few seconds or longer, and is streamed to reduce memory overhead. Streaming audio in LE1 is typically localized voiceover and music. Streaming Audio uses a BioSoundNodeWaveStreamingData export that is linked to SoundNodeWave exports via a property. There will be no data in the SoundNodeWave export.

Non-streaming audio

Non-streamed audio is commonly done as sound effects and other short bursts of non-localized audio. This audio is stored directly in the binary segment of SoundNodeWave exports, in the RawData section. The data format is as follows:

0x0 INT Embedded ISB Offset (from this address) 0x4 RIFF FILE Embedded ICB - stripped to only contain the sound event

?> RIFF FILE Embedded ISB - stripped to only contain the single sound sample data

Unreal + ISACT

To properly edit audio, we must first understand how BioWare integrated the ISACT engine into their version of Unreal Engine 3.

Audio in LE1 is referenced by sound cues and sound node waves. Sound Cue's are what the engine uses to request audio to play, which in turn plays the SoundNodeWave, which is what actually plays the stored the audio. BioWare’s implementation moves the streaming audio out of this export and moves the metadata to BioSoundNodeWaveStreamingData exports.

SoundNodeWave exports are serialized as “bulk data”, which is a common unreal engine 3 format to store data in. Data will exist in the RawData section, which you can see in Binary Interpreter in Legendary Explorer. If there is no data in that section (size = 0), it means this is streaming audio. Streaming audio will have a reference to a BioSoundNodeWaveStreamingData object in the properties of the SoundNodeWave. This object contains an ICB and a special ISB file, which in turn are both used to play audio from the external ISB file. It is important that your exports are properly named, or the game will not know how to use the data.

Some streaming SoundNodeWave's in the games will not have a reference to the BioSoundNodeWaveStreamingData. This was created in ISACT during game development but the audio was never imported; thus it was never included in the games.

Streamed audio notes

Streamed audio can only be by adding new audio to the game and repointing existing references to it. Replacing existing vanilla audio is very difficult and is not worth the amount of time it would take to implement. For streamed audio, you will need to use the ice hack tool to create the audio, The bank builder tool to prepare the audio and legendary explorer to import the audio as well as linking it up to the game.

Non-streamed audio notes

Non-stream audio is complicated in the sense that we can replace vanilla audio, but we cannot clone and add new audio without breaking several things due to how the engine internally works. This can be difficult to understand as it differs from the later games which allow you to simply clone exports and replace their data. If you wish to add new non-streaming audio, you will need to import it through the ISACT tool, the same way as done when importing new streaming audio. This is because a proper ICB and ISB are created for the audio which the game internally uses to actually play the data.

To replace existing audio, find a SoundNodeWave export that contains non-streaming audio and use sound panel to replace it. It will convert your data to an ogg format which will be updated in the game. You may need to ensure that all instances of that export are identical or you may have incorrect audio played based on what was previously loaded.

ISACT

The version of ISACT used by the game is a slightly modified BioWare fork of the original 1.64 release of ISACT. This audio engine is very old, and appears to have been abandoned within two years of it coming out of beta status in 2006. As such, the tooling for this engine is very old and it's not easy to use nor is it easy to run. You will need to be sure that the primary screen on your computer is not above 1080p or the application will crash on launch.

Inside of an ISACT installation you will find PDFs that serve as virtually the only documentation in existence on ISACT, which I've linked below here for convenience.

ISACT Banks

ISACT breaks audio into two different components: ICB and ISB. These two components are used together to play audio in the game.

  • ICB stands for ISACT Content Bank. Content banks contain information on what audio to play, and how, such as looping. Content banks are semi-analogous to WwiseEvents from later games.
  • ISB stands for ISACT Sample Bank. Sample banks contain the actual audio samples and information about the audio sample. They are semi-analogous to WwiseStream from later games.

A third type which you may see referenced in documentation is SAC - this is the project file that encompasses multiple ICB and ISBs. The only reason we use these is to save our work in ISACT, we don’t use them in game.

Tutorial: Replacing sound effects (non-streaming audio)

This part is currently in development in the toolset!

Tutorial: Using ISACT to replace the title screen music (streaming audio)

This will be a brief tutorial on how to replace the splash screen's music. It will teach you the basics of replacing music in the game - other things like voice over are slightly different - an updated tutorial may appear in the future for that use case. For this example I will be using a .wav version of this track from the game Astral Chain. I would not ship this as it is licensed music, but for personal use it is fine.

We first need to pick the name of our package we will be storing music under. While this specific name doesn't have any hard naming requirement, LE1 uses a lot of naming conventions it assumes are being used. We will use the name music_astral. I suggest music banks start with music_. There are others, such as ss_ for soundset, c_ for sound effects, and se_ for sound entities.

To begin, we first open ISACT and create a new sample bank by right clicking in the sample bank tab and selecting new bank. We will name the bank music_astral.isb. We also do the same thing for the ICB in the content tab by creating a new content bank and naming it music_astral.icb, in the same folder. These files need to be named the same but with different extensions.

image

I recommend making a subdirectory named output as well at this point, we will be using it later. image

At this point, save your work by going to the file menu and saving your project in the same directory as your ISB/ICB. ISACT is very prone to crashing and you will quickly find yourself losing work if you do not save often.

Prepare the sample bank

We need to first set our bank as a streaming sample bank, otherwise it won't work for streaming, and you will get errors later in this process. Right click your bank and select Properties. In the options panel, make sure it is set to a Streaming Sample Bank. The vanilla version of the music bank uses a 2000ms packet size, so we will also use that value.

image

Import your music audio sample by going to your sample bank and right clicking it, and then doing New. In the dialog that shows up, pick Audio Sample under Content Object.

image

Once you select your .wav, you may be asked if you want stereo or mono, choose whichever you prefer. As this is music, I'm going to leave it in stereo.

image

You will see your clip in index 0 of the ISB, like this:

image

If you wish you add more audio tracks, you can do so the same was as above. However, we will only be adding one for this tutorial. You do not need to change any of the target platforms or target formats. Make sure you've saved your work at this point.

Prepare the content bank

We will now prepare the content bank, which is how the audio engine knows what to play out of the ISB. This system is still being researched as BioWare's usage of the system doesn't appear to fully match the ISACT documentation's intended usage.

For the title screen music, we need two objects: A sound event, which plays a piece of audio. We also need a sound queue, which is a list of events to execute. Not all audio needs a queue, but for the title screen to loop it does. Note that some audio can loop via unreal properties/objects, but we are mimicking how the title screen audio is set up for this tutorial.

Right click your content bank and select New. Select Sound Event.

image

The name of this does not typically matter, but you will may need to create this name in unreal files, so make sure it works there too. I'm going to name mine astralplane. I leave the rest of the objects as default.

image

This next step is not intuitive - you need to add your audio sample to your sound event's panel that just opened. The only way this is done is via drag drop. Go to your sample bank and drag/drop the music sample from the tree to the blank sound event panel, as shown here: image

You will now see it added:

image

You can change settings here if you wish, though the game can also override many of these in the properties, such as volume.

Return to your content bank and make another new object, this time a Sound Queue. This is what we will point the game to play, and following the vanilla game's sound event setup for the title screen, it is prefixed with mus_. So I named mine mus_astralplane.

image

You will be greeted with a completely blank window. In another not-so-intuitive user interface design, you need to drag/drop your sound event you made earlier to this panel. It will populate a row, in which we will check the Looped button.

image

That's all we need to do in ISACT. You need to save your work at this point. If you wished to do more than 1 piece of audio, the above directions can be repeated - banks can contain multiple objects. We will close ISACT now.

Build shipping versions of the banks

With our 2 banks built, we need to now make the versions that the game will actually use. The current versions don't use compressed audio and are very large and impractical to use. There is a tool included in ISACT named BankBuilder, which prepares our files for use by a target platform. For bankbuilder to work, you need to make sure ogg.dll and vorbis.dll are in the same folder as BankBuilder, which by default, for some reason, are not. You can copy them out of the ISACT folder where ips.exe is located a few directories up.

We will need to switch to the command line to run BankBuilder.exe. The easiest way for users who don't actively use command line is to type the command 'cmd' into a file explorer window in the directory you want it to open to.

image

We then need to issue the conversion command - note there are no spaces between the parameter and the value.

BankBuilder.exe -i"<Directory where your .icb/isb is>" -o"<The output directory you made earlier>" -cOGGVORBIS -pWindows -q0.8

The parameters listed are as follows:

  • -i: Input directory. It should be put into quotes since it may contain spaces.
  • -o: Output directory. It should be put into quotes since it may contain spaces. Ensure this is not the same as the input directory.
  • -c: The compressor codec. We use OGGVORBIS.
  • -p: The target platform. This may not be required; but I specify it anyways.

Here is the command I ran for my specific local setup and the output of it: image

It will take a few seconds while your audio is compressed to Ogg Vorbis. You will get an icb and isb file in your output directory you specified in the command; it should be the same one we made earlier. You will likely also get a .sac file, but that file is not useful to us.

Prepare the Unreal side

We no longer need to use any of ISACT or things it comes with. From here on out we will be doing things on the package side of things.

To change the title screen audio, we will need to do the following in game files:

  1. We need to make a new package file has all of the information necessary to play streaming audio. The 2DA we edit in step 2 will reference this package file.
  2. We need to update Engine.pcc's UISounds_GuiMusic Bio2DA table. Since the music plays before DLC mount, we have to edit Engine.pcc. This should be updated via a merged 2DA table for all other music or you will have incompatible changes. We will use a merge mod for this so we don't need to replace the entire Engine file.

First, we need to make a DLC mod in ME3Tweaks Mod Manager. I am naming mine DLC_MOD_AstralMusic. We need to make an additional folder named Content next to CookedPCConsole, and within it, make and Packages folder, and within that, a ISACT folder. We will eventually move our processed ISB there; however do not do it now. The path in your mod will be <DLC mod>\Content\Packages\ISACT.

Creating the music package file

First, we need to create a package file that contains a SoundCue, a SoundNodeWave, and a BioSoundNodeWaveStreamingData object. The sound cue will reference the sound node wave, which will reference the streaming data, which will reach out to the external ISB.

You can use this template package to create a blank, single audio sample file. You can expand it further if you wish via cloning, but for this tutorial, or as a starting file, this template will speed things up. If you expand or make your own, you need to make sure that the root level non-package exports do not have the ForcedExport flag or the game will not find the object in memory when it dynamically loads it. The BioSoundNodeWaveStreamingData and its containing packages need the ForcedExport flag.

The template package file looks like this:

image

We will need to adjust the object names and import a new binary blob for the BioSoundNodeWaveStreamingDataObject under the DVDStreamingAudioData package. Rename this file to music_astralplane.pcc and open the renamed version so we can edit it.

The SoundCue name must match the object name we want to play in ISACT's content bank; in this case, mus_astralplane. The SoundNodeWave name must be in the following format:

ISBNAME:ICBObjectName

In this instance, our ISB is named music_astral, and our object we are playing is the sound queue object, mus_astralplane. So we name it music_astral:mus_astralplane.

Finally, we must update the streaming data. Rename the BioSoundNodeWaveStreamingData export to our ISB name, music_astral. Right click the export and select Import > Embedded File(s), and then select the PROCESSED ICB in the output directory we made earlier. The .isb file that was processed also must be in this folder; the import step reads both files and builds a streaming data blob for that ICB/ISB pair.

image

In technical terms, the sample data is stripped out of the ISB, a new soff chunk is added that contains the offset of the Ogg Vorbis sample data, and then the ICB and stripped ISB are paired together.

NOTE: You may get an error at this step if you forgot to set a streaming bank. Please come to the ME3Tweaks Discord if you have issues at this step, we are still working this step out, and the error codes are not labeled in LEX currently (Sept 14 2022).

NOTE: Your sound cue export will specify a SoundGroup - this is what groups different types of audio together. If you're doing voiceover, you will need to change this otherwise it will not respond to in-game events properly like pausing or player death. Look at other sound cues to identify their group.

The final package should look something like this:

image

Save this package to your DLC mod's CookedPCConsole folder. You can close the file; we don't need it anymore. At this point, we can also move our processed ISB file to the <DLC Mod>\Content\Packages\ISACT folder we made earlier.

Updating Engine.pcc

Finally, we need to update the reference that the game uses when it's time to play the main menu theme. We open Engine.pcc for this; do NOT copy it to your DLC mod. We will first edit Engine.pcc to verify it works; we will then extract our changes to a merge mod.

In Engine.pcc, there is a Bio2DA table named UISounds_GuiMusic. Locate this in Package Editor and go to the Bio2DA tab. image

The row we are editing is the MainMenu row; we need to change the MusicResource column to be our package's SoundCue export memory path. LE1 will dynamically load our object if is not loaded in memory. First, we need to add our SoundCue's full memory path as a name, so press CTRL + SHIFT + A to add a name. We enter music_astral.mus_astralplane, as that is our PackageFile.ObjectName as well as it's memory path once the package is loaded. If you did not clear the ForcedExport flag on your Sound Cue earlier (the template already had it cleared), this step will fail as the memory path will not resolve correctly.

Set the Bio2DA value to this new name with an index of 0.

image

Commit the 2DA and save the package, and then install your mod. At this point, your DLC mod folder should look like this:

Y:.
|   AutoLoad.ini
|
+---Content
|   \---Packages
|       \---ISACT
|               music_astral.isb
|
\---CookedPCConsole
        DLC_MOD_AstralMusic_GlobalTlk.pcc
        DLC_MOD_AstralMusic_GlobalTlk_DE.pcc
        DLC_MOD_AstralMusic_GlobalTlk_ES.pcc
        DLC_MOD_AstralMusic_GlobalTlk_FE.pcc
        DLC_MOD_AstralMusic_GlobalTlk_FR.pcc
        DLC_MOD_AstralMusic_GlobalTlk_GE.pcc
        DLC_MOD_AstralMusic_GlobalTlk_IE.pcc
        DLC_MOD_AstralMusic_GlobalTlk_IT.pcc
        DLC_MOD_AstralMusic_GlobalTlk_JA.pcc
        DLC_MOD_AstralMusic_GlobalTlk_PL.pcc
        DLC_MOD_AstralMusic_GlobalTlk_PLPC.pcc
        DLC_MOD_AstralMusic_GlobalTlk_RA.pcc
        DLC_MOD_AstralMusic_GlobalTlk_RU.pcc
        music_astral.pcc

You should now be able to start the game and hear your audio! And... well, that's probably all you'll hear, as it's super loud. You can set the Volume property on the SoundNodeWave object in your music package:

image

That's much better. In the above picture it shows a duration; this does not appear to be used by the game, it was only for convenience in the original game's editor tools.

Conversion to Merge Mod

Merge mods allow us to ship export-level changes to basegame-only files so we don't have to do full file replacement, which is a compatibility nightmare. Now that we know it works, we can extract our 2DA to a package. You can read about Merge Mods on the Mod Manager documentation page.

To create the asset package, we create a new package in our Mod Manager's mod folder (not the DLC mod!) named MergeMods, next to our DLC mod folder. We save our package there; it can be anything - but don't name it after a vanilla file. I'm naming mine UISounds_GuiMusic.pcc. Once created, we can perform two drag/drop operations from Engine.pcc to make a tiny package file that has only our changes.

image

When porting these two objects, make sure you pick the Add only option. image

Save the package.

Now we create a new text file next to this package, and put in the following contents; if you want to understand it, please read the merge mod documentation linked above:

{
  "files": [
    {
      "filename": "Engine.pcc",
      "changes": [
        {
          "entryname": "BIOG_2DA_UI_X.UISounds_GuiMusic",
          "assetupdate": {
            "assetname": "uisounds_guimusic.pcc",
            "entryname": "BIOG_2DA_UI_X.UISounds_GuiMusic"
          }
        }
      ]
    }
  ],
  "game": "LE1"
}

I saved this as uisounds_guimusic.json, next to a package file of the same name that we just made. I then drag/drop this file onto ME3Tweaks Mod Manager; it will compile a .m3m file that the mod will use to install the changes.

Lastly, we need to add this to the BASEGAME header of the moddesc.ini file. Open the file in a text editor (or use the built-in moddesc.ini editor in Mod Manager) and add the following:

[BASEGAME]
moddir = .
mergemods = uisounds_guimusic.m3m

Reload the mod, and you should be done. To properly test, you will need to first restore Engine.pcc to make sure your changes actually apply.

Your final mod folder from the root should look like this:

|   moddesc.ini
|
+---DLC_MOD_AstralMusic
|   |   AutoLoad.ini
|   |
|   +---Content
|   |   \---Packages
|   |       \---ISACT
|   |               music_astral.isb
|   |
|   \---CookedPCConsole
|           DLC_MOD_AstralMusic_GlobalTlk.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_DE.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_ES.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_FE.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_FR.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_GE.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_IE.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_IT.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_JA.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_PL.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_PLPC.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_RA.pcc
|           DLC_MOD_AstralMusic_GlobalTlk_RU.pcc
|           music_astral.pcc
|
\---MergeMods
        uisounds_guimusic.json // Not referenced, will not actually be part of deployment package
        uisounds_guimusic.m3m
        uisounds_guimusic.pcc // Not referenced, will not actually be part of deployment package
Clone this wiki locally