SABS & SABL Files: Difference between revisions

From COD Engine Research
Red-EyeX32 (talk | contribs)
Red-EyeX32 (talk | contribs)
 
(15 intermediate revisions by 2 users not shown)
Line 3: Line 3:
SAB(Stream) and SAB(Load). The B is most likely "bank" as the game code refers to a "sound bank" when loading SABL/SABS files.  
SAB(Stream) and SAB(Load). The B is most likely "bank" as the game code refers to a "sound bank" when loading SABL/SABS files.  


* SABS = Snd Alias Bank Stream
* SABS = Snd Asset Bank Stream
* SABL = Snd Alias Bank Load
* SABL = Snd Asset Bank Load
== Structure ==
== Structure ==
Thanks to Jakes625, Red-EyeX32, master131, and kokole.
<source lang="cpp">
<source lang="cpp">
struct hash_entry_t
enum snd_asset_channel_mode
{
{
u8 md5[0x10];                  // md5 of the audio file
  SND_ASSET_CHANNEL_MODE_MONO = 0x1,
}; // 0x10
  SND_ASSET_CHANNEL_MODE_DUAL = 0x2,
  // Could be more modes ex: ("Joint Stereo" and "Stereo")
};
 
enum snd_asset_format
{
  SND_ASSET_FORMAT_PCMS16 = 0x0,
  SND_ASSET_FORMAT_PCMS24 = 0x1,
  SND_ASSET_FORMAT_PCMS32 = 0x2,
  SND_ASSET_FORMAT_IEEE = 0x3,
  SND_ASSET_FORMAT_XMA4 = 0x4,
  SND_ASSET_FORMAT_MP3 = 0x5,
  SND_ASSET_FORMAT_MSADPCM = 0x6,
  SND_ASSET_FORMAT_WMA = 0x7,
  SND_ASSET_FORMAT_FLAC = 0x8,
  SND_ASSET_FORMAT_WIIUADPCM = 0x9,
  SND_ASSET_FORMAT_MPC = 0xA,
  SND_ASSET_FORMAT_COUNT = 0xB,
};


struct audio_entry_t
struct SndAssetBankEntry
{
{
u32 name; // this is a hash of the name. Name Found in snd_alias_t asset in ff
unsigned int id;             // this is a hash of the name. Name Found in SndBank asset in ff
         u32 size;
         unsigned int size;
u32 offset;
unsigned int offset;
u32 unk1; // not hash but idk what is it. if *(_DWORD *)(v5 + 12) > 0 (seen in the game)
unsigned int frameCount;  
u8 type; // always 0x6
char frameRateIndex;             // see frame_rate_table
u8 channelCount; // enum 0x1 = mono 0x2 = dual
snd_asset_channel_mode channelCount; // enum 0x1 = mono 0x2 = dual
u8 unk2; // no idea
char looping;
u8 format; // enum 0x0 = headerless wav, 0x5 = mp3, 0x8 = flac, 0x4 = xbox sound ??
snd_asset_format format;
}; // 0x14
}; // 0x14


struct header_t
struct SndAssetBankEntryHash
{
{
u32 magic;         // "2UX#"
char hash[16]; // md5 of the audio file
u32 version;         // 0x0E
}; // 0x10
u32 sizeOfAudioEntry;          // 0x14
u32 sizeOfHashEntry;            // 0x10
u32 sizeOfStringEntry;          // 0x40
u32 entryCount; // number of sound entries NOT NAME ENTRIES
u64 unk1; // always 0x8 for some reason, might be the size of the next 3 fields
u64 fileLength; // Size of the whole file
u64 entries; // &audio_entry_t[0]
u64 hashes; // &hash_entry_t[0]
}; // 0x38


struct sabs_file
struct SndAssetBankHeader
{
{
header_t header;
unsigned int magic;       // "2UX#"
u8 asset_link_id[0x10];         // 16 bytes which are associated between sabs + 0x38 and soundasset + 0x830 (can be > 0x830)
unsigned int version;        // 0x0E
u8 nameEntries[30][64];
unsigned int entrySize;      // 0x14
u8 padding[0x38];
unsigned int checksumSize;    // 0x10
unsigned int dependencySize;  // 0x40
unsigned int entryCount;      // Amount of sound entries NOT NAME ENTRIES
unsigned int dependencyCount; // Always 0x8 for some reason, might be the size of the next 3 fields
unsigned int pad32;
__int64 fileSize;       // Size of the whole file
__int64 entryOffset;       // &SndAssetBankEntry[0]
__int64 checksumOffset;      // &SndAssetBankEntryHash[0]
char checksumChecksum[16];   // 16 bytes which are associated between sabs + 0x38 and soundasset + 0x830 (can be > 0x830)
char dependencies[512];
        char padding[1464];
}; // 0x800
}; // 0x800
</source>
To calculate the duration of an audio entry:
<source lang="cpp">
unsigned int SND_AssetBankGetFrameRate(SndAssetBankEntry *entry) {
        int frameRate;
        if (!entry)
            break;
       
        switch (entry->frameRateIndex) {
                case 0: frameRate = 8000; break;
                case 1: frameRate = 12000; break;
                case 2: frameRate = 16000; break;
                case 3: frameRate = 24000; break;
                case 4: frameRate = 32000; break;
                case 5: frameRate = 44100; break;
                case 6: frameRate = 48000; break;
                case 7: frameRate = 96000; break;
                case 8: frameRate = 192000; break;
                default:
                  frameRate = 0;
                  break;
        }
        return frameRate;
}
 
unsigned int SND_AssetBankGetLengthMs(SndAssetBankEntry *entry) {
        if (!entry)
            break;
       
        return 1000 * entry->frameCount / SND_AssetBankGetFrameRate(entry);
}
</source>
</source>

Latest revision as of 18:56, 5 July 2015

SAB(Stream) and SAB(Load). The B is most likely "bank" as the game code refers to a "sound bank" when loading SABL/SABS files.

  • SABS = Snd Asset Bank Stream
  • SABL = Snd Asset Bank Load

Structure

enum snd_asset_channel_mode
{
  SND_ASSET_CHANNEL_MODE_MONO = 0x1,
  SND_ASSET_CHANNEL_MODE_DUAL = 0x2,
  // Could be more modes ex: ("Joint Stereo" and "Stereo")
};

enum snd_asset_format
{
  SND_ASSET_FORMAT_PCMS16 = 0x0,
  SND_ASSET_FORMAT_PCMS24 = 0x1,
  SND_ASSET_FORMAT_PCMS32 = 0x2,
  SND_ASSET_FORMAT_IEEE = 0x3,
  SND_ASSET_FORMAT_XMA4 = 0x4,
  SND_ASSET_FORMAT_MP3 = 0x5,
  SND_ASSET_FORMAT_MSADPCM = 0x6,
  SND_ASSET_FORMAT_WMA = 0x7,
  SND_ASSET_FORMAT_FLAC = 0x8,
  SND_ASSET_FORMAT_WIIUADPCM = 0x9,
  SND_ASSET_FORMAT_MPC = 0xA,
  SND_ASSET_FORMAT_COUNT = 0xB,
};

struct SndAssetBankEntry
{
	unsigned int id; 	             // this is a hash of the name. Name Found in SndBank asset in ff
        unsigned int size;
	unsigned int offset;
	unsigned int frameCount; 
	char frameRateIndex; 	             // see frame_rate_table
	snd_asset_channel_mode channelCount; // enum 0x1 = mono 0x2 = dual
	char looping;
	snd_asset_format format;
}; // 0x14

struct SndAssetBankEntryHash
{
	char hash[16]; // md5 of the audio file
}; // 0x10

struct SndAssetBankHeader
{
	unsigned int magic; 	      // "2UX#"
	unsigned int version;         // 0x0E
	unsigned int entrySize;       // 0x14
	unsigned int checksumSize;    // 0x10
	unsigned int dependencySize;  // 0x40
	unsigned int entryCount;      // Amount of sound entries NOT NAME ENTRIES
	unsigned int dependencyCount; // Always 0x8 for some reason, might be the size of the next 3 fields
	unsigned int pad32;
	__int64 fileSize; 	      // Size of the whole file
	__int64 entryOffset; 	      // &SndAssetBankEntry[0]
	__int64 checksumOffset;       // &SndAssetBankEntryHash[0]
	char checksumChecksum[16];    // 16 bytes which are associated between sabs + 0x38 and soundasset + 0x830 (can be > 0x830)
	char dependencies[512];
        char padding[1464];
}; // 0x800

To calculate the duration of an audio entry:

unsigned int SND_AssetBankGetFrameRate(SndAssetBankEntry *entry) {
        int frameRate;

        if (!entry)
            break;
        
        switch (entry->frameRateIndex) {
                case 0: frameRate = 8000; break;
                case 1: frameRate = 12000; break;
                case 2: frameRate = 16000; break;
                case 3: frameRate = 24000; break;
                case 4: frameRate = 32000; break;
                case 5: frameRate = 44100; break;
                case 6: frameRate = 48000; break;
                case 7: frameRate = 96000; break;
                case 8: frameRate = 192000; break;
                default:
                  frameRate = 0;
                  break;
        }
        return frameRate;
}
  
unsigned int SND_AssetBankGetLengthMs(SndAssetBankEntry *entry) {
        if (!entry)
            break;
        
        return 1000 * entry->frameCount / SND_AssetBankGetFrameRate(entry);
}