SND File - Documentation (PS2)
May 16, 2023 1:21:18 GMT 10
Sr. Belt, JADERLINK, and 1 more like this
Post by HardRain on May 16, 2023 1:21:18 GMT 10
Documentation about .SND file
RESIDENT EVIL 4 2005 - PS2
(15, may 2023)
(15, may 2023)
SND file is a container for audio groups of .vag extension, used mainly on PS1 and PS2 for space efficiency. Here I will try to dissect through each section in detail, although I'm not too much experienced with audio handling.
The Header
SND files always have this unique magic file identifier composed of 0x20 bytes:
--------------------------
0x24 uint32: Metadata length
0x2C uint32: Metadata offset
0x44 uint32: Audio parameters section length
0x4C uint32: Audio parameters section offset
0x64 uint32: Vag chunk length
0x6C uint32: Vag chunk offset
The header lists descriptions of audio groups, and it can contain multiple groups, each one with 0x60 length (marked with outlined green rectangle).
Each group has offsets that point to where data starts, the length of each data chunk, three file identifiers and some more unknown values.
*Each data chunk has its own local scope, which means it will read starting from offset 00
Room audios rXXX.snd always have 2 audio groups, and any other .snd uses just 1 group.
0x34 uint32: File identifier
0x54 uint32: File identifier
0x74 uint32: File identifier
File identifiers change based on target’s id, examples:
00 01 00 00 = r100
13 02 00 00 = r213
1D 00 00 00 = em1D
0E 00 00 00 = pl0E
*Obs: on files like em12.snd, the identifier is 10 because em10.snd contains every audio for every ganado, just like em20.snd is 1D because em1D.snd is the full parent. This may need more research.
0x400 byte array: unknown metadata
This is the first part of the audio group, I have no clue what it does, possibly volume? pitch? anyway, I just call it metadata, and if you’re not planning to recreate .snd from scratch, you don’t need to mess with this section.
Note: from here onwards, the offsets will not be the same for every .snd, you need to be based on the offsets listed in the audio group. And I will use pl0e.snd for better examples on the next sections.
The second data chunk of the audio group is split into four sections: Head, Prog, Smpl and Vagi.
Let’s dissect through each one of them.
Head
0x00 uint32: magic identifier for Head, which is the header for subsequent vag sections
0x04 uint32: block length
0x08 uint32: unknown, maybe count
0x0C uint32: offset to where audios chunk starts
-
0x10 uint32: offset to where audio group 2 starts (in case of only 1 group exists, it points to the end of the file)
0x14 uint32: offset to where Prog section starts
0x18 uint32: offset to where Smpl section starts
0x1C uint32: offset to where Vagi section starts
Prog
0x20 uint32: magic identifier for Prog, which should stand for Progressive/Progression?
0x24 uint32: block length
Unfortunately I have no previous experience on audio structure, this is my first attempt on reverse engineering an audio format.
So I’m not sure what this does, but we can easily identify increasing numbers in a progressive way, maybe this could be related to fade in & fade out?
Any help on this will be much appreciated.
Smpl
0x90 uint32: magic identifier for Smpl, which stands for Sample
0x94 uint32: block length
0x98 uint32: sample count
0x9C uint32: padding
-
0xA0 uint32: unknown
0xA4 uint32: unknown, but the second byte increases by +1 at each sample
0xAA uint16: index
I also have no knowledge on sampling, but every sample here is made of 0x0C bytes. These values may even not be uint32, but uint16. If we’re not going to add or remove audios, we can leave this section alone.
But it seems to be important to have it documented.
Vagi
0xF0 uint32: magic identifier for Vagi, which stands for Vag info
0xF4 uint32: block length
0xF8 uint32: .vag audio count
0xFC uint32: padding
-
0x100 uint32: offset where audio starts
0x104 uint32: audio length (bytes)
0x108 uint32: loop flag (01 = on, 00 = off)
0x10C uint32: audio frequency
These are the most relevant audio specifications, if we’re going to import a smaller/bigger audio or if it has a different frequency, we must update them correctly here.
After this section, is where the .vag audio data starts.
*Obs: the audio offsets use local scope, which means they reset to offset 00 after this Vagi data chunk ends.
Vag audio
A vag audio is ADPCM, which uses a lossy compression algorithm to reduce its size (significant for PS2 era).
Inside the .SND, the .vag specifications are set in the Vagi chunk, and it is followed by the audio data itself, .vag version 3 is used here.
The second byte of each row is a play flag, examples:
0x00 = play next row
0x01 = stop playing
0x02 = play next row
0x03 = restart the audio (loop)
Extra tips:
You can use MFAudio to convert .wav to .vag;
Naturally .vag audios use Big Endian header, but on the .SND it is converted to Little Endian to be used on the Vagi chunk.
More info about the header over here.