User:Kraken/Sandbox
FSB4 Format
FSB4 (FMOD Sound Bank version 4) is a proprietary audio container format developed by Firelight Technologies for use in games and interactive media. It is the native audio format used by the FMOD sound engine and is notably employed in LittleBigPlanet series for music playback.
Overview
FSB4 packages compressed audio samples (typically MP3) into a single bank file that can be loaded and played back by the FMOD engine. The format supports:
- Multiple audio samples per bank
- Loop points for seamless playback
- Startpoint markers for music synchronization
- 3D audio positioning parameters
- Sample-accurate seeking
File Layout
Offset Section ────────────────────────────── 0x000 Header (48 bytes) 0x030 Directory entries (variable, 32-byte aligned) +dat_len Audio data (MPEG frames, padded)
All multi-byte values are little-endian.
Header (48 bytes)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0x00 | 4 | magic | "FSB4" (0x34425346)
|
| 0x04 | 4 | num_files | Number of audio samples in this bank |
| 0x08 | 4 | dir_len | Directory section length in bytes (padded — see below) |
| 0x0C | 4 | dat_len | Total audio data length in bytes |
| 0x10 | 4 | version | 0x00040000 (FSB version 4)
|
| 0x14 | 4 | flags | Header flags — see #Header Flags |
| 0x18 | 8 | padding | Zero bytes |
| 0x20 | 16 | bank_uuid | Bank UUID — not validated by FMOD, left as zeros in tool-built files |
dir_len includes alignment padding
dir_len is not the raw sum of directory entry sizes. It is the distance from byte 48 to the start of audio data, rounded up to the nearest 32-byte boundary. This ensures the audio data section begins at a 32-byte aligned offset, which is required otherwise the track will play incorrectly or not at all.
raw_dir_len = sum of all (entry_len) values data_start = align_up(48 + raw_dir_len, 32) dir_len = data_start - 48
The space between the last directory entry and the audio data is filled with zero padding bytes.
Directory Entry (80 bytes base + optional startpoint table)
Each audio sample has one directory entry. The base structure is 80 bytes. If startpoints are present, the startpoint table is appended immediately after, and entry_len covers both.
| Offset | Size | Field | Description |
|---|---|---|---|
| 0x00 | 2 | entry_len | Total length of this entry including startpoint table (80 if no table, 80 + sp_size if present) |
| 0x02 | 30 | filename | Sample filename, null-padded |
| 0x20 | 4 | sample_len | Total PCM sample count (see #Sample Length Calculation) |
| 0x24 | 4 | compressed_len | Byte length of this sample's audio data in the data section |
| 0x28 | 4 | loop_start | Loop start sample (0 = no loop) |
| 0x2C | 4 | loop_end | Loop end sample (sample_len - 1 for full-track loop)
|
| 0x30 | 4 | play_mode | Playback flags — see #FSOUND_FLAGS (Play Mode) |
| 0x34 | 4 | sample_rate | Sample rate in Hz (typically 44100) |
| 0x38 | 2 | bank_volume | Volume (0–255, 255 = full) |
| 0x3A | 2 | pan | Pan (0–255, 128 = center) |
| 0x3C | 2 | playback_priority | Playback priority (128 = default) |
| 0x3E | 2 | num_channels | Number of channels (1 = mono, 2 = stereo, 6 = 5.1) |
| 0x40 | 4 | min_distance | 3D minimum distance (f32) |
| 0x44 | 4 | max_distance | 3D maximum distance (f32) |
| 0x48 | 4 | var_freq | Variable frequency (f32) |
| 0x4C | 2 | var_vol | Variable volume |
| 0x4E | 2 | var_pan | Variable pan |
Sample Length Calculation
For stereo (2ch) tracks: sample_len equals the total number of PCM samples in one channel. At 160kbps CBR, this is frame_count × 1152.
For multichannel tracks (e.g. 6ch built from 3 interleaved stereo pairs): sample_len is still frame_count × 1152 — it is not multiplied by channel count. The 6ch interleaved stream has the same sample count as a single stereo pair; the extra channels are encoded as interleaved frames within the same MPEG stream.
Startpoint Table (optional)
Appended directly after the 80-byte base entry when entry_len > 80. Only present when the FSOUND_SYNCPOINTS flag is set in play_mode.
| Offset | Size | Field | Description |
|---|---|---|---|
| 0x00 | 4 | magic | "SYNC" (0x434E5953)
|
| 0x04 | 4 | count | Number of startpoint entries |
Each startpoint entry is 260 bytes:
| Offset | Size | Field | Description |
|---|---|---|---|
| 0x00 | 4 | sample_offset | Absolute sample offset into the audio track |
| 0x04 | 10 | label | ASCII string "startpoint"
|
| 0x0E | 246 | reserved | Zero bytes |
Startpoints allow the game to jump to specific positions in the music. In LittleBigPlanet, only track 0 of a multi-track bank receives startpoints. Typical count: 5 for single-track stereo, 7 for multi-track, but can vary between 1-8. Positions are usually snapped to MP3 frame boundaries (multiples of 1152 samples).
Audio Data Section
Begins at 0x30 + dir_len (32-byte aligned). Contains raw MPEG frames for each sample, concatenated in directory order. The byte offset of each sample's audio data is the running sum of compressed_len values from preceding entries, starting from data_start.
MPEG Frame Padding (MPEG_PADDED)
When the FMOD_FSB_SOURCE_MPEG_PADDED flag (0x20) is set in the file header, each MPEG frame in the audio data section is padded with zero bytes to meet alignment requirements:
| Track type | Padding alignment |
|---|---|
| Stereo (2ch) | Nearest 2-byte boundary |
| Multichannel (6ch) | Nearest 16-byte boundary |
The padding bytes exist between frames — they are not inserted into the frame data itself. The MPEG frame header's padding_bit field is unrelated to this FMOD-level padding.
This flag is required. FMOD on PS3 will not play FSB4 files without MPEG_PADDED set. The audio data bytes (frame payloads) are identical to a standard MP3 file; only the inter-frame spacing differs.
MPEG Frame Format
LittleBigPlanet uses MPEG1 Layer III (MP3) exclusively:
| Parameter | Value |
|---|---|
| Version | MPEG1 |
| Layer | III |
| Sample rate | 44100 Hz |
| Bitrate | 160 kbps CBR |
| Channels | 2 (stereo per pair) |
| Frame size | 522 bytes (unpadded) or 523 bytes (with padding bit) |
| Samples per frame | 1152 |
Frames are identified by the 11-bit sync word (all ones) followed by header bytes. In practice, the second byte is 0xFB (MPEG1, Layer III, no CRC). The frame size formula is:
frame_size = (144 × bitrate_bps / sample_rate) + padding_bit
= (144 × 160000 / 44100) + padding_bit
= 522 + padding_bit
Multichannel Interleaving (6ch)
Six-channel tracks are built from 3 stereo MP3 pairs interleaved frame-by-frame:
[pair1_frame0] [pad 16] [pair2_frame0] [pad 16] [pair3_frame0] [pad 16] [pair1_frame1] [pad 16] [pair2_frame1] [pad 16] [pair3_frame1] [pad 16] ...
FMOD reads frames in round-robin order: frame N from pair 1, frame N from pair 2, frame N from pair 3, then advances to frame N+1. Each pair's frames are padded to 16-byte boundaries per MPEG_PADDED for multichannel.
The FSOUND_MULTICHANNEL flag (0x04000000) in play_mode tells FMOD to deinterleave the pairs into separate channel streams during playback. The channel layout follows Pro Tools convention (L, C, R, LS, RS, LFE) when FSOUND_CHANNELMODE_PROTOOLS is also set.
The minimum frame count across all 3 pairs is used — longer pairs are truncated to match the shortest.
Header Flags
Bitmask values for the flags field at offset 0x14 in the file header.
| Flag | Value | Description |
|---|---|---|
FMOD_FSB_SOURCE_FORMAT |
0x00000001 | Samples stored in original compressed format |
FMOD_FSB_SOURCE_BASICHEADERS |
0x00000002 | Use basic header structure |
FMOD_FSB_SOURCE_ENCRYPTED |
0x00000004 | All sample data is encrypted |
FMOD_FSB_SOURCE_BIGENDIANPCM |
0x00000008 | PCM samples in big-endian byte order |
FMOD_FSB_SOURCE_NOTINTERLEAVED |
0x00000010 | Sample data is not interleaved |
FMOD_FSB_SOURCE_MPEG_PADDED |
0x00000020 | MPEG frames padded: 2-byte (stereo) / 16-byte (multichannel) |
FMOD_FSB_SOURCE_MPEG_PADDED4 |
0x00000040 | MPEG frames padded: 4-byte (stereo) / 16-byte (multichannel) |
LittleBigPlanet files use 0x20 (FMOD_FSB_SOURCE_MPEG_PADDED).
FSOUND_FLAGS (Play Mode)
Bitmask values for the play_mode field in directory entries. These are the same flags used in FMOD's FSOUND_SetMode() API.
Loop Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_LOOP_OFF |
0x00000001 | No looping |
FSOUND_LOOP_NORMAL |
0x00000002 | Forward looping |
FSOUND_LOOP_BIDI |
0x00000004 | Bidirectional looping (no effect in hardware) |
Sample Format Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_8BITS |
0x00000008 | 8-bit samples |
FSOUND_16BITS |
0x00000010 | 16-bit samples |
FSOUND_MONO |
0x00000020 | Mono channel |
FSOUND_STEREO |
0x00000040 | Stereo (2 channels) |
FSOUND_UNSIGNED |
0x00000080 | Unsigned sample data |
FSOUND_SIGNED |
0x00000100 | Signed sample data |
Compression Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_MPEG |
0x00000200 | MPEG Layer 2/3 compressed data |
FSOUND_MPEG_LAYER2 |
0x00040000 | MPEG Layer 2 data |
FSOUND_MPEG_LAYER3 |
0x10000000 | MPEG Layer 3 (MP3) data |
FSOUND_IMAADPCM |
0x00400000 | IMA ADPCM compressed |
FSOUND_IMAADPCMSTEREO |
0x20000000 | IMA ADPCM stereo (not two interleaved mono) |
FSOUND_VAG |
0x00800000 | Sony VAG format (PS2 only) |
FSOUND_XMA |
0x01000000 | XMA format (Xbox 360 only) |
FSOUND_GCADPCM |
0x02000000 | GameCube DSP-ADPCM |
FSOUND_OGG |
0x08000000 | Vorbis OGG |
Channel Mode Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_CHANNELMODE_ALLMONO |
0x00000400 | Collection of mono channels |
FSOUND_CHANNELMODE_ALLSTEREO |
0x00000800 | Collection of stereo channel pairs |
FSOUND_CHANNELMODE_PROTOOLS |
0x00010000 | 6ch Pro Tools layout (L C R LS RS LFE) |
Playback Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_MULTICHANNEL |
0x04000000 | Interleaved multi-channel format (PS2/GC) |
FSOUND_2D |
0x00002000 | Ignore 3D processing |
FSOUND_3D |
0x00100000 | 3D software sound |
FSOUND_HW2D |
0x00080000 | 2D hardware sound |
FSOUND_HW3D |
0x00001000 | 3D hardware acceleration |
FSOUND_DUPLICATE |
0x00008000 | Duplicate of previous subsound (same data, different mode bits) |
FSOUND_32BITS |
0x00200000 | 32-bit float samples |
Metadata Flags
| Flag | Value | Description |
|---|---|---|
FSOUND_SYNCPOINTS |
0x80000000 | Syncpoint (startpoint) table present |
FSOUND_SYNCPOINTS_NONAMES |
0x00004000 | Syncpoints present without name labels |
FSOUND_MPEGACCURATE |
0x00020000 | Accurate stream length/time operations |
FSOUND_IGNORETAGS |
0x40000000 | Skip ID3v2 tag checks when opening stream |
Platform-Specific (PS2)
| Flag | Value | Description |
|---|---|---|
FSOUND_LOADMEMORYIOP |
0x20000000 | Name interpreted as IOP memory address (PS2) |
Note: FSOUND_LOADMEMORYIOP and FSOUND_IMAADPCMSTEREO share the same bit value (0x20000000). This is intentional — they are context-dependent and mutually exclusive by format.
Common LittleBigPlanet Play Modes
| Value | Flags | Use |
|---|---|---|
0x80000240 |
SYNCPOINTS + MPEG + STEREO | Stereo track with startpoints |
0x00000240 |
MPEG + STEREO | Stereo track without startpoints |
0x84000200 |
SYNCPOINTS + MULTICHANNEL + MPEG | 6ch track with startpoints |
0x04000200 |
MULTICHANNEL + MPEG | 6ch track without startpoints |
Example: appliance_of_science.fsb
Single stereo track, 160kbps MP3, 44100Hz, ~3:26 duration.
File Header (0x000–0x02F)
0x000: 46 53 42 34 "FSB4" 0x004: 01 00 00 00 num_files = 1 0x008: 90 08 00 00 dir_len = 0x890 (2192 bytes, includes padding) 0x00C: 80 10 3F 00 dat_len = 0x3F1080 (4132992 bytes) 0x010: 00 00 04 00 version = 0x00040000 0x014: 20 00 00 00 flags = 0x20 (MPEG_PADDED) 0x018: 00 00 00 00 00 00 00 00 padding 0x020: 15 D6 A2 28 51 35 35 43 A9 CF ... bank_uuid
Directory Entry (0x030–0x08A7)
Base entry (80 bytes):
0x030: 78 08 entry_len = 0x878 (2168 bytes, includes startpoint table) 0x032: 61 70 70 6C 69 61 6E 63 65 5F ... filename = "appliance_of_science.wav" 0x050: 00 F0 8A 00 sample_len = 9105408 0x054: 80 10 3F 00 compressed_len = 4132992 0x058: 00 00 00 00 loop_start = 0 0x05C: FF EF 8A 00 loop_end = 9105407 0x060: 40 02 00 80 play_mode = 0x80000240 0x064: 44 AC 00 00 sample_rate = 44100 0x068: FF 00 volume = 255 0x06A: 80 00 pan = 128 (center) 0x06C: 80 00 priority = 128 0x06E: 02 00 num_channels = 2 0x070–0x07F: 3D 00 00 00 00 40 1C 46 00 00 00 00 00 00 00 00
Startpoint table (at 0x080, after the 80-byte base entry):
0x080: 53 59 4E 43 "SYNC" 0x084: 08 00 00 00 count = 8
8 entries × 260 bytes each (0x088–0x08A7):
| # | Sample Offset | Time |
|---|---|---|
| 0 | 396,897 | 9.0s |
| 1 | 1,243,634 | 28.2s |
| 2 | 2,090,032 | 47.4s |
| 3 | 2,936,516 | 66.6s |
| 4 | 3,781,720 | 85.8s |
| 5 | 5,477,247 | 124.2s |
| 6 | 6,323,333 | 143.4s |
| 7 | 8,017,338 | 181.8s |
Alignment Padding (0x08A8–0x08BF)
Zero bytes padding the directory to 32-byte alignment. dir_len (0x890) accounts for this: 0x08C0 - 0x030 = 0x890.
Audio Data (0x08C0+)
MPEG1 Layer III frames at 160kbps, 44100Hz stereo. Frames alternate between 522 bytes (no padding bit) and 523 bytes (padding bit set), separated by 0–1 zero padding bytes per MPEG_PADDED.
0x08C0: FF FB A0 60 ... first MPEG frame (522 bytes, no padding needed — even)
FF FB A2 60 ... second MPEG frame (523 bytes, padding bit set)
00 1-byte padding to 2-byte boundary (523 is odd)
FF FB A0 60 ... third MPEG frame (522 bytes, no padding needed — even)
...