EvilEngine/Sound Format

From Heavy Iron Modding
< EvilEngine(Redirected from Sound Format)

This page contains information on how sounds and music are stored in the games.

Sounds are usually contained in SND and SNDS assets, with the SNDI asset containing information about them. Each HOP file (sometimes the HIP) contains multiple SND and SNDS assets and one single SNDI asset. There doesn't seem to be an internal difference between SND and SNDS other than being stored as different assets; sound effects are usually in SND and voice lines and music (stored in mnu5.HIP in BFBB) are usually in SNDS.

SND/SNDS Format[edit]

SND/SNDS
Sound/Streaming Sound
TypeBinary
Games usedNight of 100 Frights

Battle for Bikini Bottom
The SpongeBob SquarePants Movie
The Incredibles
Rise of the Underminer

Ratatouille Prototype

GameCube[edit]

In Scooby-Doo: Night of 100 Frights and Spongebob Squarepants: Battle For Bikini Bottom, SND and SNDS are a GameCube DSP audio file stripped of its 0x60 byte header: all of a level's sound headers are kept separate in the single SNDI asset.

In The Spongebob Squarepants Movie Game, The Incredibles and Rise of the Underminer, the SND and SNDS assets are empty, and instead, all of the sounds are contained entirely in the SNDI asset.

Xbox[edit]

The audio format on the Xbox version of all 5 games is either raw IMA ADPCM, or raw 16-bit Linear PCM stripped of its *.wav header: all of a level's sound headers are kept separate in the single SNDI asset.

Playstation 2[edit]

The audio format on the PS2 version of all 5 games is a PS2 VAG sound file stripped of its 0x30 byte header: all of a level's sound headers are kept separate in the single SNDI asset.

SNDI Format[edit]

SNDI
Sound Info
TypeBinary
Games usedNight of 100 Frights

Battle for Bikini Bottom
The SpongeBob SquarePants Movie
The Incredibles
Rise of the Underminer

Ratatouille Prototype

GameCube (Night of 100 Frights/Battle For Bikini Bottom)[edit]

The SNDI has a 0xC or 0x10 byte header:

Offset Type Variable Description
0x00 int amount of SND Amount of headers for SND assets.
0x04 byte[4] null Padding
0x08 int amount of SNDS Amount of headers for SNDS assets.
0x0C int amount of cutscene SNDS Amount of headers for SNDS assets used in cutscenes. BFBB only.

After that, there are three consecutive arrays of SNDI entries: one for the SND, one for the SNDS and one for the cutscene SNDS. Each SNDI entry is 0x64 bytes long and follows this structure:

Offset Type Variable Description
0x00 byte[0x60] Sound Header Header of GameCube DSP sound file.
0x60 AssetID Sound Asset ID Asset ID of corresponding SND or SNDS asset.

GameCube (The SpongeBob SquarePants Movie - Ratatouille Prototype)[edit]

In those games, the SNDI contains not only the sound headers but also the entirety of the sound files themselves.

SNDI Header[edit]

The SNDI itself has a 0x20 byte header:

Offset Type Variable Description
0x00 AssetID uSoundInfoID Asset ID of this asset
0x04 uint uSumFSBSize / nOffsetFinalFSBEnd Offset relative to end of this header to the Footer section. Add 0x20 to get the absolute offset of the Footer.
0x08 int pFMusicMod null
0x0C int pFSBFileArray null
0x10 int pWavInfoArray null
0x14 int pCutsceneAudioHeaders null
0x18 ushort nWavFiles Total amount of sounds in SNDI
0x1A ushort nSounds Amount of sounds in the first FSB3 of the SNDI
0x1C ushort nStreams Amount of sounds combining all FSB3s which are not the first of the SNDI
0x1E byte nFSBFiles Amount of FSB3 files
0x1F byte nCutsceneAudioHeaders Amount of cutscene sounds in file. The values related to cutscene files are not addressed in the description below yet.

All sounds are contained inside FSB3 files. Each FSB3 can contain one or multiple sounds; in all files analyzed so far, most of the sounds are contained in the first FSB3 file, with each subsequent file containing only one. This is the structure of a FSB3 file:

FSB3 Header[edit]

This is the header of a FSB3 file. There is one per FSB3 in the SNDI.

Offset Type Variable Description
0x00 char[4] magic "FSB3" in ASCII
0x04 int numSamples Amount of samples in the FSB3. Each sample is a sound. However, unlike most FSB3 files in other games, here only one sample header is used for all sounds, which might be confusing, and a different, custom header is used for individual sounds.
0x08 int totalHeadersSize Total size of the single sample header + each individual sound header. This is always equal to (72 + 0x36 * numSamples).
0x0C int totalDataSize Total size of all sound data combining all sound entries.
0x10 int version Always 196609.
0x14 int mode Always 2.

After the FSB3 header, there is one sample header.

Sample Header[edit]

This is the header of a FSB3 sample. There is one per FSB3 in the SNDI, immediately after the FSB3 header above.

Offset Type Variable Description
0x00 short size 126 if mono, 172 if stereo
0x02 char[30] soundName Sample name in ASCII. Since each sample actually refers to multiple sounds and this is usually different from the actual sound names, this is likely leftover data and unused.
0x20 int lengthSamples Misleading name; this is actually the amount of samples on the uncompressed data for the first sound only. The first sound in the list will have 0 as its own lengthSamples.
0x24 int lengthCompressedBytes Misleading name; this is actually the length of the compressed sound data in bytes for the first sound only. The first sound in the list will have 0 as its own lengthCompressedBytes.
0x28 int loopStart Start of loop in sample. Only refers to first sound in list. This is probably unused as each sound would require its own loopStart.
0x2C int loopEnd End of loop in sample. Only refers to first sound in list. This is probably unused as each sound would require its own loopEnd.
0x30 int sampleHeaderMode 33558561 if mono, 34078785 if stereo
0x34 int deffreq Always 32000. Does support other frequencies.
0x38 short defvol Always 255
0x3A short defpan 128 if mono, -1 if stereo
0x3C short defpri Always 255
0x3E short numchannels 1 if mono, 2 if stereo
0x40 float minDistance Always 1.0
0x44 float maxDistance Always 1000000.0

Sound Header[edit]

After the sample header, there are sound headers. This header repeats numSamples times (one for each sound). This header is 0x36 bytes long, an unusual length since it's not aligned to 4 bytes.

Offset Type Variable Description
0x00 int lengthSamples Length of uncompressed samples in sound. This is 0 for the first sound in the list, as the value is set in the sample header above, but for each subsequent sound it's the actual value.
0x04 int lengthCompressedBytes Length of bytes in compressed data. This is 0 for the first sound in the list, as the value is set in the sample header above, but for each subsequent sound it's the actual value.
0x08 uint[8] unknown 8 ints with unknown function.
0x28 byte[14] unknown 14 bytes with unknown function.

Adding the lengthCompressedBytes in each Sound Header entry will result in the totalDataSize value of the FSB3 header.

Sound Data[edit]

After numSamples occurrences of the Sound Header, we have the compressed sound data. The total length of this is set in the FSB3 Header (totalDataSize), with each sound in order.

After the sound data for the entire FSB3 file ends, we usually have the next FSB3 file, or if it's the last one, then we've reached the Footer section.

Footer Section[edit]

This is a section which occurs at the end of the file. The offset to this is set in the SNDI header. This is its structure:

Offset Type Variable Description
0x00 int[nFSBFiles] FSB3offsets An array of ints. The amount of ints is the same amount of FSB3 files, as set in the SNDI header. Each int is an offset to the start of each FSB3 file, relative to the end of the header. Add 0x20 to each value to get the absolute offset of the file.

After this, we have nWavFiles times the following structure, which refers to each sound in the SNDI:

gcWavInfo[edit]
Offset Type Variable Description
0x00 AssetID uAssetID Asset ID of sound.
0x04 byte uFlags
0x05 byte uAudioSampleIndex Zero-based index of sound inside its FSB3 file.
0x06 byte uFSBIndex Zero-based index of the FSB3 file containing this sound (index to the FSB3offsets array).
0x07 byte uSoundInfoIndex

Xbox[edit]

The SNDI has a 0xC byte header:

Offset Type Variable Description
0x00 int amount of SND Amount of headers for SND assets.
0x04 int amount of SNDS Amount of headers for SNDS assets.
0x08 int amount of cutscene SNDS Amount of headers for SNDS assets used in cutscenes.

After that, there are three consecutive arrays of SNDI entries: one for the SND, one for the SNDS and one for the cutscene SNDS. Each SNDI entry is 0x2C bytes long and follows this structure:

Offset Type Variable Description
0x00 short fmtId 0x0069 if Xbox ADPCM, 0x0001 if Linear PCM.
0x02 short fmtChannels Number of audio Channels.
0x04 int fmtSampleRate Sampling rate. Xbox ADPCM data plays at this rate multipled by 65/64.
0x08 int fmtBytesPerSecond Used as an estimate for bytes per second. Can be ignored.
0x0C short fmtBlockAlignment Block Size. 0x0024 for Xbox ADPCM data.
0x0E short fmtBitsPerSample Number of bits used per sample. 0x0004 if Xbox ADPCM, 0x0000 if Linear PCM.
0x10 short fmtExtBytes Will always be 0x0002 if Xbox ADPCM. 0x0000 if Linear PCM.
0x12 short fmtExtData ADPCM nibbles per block. Normally 0x0040 if Xbox APCM. 0x0000 if Linear PCM.
0x14 int dataSize Size of the corresponding SND or SNDS asset.
0x18 AssetID Sound Asset ID Asset ID of corresponding SND or SNDS asset.
0x1C byte[16] Padding

Playstation 2[edit]

The SNDI has a 0x8 byte header:

Offset Type Variable Description
0x00 uint num_effects Amount of headers for SND assets.
0x04 uint num_streams Amount of headers for SNDS assets.

After that, there are two consecutive arrays of SNDI entries: one for the SND and one for the SNDS. Each SNDI entry is 0x30 bytes long and is a VAG header. The reserved space at 0x8 in the header contains the sound's Asset ID.

VAGHeader[edit]

Offset Type Variable Description
0x00 char[4] id "VAGp"
0x04 uint version
0x08 uint assetID Asset ID of SND/SNDS
0x0C uint data_size
0x10 uint frequency
0x14 uint streamInterleaveSize
0x18 uint streamInterleaveCount
0x1C uint reserved2
0x20 char[16] name