-
Notifications
You must be signed in to change notification settings - Fork 3
Wave Bank Format
This page is a work-in-progress. And only intended for use by developers/programmers.
Filesize Note: The 3 different wavebank formats: Compact, Standard, and Streaming each have different requirements on total filesize and how audio wave data is aligned.
Xbox Note: Xbox WaveBanks Have all data written in Big Endian format, opposite of Windows, stored in little endian. You may determine which format a file is in by comparing the order of the signature characters. "WBND" for Windows, "DNBW" for Xbox.
| Data Type | Value | Description |
|---|---|---|
char[4] |
"WBND" | File Signature |
uint32 |
ContentVersion | Version of this file format (46) |
uint32 |
ToolVersion | Version of XACT toolset that wrote this format? (44) |
| Segment[5] | Segments | Offset/Length pairs to different data in the wave bank beyond this point |
| Data Type | Value | Description |
|---|---|---|
uint32 |
Offset | Absolute offset to data |
uint32 |
Length | Length of data at offset |
* Note: A segment length of 0 is considered valid even when the offset is non-zero. In these cases, the segment is not read.
The index of each segment determines what type of data is pointed to.
| # | Name | Details |
|---|---|---|
0 |
BankData | Extended information of this wave bank file (required) |
1 |
EntryMetadata | Table of fixed-length structures describing each Wave in the Wave Bank (required) |
2 |
SeekTables | Table of variable-length arrays for each entry with preprocessed? offsets used for seeking (optional) |
3 |
EntryNames | Table of fixed-length names for each entry (optional) |
4 |
EntryWaveData | Table of raw audio data pointed to by structures in EntryMetadata (required) |
| Data Type | Value | Description |
|---|---|---|
uint32 |
Flags | WaveBank flags... |
uint32 |
EntryCount | Number of Waves |
char[64] |
BankName | Name of wave bank |
uint32 |
EntryMetadataSize | Fixed size of each metadata structure in EntryMetadata |
uint32 |
EntryNameSize | Fixed size of each entry name in EntryNames |
uint32 |
Alignment | Alignment of entry audio data in EntryWaveData |
uint32 |
CompactFormat | Format for all Waves when Compact flag |
uint64 |
BuildTime | Build FILETIME of the wave bank |
| Value | Flag | Description |
|---|---|---|
0x1 |
Streaming | Streaming wave data format |
0x10000 |
EntryNames | EntryNames segment is defined |
0x20000 |
Compact | Compact wave bank entry format |
0x40000 |
SyncDisabled | Audition Sync is disabled*??* |
0x80000 |
SeekTables | SeekTables segment is defined |
* Note: Some versions of XNA/Xact3(?) have shown to fail when attempting to read wave banks with both EntryNames | SeekTables flags, (only when both segments have a non-zero length). Because of this, it is required to turn off the EntryNames flag when writing xWMA or XMA formats to the wavebank.
* Extended Note: A non-zero segment length is accepted as long as the associated flag is not set. Most available WaveBank readers present on the web either ignore the EntryNames segment altogether, or ignore the flag and read the segment when it's length is non-zero. Meaning this is a generally safe approach if you want to preserve this information.
N = BankData.EntryCount;
compact = (BankData.Flags & Compact);
typeof(Entry) = (compact ? EntryFull : EntryCompact);
sizeof(Entry) = BankData.EntryMetadataSize;| Data Type | Value | Description |
|---|---|---|
| Entry[N] | Entries | Table of Wave Entry metadata |
| Data Type | Value | Description |
|---|---|---|
uint32 |
FlagsAndDuration | EntryFlags and duration (in total samples) |
uint32 |
Format | Individual entry mini wave format |
uint32 |
PlayOffset | Offset to raw audio data (in bytes) relative to EntryWaveData |
uint32 |
PlayLength | Length of raw audio data (in bytes) |
uint32 |
LoopStart | The start sample position for looped audio |
uint32 |
LoopDuration | The duration in samples of the looped audio region |
| Data Bits | Value | Description |
|---|---|---|
bits[ 0:4] |
Flags | (value & 0xf) |
bits[4:32] |
Duration | (value >> 4) & 0x0fffffff |
It seems these flags only specify how to handle entry data, and not how to read/extract it.
| Value | Flag | Description |
|---|---|---|
0x1 |
ReadAhead | Enable stream read-ahead |
0x2 |
LoopCache | One or more looping sounds use this wave |
0x4 |
RemoveLoopTail | Remove data after the end of the loop region |
0x8 |
IgnoreLoop | Used internally when the loop region can't be used |
* Note: Flag descriptions taken directly from DirectXTK/xwbtool.cpp
| Data Type | Value | Description |
|---|---|---|
uint32 |
OffsetAndLengthDeviation | Combined PlayOffset/PlayLength of entry audio data |
| Data Bits | Value | Description |
|---|---|---|
bits[ 0:21] |
CompactOffset | (value & 0x1fffff) |
bits[21:32] |
LengthDeviation | (value >> 21) & 0x7ff |
UInt32 value = reader.ReadUInt32();
CompactOffset = (value & 0x1fffff);
// Deviation in data length to account for BankData.Alignment
LengthDeviation = (value >> 21) & 0x7ff;
PlayOffset = CompactOffset * BankData.Alignment;
UInt32 nextOff;
if (i+1 < BankData.EntryCount)
nextOff = Entries[i+1].PlayOffset;
else
nextOff = Header.Segments[4].Length; //EntryWaveData
PlayLength = (nextOff - PlayOffset) - LengthDeviation;N = BankData.EntryCount;
SeekTablesStart = N * 4; //sizeof(UInt32)| Data Type | Value | Description |
|---|---|---|
| uint32[N] | Offsets | Offset in bytes to entry seek table relative to Tables field |
| EntrySeekTable[>] | Tables | Entry seek table data pointed to by Offsets |
Skip the current entry seek table if Offsets[i] == 0xffffffff
Position = Offsets[i] + Header.Segments[2]; /*SeekTables*/ + (BankData.EntryCount * 4); //sizeof(UInt32)| Data Type | Value | Description |
|---|---|---|
uint32 |
Count | Number of values |
| uint32[Count] | SeekTable | Entry Wave seek table indices |
N = BankData.EntryCount;
Len = BankData.EntryNameSize;| Data Type | Value | Description |
|---|---|---|
| char[N][Len] | Names | Fixed length name of each Wave entry |
| Data Type | Value | Description |
|---|---|---|
| bytes | RawData | Raw audio data pointed to by Entry metadatas' PlayOffset and PlayLength |
* Note: Streaming wave data format will align the beginning of all audio data to the disk block size. As observed: this seems to be 2048, and not 4096.