EvilEngine/Sound Format: Difference between revisions
Battlepedia>Igorseabra4 |
EnergyDrink (talk | contribs) No edit summary |
||
(12 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
This page contains information on how sounds and music are stored in |
This page contains information on how sounds and music are stored in [[EvilEngine]] games. |
||
In [[Scooby-Doo! Night of 100 Frights]] and [[SpongeBob SquarePants: Battle for Bikini Bottom]] sounds are usually contained in '''SND''' and '''SNDS''' [[EvilEngine/Assets|assets]], with the '''SNDI''' asset containing information about them. Each [[EvilEngine/HIP_(File_Format)|HOP]] file (sometimes the [[EvilEngine/HIP_(File_Format)|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. |
|||
In [[The SpongeBob SquarePants Movie]], [[The Incredibles]] and [[The Incredibles: Rise of the Underminer]], '''SND''' and '''SNDS''' assets are empty, and instead, all of the sounds are contained entirely in the '''SNDI''' asset. |
|||
Xbox and the [[FMOD]] GameCube games are the only platform which support '''Stereo'''. PS2 and GameCube (Scooby/BFBB) only support '''Mono''' due to its sound format (VAG and DSP). |
|||
==SND/SNDS Format== |
==SND/SNDS Format== |
||
Line 9: | Line 13: | ||
|subtitle=Sound/Streaming Sound |
|subtitle=Sound/Streaming Sound |
||
|type=[[Binary]] |
|type=[[Binary]] |
||
|games=Scooby BFBB TSSM Incredibles ROTU RatProto}} |
|||
|games=Night of 100 Frights<br>Battle for Bikini Bottom<br>The SpongeBob SquarePants Movie<br>The Incredibles<br>Rise of the Underminer}} |
|||
===GameCube=== |
===GameCube (Night of 100 Frights/Battle for Bikini Bottom)=== |
||
The audio format on the GameCube version of Scooby-Doo and BFBB is a Nintendo DSP-ADPCM audio file stripped of its 0x60 bytes *.dsp header: all of a level's sound headers are kept separate in the single SNDI asset. |
|||
===GameCube (The SpongeBob SquarePants Movie - Ratatouille Prototype)=== |
|||
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. |
|||
Those games on GameCube are the only EvilEngine games which utilize the [[FMOD]] audio engine. This allows stereo support although it still uses the same Nintendo non-stereo codec like Scooby-Doo and BFBB by interleaving two mono tracks. SND/SNDS assets are empty; all sounds are contained entirely in SNDI assets within "FSB3" (FMOD Sample Bank) files. |
|||
===Xbox=== |
===Xbox=== |
||
The audio format on the Xbox version of all 5 games is either |
The audio format on the Xbox version of all 5 games is either Xbox 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=== |
||
The audio format on the PS2 version of all 5 games is a PS2 VAG sound file stripped of its 0x30 |
The audio format on the PS2 version of all 5 games is a PS2 VAG sound file stripped of its 0x30 bytes header (except in Scooby-Doo): all of a level's sound headers are kept separate in the single SNDI asset. The first 0x10 bytes are usually null to initialize the SPU. |
||
== |
==CSSS Format== |
||
{{AssetInfobox |
|||
|title=CSSS |
|||
|subtitle=Cutscene Streaming Sound |
|||
|type=[[Binary]] |
|||
|games=TSSM Incredibles ROTU}} |
|||
Same as SND/SNDS in Movie and The Incredibles: CSSS assets are empty and only used to "link" the sound header in SNDI with the sound data stored in [[EvilEngine/CSN|cutscenes]]. |
|||
==SNDI Format== |
|||
{{AssetInfobox |
{{AssetInfobox |
||
|title=SNDI |
|title=SNDI |
||
|subtitle=Sound Info |
|subtitle=Sound Info |
||
|type=[[Binary]] |
|type=[[Binary]] |
||
|games=Scooby BFBB TSSM Incredibles ROTU RatProto}} |
|||
|games=Night of 100 Frights<br>Battle for Bikini Bottom<br>The SpongeBob SquarePants Movie<br>The Incredibles<br>Rise of the Underminer}} |
|||
===GameCube (Night of 100 Frights/Battle |
===GameCube (Night of 100 Frights/Battle for Bikini Bottom)=== |
||
The SNDI has a 0xC or 0x10 |
The SNDI has a 0xC or 0x10 bytes big-endian header: |
||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || |
| 0x00 || u32 || '''num_effects''' || Amount of headers for SND assets |
||
|- |
|- |
||
| 0x04 || |
| 0x04 || u32 || - || Padding "0xCDCDCDCD" |
||
|- |
|- |
||
| 0x08 || |
| 0x08 || u32 || '''num_streams''' || Amount of headers for SNDS assets |
||
|- |
|- |
||
| 0x0C || |
| 0x0C || u32 || num_cutscenes || Amount of headers used in cutscene assets. '''(BFBB only)''' |
||
|} |
|} |
||
After that, there are three consecutive arrays of SNDI entries: one for the SND, one for the SNDS and one for |
After that, there are three consecutive arrays of SNDI entries: one for the SND, one for the SNDS and one for cutscene headers. Each SNDI entry is 0x64 bytes long, big-endian and follows this structure: |
||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || |
| 0x00 || u32 || '''num_samples''' || Amount of raw samples |
||
|- |
|- |
||
| 0x04 || u32 || '''num_adpcm_nibbles''' || Amount of ADPCM nibbles (including frame headers) |
|||
| 0x60 || [[AssetID]] || Sound Asset ID || Asset ID of corresponding SND or SNDS asset. |
|||
| |
|- |
||
| 0x08 || u32 || '''sample_rate''' || Sample rate in Hz |
|||
|- |
|||
| 0x0C || u16 || '''loop_flag''' || 0 = Not Looped, 1 = Looped |
|||
|- |
|||
| 0x0E || u16 || '''format''' || Always 0 |
|||
|- |
|||
| 0x10 || u32 || '''sa''' || Loop start offset, in nibbles |
|||
|- |
|||
| 0x14 || u32 || '''ea''' || Loop end offset, in nibbles |
|||
|- |
|||
| 0x18 || u32 || '''ca''' || Initial offset value, always 2 |
|||
|- |
|||
| 0x1C || s16[16] || '''coef''' || Decoder coefficients |
|||
|- |
|||
| 0x3C || u16 || '''gain''' || Gain factor. Always 0 |
|||
|- |
|||
| 0x3E || u16 || '''pred_scale''' || Predictor and scale. This will be initialized to the predictor and scale value of the sample’s first frame. |
|||
|- |
|||
| 0x40 || u16 || '''yn1''' || rowspan="2" | History data; used to maintain decoder state during sample playback |
|||
|- |
|||
| 0x42 || u16 || '''yn2''' |
|||
|- |
|||
| 0x44 || u16 || '''loop_pred_scale''' || Predictor/scale for the loop point frame. If the sample does not loop, this value is zero |
|||
|- |
|||
| 0x46 || u16 || '''loop_yn1''' || rowspan="2" | History data for the loop point. If the sample does not loop, this value is zero. |
|||
|- |
|||
| 0x48 || u16 || '''loop_yn2''' |
|||
|- |
|||
| 0x4A || u8[22] || '''pad''' || Unknown values |
|||
|- |
|||
! colspan="4" | |
|||
|- |
|||
| 0x60 || [[AssetID]] || '''uAssetID''' || Asset ID of corresponding SND/SNDS asset |
|||
|} |
|||
===GameCube (The SpongeBob SquarePants Movie - Ratatouille Prototype)=== |
|||
In those games, the SNDI contains not only the sound headers but also the entirety of the sound data themselves. |
|||
====SNDI Header==== |
|||
===GameCube (Movie Game/Incredibles/Rise of the Underminer)=== |
|||
The SNDI itself has a 0x20 byte big-endian header: |
|||
In those games, the SNDI contains not only the sound headers but also the entirety of the sound files themselves. It has a 0x20 byte header: |
|||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || [[AssetID]] || |
| 0x00 || [[AssetID]] || '''uSoundInfoID''' || Asset ID of this asset |
||
|- |
|- |
||
| 0x04 || |
| 0x04 || u32 || '''uSumFSBSize / nOffsetFinalFSBEnd''' || Total size of all FSB3 files, also offset to the Footer section (relative to end of this header, add 0x20 to get the absolute offset). |
||
|- |
|- |
||
| 0x08 || |
| 0x08 || s32 || '''pFMusicMod''' || ''null'' |
||
|- |
|- |
||
| |
| 0x0C || s32 || '''pFSBFileArray''' || ''null'' |
||
|- |
|- |
||
| 0x10 || s32 || '''pWavInfoArray''' || ''null'' |
|||
| 0x1A || short || ? || Amound of sounds in SNDI - amount of unknown ints at last section (value at 0x18 - value at 0x1C) |
|||
|- |
|- |
||
| 0x14 || s32 || '''pCutsceneAudioHeaders''' || ''null'' |
|||
| 0x1C || short || ? || Amount of unknown ints at last section |
|||
|- |
|- |
||
| |
| 0x18 || u16 || '''nWavFiles''' || Total amount of sounds |
||
|- |
|||
| 0x1A || u16 || '''nSounds''' || Amount of sounds in the first FSB3 of the SNDI |
|||
|- |
|||
| 0x1C || u16 || '''nStreams''' || Amount of sounds combining all FSB3's which are not the first of the SNDI |
|||
|- |
|||
| 0x1E || u8 || '''nFSBFiles''' || Amount of FSB3 files |
|||
|- |
|||
| 0x1F || u8 || '''nCutsceneAudioHeaders''' || Amount of cutscene headers |
|||
|} |
|} |
||
=== |
====FSB3 Format==== |
||
All sounds are contained inside FSB3 files. The first FSB3 is loaded into RAM, thus it has a ~8MB size limit, but can contain multiple sounds. Every subsequent FSB3 is streamed, thus it has no size limit but can only contain 1 sound. Read [[FMOD]] for more information about FMOD and the FSB3 format. <u>'''Note:'''</u> SNDI header and the Footer section are stored in big-endian while FSB's are little-endian. |
|||
The SNDI has a 0xC byte header: |
|||
====Footer Section==== |
|||
This is a section which occurs at the end of the SNDI. The offset to this is set in the SNDI header. This is its structure: |
|||
=====FSB3 Offsets===== |
|||
{| class="wikitable" |
|||
! Offset !! Size !! Description |
|||
|- |
|||
| 0x00 || 4[[#SNDI Header|'''[nFSBFiles]''']] || '''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 SNDI header. Add 0x20 to each value to get the absolute offset. |
|||
|} |
|||
After this, we have [[#SNDI Header|'''nWavFiles''']] times the following structure, which refers to each sound in the SNDI: |
|||
=====gcWavInfo===== |
|||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || |
| 0x00 || [[AssetID]] || '''uAssetID''' || Asset ID of sound. |
||
|- |
|||
| 0x04 || u8 || '''uFlags''' || Loop and format flag. |
|||
* 0 = RAM sound (first FSB) |
|||
* 1 = Looped |
|||
* 2 = Streaming sound (subsequent FSB) |
|||
|- |
|||
| 0x05 || u8 || '''uAudioSampleIndex''' || Zero-based index of sound inside its FSB3 file |
|||
|- |
|- |
||
| 0x06 || u8 || '''uFSBIndex''' || Zero-based index of the FSB3 file containing this sound (index to the FSB3 offsets array) |
|||
| 0x04 || int || amount of SNDS || Amound of headers for SNDS assets. |
|||
|- |
|- |
||
| 0x07 || u8 || '''uSoundInfoIndex''' || |
|||
| 0x08 || int || amount of cutscene SNDS || Amound of headers for SNDS assets used in cutscenes. |
|||
|} |
|} |
||
=====Cutscene Header===== |
|||
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: |
|||
At the end of the SNDI are the cutscene header. They are a 0x60 bytes dsp header + asset id of corresponding CSSS asset (same format as header in Scooby/BFBB). |
|||
===Xbox=== |
|||
Stored in little-endian. The SNDI has a 0xC byte header: |
|||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || |
| 0x00 || u32 || '''num_effects''' || Amount of headers for SND assets |
||
|- |
|- |
||
| |
| 0x04 || u32 || '''num_streams''' || Amount of headers for SNDS assets |
||
|- |
|- |
||
| 0x08 || u32 || num_cutscenes || Amount of headers used in cutscenes assets |
|||
| 0x04 || int || fmtSampleRate || Sampling rate. Xbox ADPCM data plays at this rate multipled by 65/64. |
|||
|} |
|||
After that, there are three consecutive arrays of entries: one for the SND, one for the SNDS and one for cutscene headers. Each entry is 0x2C bytes long and follows this structure: |
|||
{| class="wikitable" |
|||
! Offset !! Type !! Variable !! Description |
|||
|- |
|- |
||
| |
| 0x00 || u16 || '''wFormatTag''' || 1 if PCM, 0x69 (105) if Xbox ADPCM |
||
|- |
|- |
||
| 0x02 || u16 || '''nChannels''' || Number of audio Channels. Always 1 (Mono), but support for 2 (Stereo) |
|||
| 0x0C || short || fmtBlockAlignment || Block Size. 0x0024 for Xbox ADPCM data. |
|||
|- |
|- |
||
| 0x04 || u32 || '''nSamplesPerSec''' || Sampling rate in Hz |
|||
| 0x0E || short || fmtBitsPerSample || Number of bits used per sample. 0x0004 if Xbox ADPCM, 0x0000 if Linear PCM. |
|||
|- |
|- |
||
| |
| 0x08 || u32 || '''nAvgBytesPerSec''' || Used as an estimate for bytes per second. Can be ignored |
||
|- |
|- |
||
| |
| 0x0C || u16 || '''nBlockAlign''' || Block size in bytes. 2 if PCM, 36 (0x24) if Xbox ADPCM |
||
|- |
|- |
||
| 0x0E || u16 || '''wBitsPerSample''' || Number of bits used per sample. 16 (0x10) if PCM, 4 if Xbox ADPCM |
|||
| 0x14 || int || dataSize || Size of the corresponding SND or SNDS asset. |
|||
|- |
|- |
||
| 0x10 || u16 || '''cbSize''' || Amount of extra bytes. Always 0 if PCM, 2 if Xbox ADPCM (NibblesPerBlock) |
|||
| 0x18 || [[AssetID]] || Sound Asset ID || Asset ID of corresponding SND or SNDS asset. |
|||
|- |
|- |
||
| 0x12 || u16 || NibblesPerBlock || ADPCM nibbles per block. 64 (0x40) if Xbox ADPCM, 0 if PCM |
|||
| 0x1C || byte[16] || Padding || |
|||
|- |
|||
| 0x14 || u32 || Datasize || Size of corresponding sound data. |
|||
|- |
|||
| 0x18 || [[AssetID]] || Sound Asset ID || Asset ID of corresponding SND or SNDS asset |
|||
|- |
|||
| 0x1C || u32 || flag/loop || 0 = Not Looped, 1 = Looped, 2 = Unknown |
|||
|- |
|||
| 0x20 || u8[12] || Padding || ''null'' |
|||
|} |
|} |
||
More information about [https://xboxdevwiki.net/Xbox_ADPCM Xbox ADPCM]. |
|||
===PlayStation 2=== |
|||
The SNDI has a 0x8 or 0xC bytes little-endian header: |
|||
{| class="wikitable" |
|||
===Playstation 2=== |
|||
! Offset !! Type !! Variable !! Description |
|||
The SNDI has a 0x8 byte header: |
|||
|- |
|||
| 0x00 || [[AssetID]] || assetID || AssetID of SNDI '''(Only present in Incredibles and ROTU)''' |
|||
|- |
|||
| 0x04/0x00 || uint || '''num_effects''' || Amount of headers for SND assets |
|||
|- |
|||
| 0x08/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 Sony VAG header. |
|||
====Scooby-Doo: Night of 100 Frights==== |
|||
Stored in big-endian, except '''reserved''' and probably also '''reserved2''' which are in little-endian. |
|||
{| class="wikitable" |
{| class="wikitable" |
||
! Offset !! Type !! Variable !! Description |
! Offset !! Type !! Variable !! Description |
||
|- |
|- |
||
| 0x00 || |
| 0x00 || char[4] || '''id''' || "VAGp" |
||
|- |
|||
| 0x04 || u32 || '''version''' || Always 3, 4 or 32 |
|||
|- |
|||
| 0x08 || u32 || '''reserved''' || Asset ID of corresponding SND/SNDS |
|||
|- |
|||
| 0x0C || u32 || '''data_size''' || Size of corresponding SND/SNDS asset |
|||
|- |
|||
| 0x10 || u32 || '''frequency''' || Sampling rate in Hz |
|||
|- |
|||
| 0x14 || u32[3] || '''reserved2''' || |
|||
* u32[1]: ''null'' |
|||
* u32[2]: ''null'' or 0xE4AC0000 |
|||
* u32[3]: ''null'' |
|||
|- |
|||
| 0x20 || char[16] || '''name''' || Old filename, can be ignored |
|||
|} |
|||
There are two 0x30 bytes "RIFF" header with a different format, one in I001.HIP and in S005.HIP. However, they don't seem to work ingame. |
|||
====Battle for Bikini Bottom - Rise of the Underminer==== |
|||
Stored in little-endian. |
|||
{| class="wikitable" |
|||
! Offset !! Type !! Variable !! Description |
|||
|- |
|||
| 0x00 || char[4] || '''id''' || "VAGp" |
|||
|- |
|||
| 0x04 || u32 || '''version''' || 4 or 32 in BFBB, always 32 in every other game |
|||
|- |
|||
| 0x08 || u32 || '''assetID''' || Asset ID of corresponding SND/SNDS |
|||
|- |
|||
| 0x0C || u32 || '''data_size''' || Size of corresponding SND/SNDS asset |
|||
|- |
|||
| 0x10 || u32 || '''frequency''' || Sampling rate in Hz |
|||
|- |
|||
| 0x14 || u32 || '''streamInterleaveSize''' || |
|||
|- |
|||
| 0x18 || u32 || '''streamInterleaveCount''' || |
|||
|- |
|||
| 0x1C || u32 || '''reserved2''' || |
|||
|- |
|- |
||
| |
| 0x20 || char[16] || '''name''' || Old filename, can be ignored |
||
|} |
|} |
||
{{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 [http://www.psdevwiki.com/ps3/Multimedia_Formats_and_Tools#VAG VAG header]. The reserved space at 0x8 in the header contains the sound's [[Asset ID]]. |
|||
[[Category:Asset]] [[Category:File Format]][[Category: |
[[Category:Asset]] [[Category:File Format]] [[Category:EvilEngine]] |
Latest revision as of 01:54, 20 January 2023
This page contains information on how sounds and music are stored in EvilEngine games.
In Scooby-Doo! Night of 100 Frights and SpongeBob SquarePants: Battle for Bikini Bottom 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.
In The SpongeBob SquarePants Movie, The Incredibles and The Incredibles: Rise of the Underminer, SND and SNDS assets are empty, and instead, all of the sounds are contained entirely in the SNDI asset.
Xbox and the FMOD GameCube games are the only platform which support Stereo. PS2 and GameCube (Scooby/BFBB) only support Mono due to its sound format (VAG and DSP).
SND/SNDS Format
SND/SNDS | |
---|---|
Sound/Streaming Sound | |
Type | Binary |
Games used | Night of 100 Frights Battle for Bikini Bottom |
GameCube (Night of 100 Frights/Battle for Bikini Bottom)
The audio format on the GameCube version of Scooby-Doo and BFBB is a Nintendo DSP-ADPCM audio file stripped of its 0x60 bytes *.dsp header: all of a level's sound headers are kept separate in the single SNDI asset.
GameCube (The SpongeBob SquarePants Movie - Ratatouille Prototype)
Those games on GameCube are the only EvilEngine games which utilize the FMOD audio engine. This allows stereo support although it still uses the same Nintendo non-stereo codec like Scooby-Doo and BFBB by interleaving two mono tracks. SND/SNDS assets are empty; all sounds are contained entirely in SNDI assets within "FSB3" (FMOD Sample Bank) files.
Xbox
The audio format on the Xbox version of all 5 games is either Xbox 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
The audio format on the PS2 version of all 5 games is a PS2 VAG sound file stripped of its 0x30 bytes header (except in Scooby-Doo): all of a level's sound headers are kept separate in the single SNDI asset. The first 0x10 bytes are usually null to initialize the SPU.
CSSS Format
CSSS | |
---|---|
Cutscene Streaming Sound | |
Type | Binary |
Games used | The SpongeBob SquarePants Movie Rise of the Underminer |
Same as SND/SNDS in Movie and The Incredibles: CSSS assets are empty and only used to "link" the sound header in SNDI with the sound data stored in cutscenes.
SNDI Format
SNDI | |
---|---|
Sound Info | |
Type | Binary |
Games used | Night of 100 Frights Battle for Bikini Bottom |
GameCube (Night of 100 Frights/Battle for Bikini Bottom)
The SNDI has a 0xC or 0x10 bytes big-endian header:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | u32 | num_effects | Amount of headers for SND assets |
0x04 | u32 | - | Padding "0xCDCDCDCD" |
0x08 | u32 | num_streams | Amount of headers for SNDS assets |
0x0C | u32 | num_cutscenes | Amount of headers used in cutscene assets. (BFBB only) |
After that, there are three consecutive arrays of SNDI entries: one for the SND, one for the SNDS and one for cutscene headers. Each SNDI entry is 0x64 bytes long, big-endian and follows this structure:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | u32 | num_samples | Amount of raw samples |
0x04 | u32 | num_adpcm_nibbles | Amount of ADPCM nibbles (including frame headers) |
0x08 | u32 | sample_rate | Sample rate in Hz |
0x0C | u16 | loop_flag | 0 = Not Looped, 1 = Looped |
0x0E | u16 | format | Always 0 |
0x10 | u32 | sa | Loop start offset, in nibbles |
0x14 | u32 | ea | Loop end offset, in nibbles |
0x18 | u32 | ca | Initial offset value, always 2 |
0x1C | s16[16] | coef | Decoder coefficients |
0x3C | u16 | gain | Gain factor. Always 0 |
0x3E | u16 | pred_scale | Predictor and scale. This will be initialized to the predictor and scale value of the sample’s first frame. |
0x40 | u16 | yn1 | History data; used to maintain decoder state during sample playback |
0x42 | u16 | yn2 | |
0x44 | u16 | loop_pred_scale | Predictor/scale for the loop point frame. If the sample does not loop, this value is zero |
0x46 | u16 | loop_yn1 | History data for the loop point. If the sample does not loop, this value is zero. |
0x48 | u16 | loop_yn2 | |
0x4A | u8[22] | pad | Unknown values |
0x60 | AssetID | uAssetID | Asset ID of corresponding SND/SNDS asset |
GameCube (The SpongeBob SquarePants Movie - Ratatouille Prototype)
In those games, the SNDI contains not only the sound headers but also the entirety of the sound data themselves.
SNDI Header
The SNDI itself has a 0x20 byte big-endian header:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | AssetID | uSoundInfoID | Asset ID of this asset |
0x04 | u32 | uSumFSBSize / nOffsetFinalFSBEnd | Total size of all FSB3 files, also offset to the Footer section (relative to end of this header, add 0x20 to get the absolute offset). |
0x08 | s32 | pFMusicMod | null |
0x0C | s32 | pFSBFileArray | null |
0x10 | s32 | pWavInfoArray | null |
0x14 | s32 | pCutsceneAudioHeaders | null |
0x18 | u16 | nWavFiles | Total amount of sounds |
0x1A | u16 | nSounds | Amount of sounds in the first FSB3 of the SNDI |
0x1C | u16 | nStreams | Amount of sounds combining all FSB3's which are not the first of the SNDI |
0x1E | u8 | nFSBFiles | Amount of FSB3 files |
0x1F | u8 | nCutsceneAudioHeaders | Amount of cutscene headers |
FSB3 Format
All sounds are contained inside FSB3 files. The first FSB3 is loaded into RAM, thus it has a ~8MB size limit, but can contain multiple sounds. Every subsequent FSB3 is streamed, thus it has no size limit but can only contain 1 sound. Read FMOD for more information about FMOD and the FSB3 format. Note: SNDI header and the Footer section are stored in big-endian while FSB's are little-endian.
This is a section which occurs at the end of the SNDI. The offset to this is set in the SNDI header. This is its structure:
FSB3 Offsets
Offset | Size | Description |
---|---|---|
0x00 | 4[nFSBFiles] | 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 SNDI header. Add 0x20 to each value to get the absolute offset. |
After this, we have nWavFiles times the following structure, which refers to each sound in the SNDI:
gcWavInfo
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | AssetID | uAssetID | Asset ID of sound. |
0x04 | u8 | uFlags | Loop and format flag.
|
0x05 | u8 | uAudioSampleIndex | Zero-based index of sound inside its FSB3 file |
0x06 | u8 | uFSBIndex | Zero-based index of the FSB3 file containing this sound (index to the FSB3 offsets array) |
0x07 | u8 | uSoundInfoIndex |
Cutscene Header
At the end of the SNDI are the cutscene header. They are a 0x60 bytes dsp header + asset id of corresponding CSSS asset (same format as header in Scooby/BFBB).
Xbox
Stored in little-endian. The SNDI has a 0xC byte header:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | u32 | num_effects | Amount of headers for SND assets |
0x04 | u32 | num_streams | Amount of headers for SNDS assets |
0x08 | u32 | num_cutscenes | Amount of headers used in cutscenes assets |
After that, there are three consecutive arrays of entries: one for the SND, one for the SNDS and one for cutscene headers. Each entry is 0x2C bytes long and follows this structure:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | u16 | wFormatTag | 1 if PCM, 0x69 (105) if Xbox ADPCM |
0x02 | u16 | nChannels | Number of audio Channels. Always 1 (Mono), but support for 2 (Stereo) |
0x04 | u32 | nSamplesPerSec | Sampling rate in Hz |
0x08 | u32 | nAvgBytesPerSec | Used as an estimate for bytes per second. Can be ignored |
0x0C | u16 | nBlockAlign | Block size in bytes. 2 if PCM, 36 (0x24) if Xbox ADPCM |
0x0E | u16 | wBitsPerSample | Number of bits used per sample. 16 (0x10) if PCM, 4 if Xbox ADPCM |
0x10 | u16 | cbSize | Amount of extra bytes. Always 0 if PCM, 2 if Xbox ADPCM (NibblesPerBlock) |
0x12 | u16 | NibblesPerBlock | ADPCM nibbles per block. 64 (0x40) if Xbox ADPCM, 0 if PCM |
0x14 | u32 | Datasize | Size of corresponding sound data. |
0x18 | AssetID | Sound Asset ID | Asset ID of corresponding SND or SNDS asset |
0x1C | u32 | flag/loop | 0 = Not Looped, 1 = Looped, 2 = Unknown |
0x20 | u8[12] | Padding | null |
More information about Xbox ADPCM.
PlayStation 2
The SNDI has a 0x8 or 0xC bytes little-endian header:
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | AssetID | assetID | AssetID of SNDI (Only present in Incredibles and ROTU) |
0x04/0x00 | uint | num_effects | Amount of headers for SND assets |
0x08/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 Sony VAG header.
Scooby-Doo: Night of 100 Frights
Stored in big-endian, except reserved and probably also reserved2 which are in little-endian.
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | char[4] | id | "VAGp" |
0x04 | u32 | version | Always 3, 4 or 32 |
0x08 | u32 | reserved | Asset ID of corresponding SND/SNDS |
0x0C | u32 | data_size | Size of corresponding SND/SNDS asset |
0x10 | u32 | frequency | Sampling rate in Hz |
0x14 | u32[3] | reserved2 |
|
0x20 | char[16] | name | Old filename, can be ignored |
There are two 0x30 bytes "RIFF" header with a different format, one in I001.HIP and in S005.HIP. However, they don't seem to work ingame.
Battle for Bikini Bottom - Rise of the Underminer
Stored in little-endian.
Offset | Type | Variable | Description |
---|---|---|---|
0x00 | char[4] | id | "VAGp" |
0x04 | u32 | version | 4 or 32 in BFBB, always 32 in every other game |
0x08 | u32 | assetID | Asset ID of corresponding SND/SNDS |
0x0C | u32 | data_size | Size of corresponding SND/SNDS asset |
0x10 | u32 | frequency | Sampling rate in Hz |
0x14 | u32 | streamInterleaveSize | |
0x18 | u32 | streamInterleaveCount | |
0x1C | u32 | reserved2 | |
0x20 | char[16] | name | Old filename, can be ignored |