Wave Dictionary: Difference between revisions

From Burnout Wiki
Content added Content deleted
(D'oh.)
(→‎Data type: Audio Layer I is only for MPEG-1, and IMAADPCM might've meant to be standard IMA, not specifically MS)
 
(42 intermediate revisions by 4 users not shown)
Line 1: Line 1:
The '''RenderWare Audio Wave Dictionary''' container format is used to store a collection of audio files. It uses the file extension <code>.awd</code>.
The '''RenderWare Audio Wave Dictionary''' container format stores audio assets in a linked list. It is normally given the file extensions <code>.awd</code>, <code>.hwd</code>, and <code>.lwd</code>.


Wave dictionaries are used in Burnout 3, Revenge, and Dominator, as well as Black and Call of Duty: Finest Hour. Note that although Burnout Legends uses .*wd extensions, its files are not the same format as described here.
= Layout =

{| class="wikitable" style=text-align:left
= Structures =
! Offset
=== Stream header ===
! Name
{| class="wikitable"
! Type
! Offset !! Length !! Type !! Name !! Description !! Comments
! Value
! Description
|-
|-
| 0x0 || 0x4 || RwUInt32 || ? || Magic number || 0x809
! colspan="5" | Header
|-
|-
| 0x4 || 0x1 || bool || ? || Indicates the stream header should be byteswapped || Causes <code>_RwaWaveDictStreamHeaderByteSwap()</code> to be run
|-
| 0x5 || 0x3 || || || Padding ||
|-
| 0x8 || 0x4 || RwUInt32 || ? || Size of the header data to read for wave loading ||
|-
| 0xC || 0x4 || [[#RwaWaveDict|RwaWaveDict]]* || ? || Wave dictionary ||
|-
| 0x10 || 0x4 || RwUInt32 || ? || || Unknown, but set at runtime if used
|-
| 0x14 || 0x4 || RwUInt32 || ? || Wave data size ||
|-
| 0x18 || 0x10 || [[#RwaUUID|RwaUUID]] || ? || Platform UUID || See [[#Platform|platform]]
|-
| 0x28 || 0x4 || void* || ? || Wave data ||
|}

=== RwaWaveDict ===
{{todo|Research and list flags.}}


{| class="wikitable"
{{ MemoryLocationTableRow | name= | offset=0x00 | type=RwUInt32 | value=0x809 | description=Magic Number. }}
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0xC || [[#RwaUniqueID|RwaUniqueID]] || uniqueID || Dictionary ID || UUID set at runtime
{{ MemoryLocationTableRow | name= | offset=0x04 | value= | type=uintptr_t | description=Pointer to location in system memory. Usually <code>nullptr</code>. }}
|-
|-
| 0xC || 0xC || [[#RwaLLNode|RwaLLNode]] || waveListHead || || Prev wraps to final node, next is first node, and data is nullptr<br>In wave dictionaries, data is an [[#RwaWave|RwaWave]]
{{ MemoryLocationTableRow | name= | offset=0x08 | value= | type=UInt32 | description=Container size. }}
|-
|-
| 0x18 || 0x2 || RwUInt8[2] || pad || Padding ||
{{ MemoryLocationTableRow | name= | offset=0x0C | value= | type=UInt32 | description=Container header size. }}
|-
|-
| 0x1A || 0x1 || RwUInt8 || flagsAux || Auxiliary flags ||
{{ MemoryLocationTableRow | name= | offset=0x10 | value= | type=UInt32 | description=If value at <code>0x04</code> is non-zero then this will be, too. }}
|-
|-
| 0x1B || 0x1 || RwUInt8 || flags || Flags ||
{{ MemoryLocationTableRow | name= | offset=0x14 | value= | type=UInt32 | description=Audio data size. }}‎
|-
|-
| 0x1C || 0x4 || RwLLLink || link || || Set at runtime<br>Structure not documented here
{{ MemoryLocationTableRow | name= | offset=0x18 | type=byte[128] | value=<div style="text-align:center">0x73F2018B75DFF0814BC8E45F453A2D04 (Xbox)<br>0x‎‎‎‎5393C7DBEA6481AE4917FC38AAEAC9AC (PS2)</div> | description=Platform UUID. }}
|-
|-
| 0x24 || 0x4 || void* || dumpAddr || Wave dump address || Set at runtime
{{ MemoryLocationTableRow | name= | offset=0x28 | value= | type=UInt32 | description=Audio data position. }}
|-
|-
| 0x28 || 0x4 || void* || waveRAMHandle || Wave handle || Set at runtime
! colspan="5" | Wave Dictionary
|-
|-
| 0x2C || 0x4 || RwUInt32 || waveRAMSize || Wave size in memory || Set at runtime
{{ MemoryLocationTableRow | offset=0x2C | name=uniqueID | type=RwaUniqueID | value= | description= }}
|}

=== RwaUniqueID ===
{{todo|Research and list flags.}}

{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0x4 || [[#RwaUniqueID__uuid|RwaUniqueID__uuid]] || uuid || UUID ||
{{ MemoryLocationTableRow | offset=0x38 | name=waveListHead | type=RwaLLNode | value= | description= }}
|-
|-
| 0x4 || 0x4 || [[#RwaUniqueID__uuid|RwaUniqueID__name]] || name || Name ||
{{ MemoryLocationTableRow | offset=0x44 | name=pad | type=byte[2] | value= | description= }}
|-
|-
| 0x8 || 0x4 || RwUInt32 || flags || Flags ||
{{ MemoryLocationTableRow | offset=0x46 | name=flagsAux | type=RwUInt8 | value= | description= }}
|}

=== RwaLLNode ===
{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0x4 || RwaLLNode* || prev || Previous node ||
{{ MemoryLocationTableRow | offset=0x47 | name=flags | type=RwUInt8 | value= | description= }}
|-
|-
| 0x4 || 0x4 || RwaLLNode* || next || Next node ||
{{ MemoryLocationTableRow | offset=0x48 | name=link | type=RwLLLink | value= | description= }}
|-
|-
| 0x8 || 0x4 || void* || data || Current node's data ||
{{ MemoryLocationTableRow | offset=0x50 | name=dumpAddr | type=void* | value= | description= }}
|}

=== RwaWave ===
{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
|-
| 0x0 || 0xC || [[#RwaUniqueID|RwaUniqueID]] || uniqueID || Wave ID || Data set at runtime
{{ MemoryLocationTableRow | offset=0x54 | name=waveRAMHandle | type=void* | value= | description= }}
|-
|-
| 0xC || 0x4 || RwaWaveDef* || waveDef || Wave definition<br>Primarily contains function pointers || Set at runtime<br>Structure not described here
{{ MemoryLocationTableRow | offset=0x58 | name=waveRAMSize | type=RwUInt32 | value= | description= }}
|-
|-
| 0x10 || 0x1C || [[#RwaWaveFormat|RwaWaveFormat]] || format || Source wave format ||
! colspan="5" | <br> <!-- TODO: wtf is this called -->
|-
|-
| 0x2C || 0x1C || [[#RwaWaveFormat|RwaWaveFormat]] || targetFormat || Target wave format ||
{{ MemoryLocationTableRow | offset=0x5C | name= | value= | type=char[] | description=Name of the AWD.<br>Size between 1 and 12 characters.<br>Padded to the nearest 4-byte boundary. }}
|-
|-
| 0x48 || 0x4 || RwUInt32 || uncompressedLength || || Null in samples. Set at runtime?
{{ MemoryLocationTableRow | offset= | name= | value= | type=RwLinkList<RwaLLNode> | description=Node data is of type <code>RwaWave</code> (see below.) }}
|-
|-
| 0x4C || 0x4 || void* || data || Wave data || Set at runtime
|-
| 0x50 || 0x4 || void* || state || Wave state || Set at runtime
|-
| 0x54 || 0x4 || RwUInt32 || flags || Flags ||
|-
| 0x58 || 0x4 || RwaObj* || obj || Object data || Set at runtime<br>Structure not described here
|}
|}


== RwaWave ==
=== RwaWaveFormat ===
{{todo|Research and list flags.<br>Research misc data.}}
Each wave is of type <code>RwaWave</code>, stored in a <code>RwLLNode</code> in the <code>RwLinkList</code>. In the AWD are of type , and are serialized as below:

{| class="wikitable" style=text-align:left
{| class="wikitable"
! Offset
! Offset !! Length !! Type !! Name !! Description !! Comments
! Name
! Type
! Value
! Description
|-
|-
| 0x0 || 0x4 || RwUInt32 || sampleRate || Sample rate ||
{{ MemoryLocationTableRow | offset=0x00 | name=uniqueID | type=RwaUniqueID | value= | description= }}
|-
|-
| 0x4 || 0x4 || RwaUUID* || dataType || Sample format || Index in asset, set to pointer at runtime.<br>See [[#Data type|data type]]
{{ MemoryLocationTableRow | offset=0x0C | name=waveDef | type=RwaWaveDef* | value= | description=Pointer to location in system memory. }}
|-
|-
| 0x8 || 0x4 || RwUInt32 || length || Duration (milliseconds) ||
{{ MemoryLocationTableRow | offset=0x10 | name=format | type=[[Wave Dictionary#RwaWaveFormat|RwaWaveFormat]] | value= | description= }}
|-
|-
| 0xC || 0x1 || uint8_t || bitDepth || Bit depth ||
{{ MemoryLocationTableRow | offset=0x2C | name=targetFormat | type=RwaWaveFormat | value= | description= Usually identical to <code>format</code>. }}
|-
|-
| 0xD || 0x1 || uint8_t || noChannels || Number of channels ||
{{ MemoryLocationTableRow | offset=0x48 | name=uncompressedLength | type=RwUInt32 | value= | description= }}
|-
|-
| 0xE || 0x2 || RwUInt8[2] || pad || Padding ||
{{ MemoryLocationTableRow | offset=0x4C | name=data| type=void* | value= | description= }}
|-
|-
| 0x10 || 0x4 || void* || miscData || Additional platform-specific data || Only used on GameCube in practice, where an additional header with coefficients and initial history data is present.
{{ MemoryLocationTableRow | offset=0x50 | name=state | type=void* | value= | description= }}
|-
|-
{{ MemoryLocationTableRow | offset=0x54 | name=flags| type=RwUInt32 | value= | description= }}
| 0x14 || 0x4 || RwUInt32 || miscDataSize || Additional data size ||
|-
|-
| 0x18 || 0x1 || uint8_t || flags || Flags ||
{{ MemoryLocationTableRow | offset=0x58 | name=obj | type=RwaObj* | value= | description= }}
|-
|-
| 0x19 || 0x1 || uint8_t || reserved || ||
|-
| 0x1A || 0x2 || || || Padding ||
|}
|}


=== RwaUUID ===
This is followed by the <code>RwaLLNode</code>, the entry (of type <code>char[]</code>) and a 128-bit UUID.
{| class="wikitable"
! Offset !! Length !! Type !! Name !! Description !! Comments
|-
| 0x0 || 0x4 || RwUInt32 || time_low || rowspan=3|Timestamp if version 1, otherwise random || rowspan=3|Always a random value as UUID version is always 4<br>See [https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-4 RFC 9562 Section 5.4]
|-
| 0x4 || 0x2 || RwUInt16 || time_mid
|-
| 0x6 || 0x2 || RwUInt16 || time_hi_and_version
|-
| 0x8 || 0x8 || RwUInt8[8] || node || ||
|}


== RwaUniqueID ==
= Unions =
=== RwaUniqueID__uuid ===
<syntaxhighlight lang="cpp">
{| class="wikitable"
struct RwaUniqueID {
! Length !! Type !! Name !! Description !! Comments
union {
|-
RwaUUID* uuid;
| 0x4 || [[#RwaUUID|RwaUUID]]* || uuid || ||
RwaUUID* copyUUID;
|-
}
| 0x4 || [[#RwaUUID|RwaUUID]]* || copyUUID || ||
|}


=== RwaUniqueID__name ===
struct name {
{| class="wikitable"
char* uniqueName;
! Length !! Type !! Name !! Description !! Comments
char* copyName;
|-
}
| 0x4 || RwChar* || uniqueName || ||
};
|-
</syntaxhighlight>
| 0x4 || RwChar* || copyName || ||
|}

= Enumerations =
=== Data type ===
{| class="wikitable"
! Index !! Name !! Format || UUID
|-
| 0 || rwaWAVEFORMAT_VAG || PlayStation VAG ADPCM || <code>d9ea9798-bbbc-447b-96b2-654759102e16</code>
|-
| 1 || rwaWAVEFORMAT_PCM || Signed 16-bit PCM || <code>d01bd217-3587-4eed-b9d9-b8e86ea9b995</code>
|-
| 2 || rwaWAVEFORMAT_FLOAT || || <code>da1e4382-2c99-4c61-ad99-7f364b211537</code>
|-
| 3 || rwaWAVEFORMAT_GCNADPCM || Nintendo DSP-ADPCM || <code>f86215b0-31d5-4c29-bd37-cdbf9bd10c53</code>
|-
| 4 || rwaWAVEFORMAT_XADPCM || Xbox IMA ADPCM || <code>632fa22b-11dd-458f-aa27-a5c346e9790e</code>
|-
| 5 || rwaWAVEFORMAT_WMA || Windows Media Audio || <code>3f1d8147-b7c4-41e6-a69b-3cc0025b33c7</code>
|-
| 6 || rwaWAVEFORMAT_MP3 || MPEG-1/2 Audio Layer III || <code>bacfb36e-529d-4692-bf53-324256b0734f</code>
|-
| 7 || rwaWAVEFORMAT_MP2 || MPEG-1/2 Audio Layer II || <code>34d09a54-57d3-409e-a6ad-2bc845aec339</code>
|-
| 8 || rwaWAVEFORMAT_MPG || MPEG-1 Audio Layer I || <code>04c15ba7-f907-40ab-a49f-eefef8c4d296</code>
|-
| 9 || rwaWAVEFORMAT_AC3 || Dolby AC-3 || <code>a30db390-58a9-43c4-b9d2-55d84d3ae754</code>
|-
| 10 || rwaWAVEFORMAT_IMAADPCM || IMA ADPCM || <code>ef386593-b611-432d-957f-a71ade44227a</code>
|}
IMA ADPCM is uncertain - Standard IMA? Microsoft IMA? Xbox IMA? VGMStream claims the codec under that UUID is identical to Xbox IMA ADPCM for RenderWare Stream <code>.rws</code>.

=== Platform ===
{| class="wikitable"
! Name !! UUID
|-
| rwaHOST_PS2 || <code>aaeac9ac-fc38-4917-ae81-64eadbc79353</code>
|-
| rwaHOST_WIN32 || <code>44e50a10-08ba-4250-b971-69e921b9cf4f</code>
|-
| rwaHOST_XBOX || <code>453a2d04-e45f-4bc8-81f0-df758b01f273</code>
|-
| rwaHOST_GCN || <code>fd9d32d3-e179-426a-8424-14720ac7f648</code>
|}


[[Category:Formats_(Takedown-Dominator)]]
== RwaWaveFormat ==
<syntaxhighlight lang="cpp">
struct RwaWaveFormat {
uint32_t sampleRate;
RwaUUID* dataType;
uint32_t length;
uint8_t bitDepth;
uint8_t noChannels;
// uint8_t pad[2];
void* miscData;
uint8_t miscDataSize;
uint8_t flags;
uint8_t reserved;
};
</syntaxhighlight>

Latest revision as of 14:19, 1 June 2024

The RenderWare Audio Wave Dictionary container format stores audio assets in a linked list. It is normally given the file extensions .awd, .hwd, and .lwd.

Wave dictionaries are used in Burnout 3, Revenge, and Dominator, as well as Black and Call of Duty: Finest Hour. Note that although Burnout Legends uses .*wd extensions, its files are not the same format as described here.

Structures

Stream header

Offset Length Type Name Description Comments
0x0 0x4 RwUInt32 ? Magic number 0x809
0x4 0x1 bool ? Indicates the stream header should be byteswapped Causes _RwaWaveDictStreamHeaderByteSwap() to be run
0x5 0x3 Padding
0x8 0x4 RwUInt32 ? Size of the header data to read for wave loading
0xC 0x4 RwaWaveDict* ? Wave dictionary
0x10 0x4 RwUInt32 ? Unknown, but set at runtime if used
0x14 0x4 RwUInt32 ? Wave data size
0x18 0x10 RwaUUID ? Platform UUID See platform
0x28 0x4 void* ? Wave data

RwaWaveDict

Hmmm...
Hmmm...
To do:
Research and list flags.
Offset Length Type Name Description Comments
0x0 0xC RwaUniqueID uniqueID Dictionary ID UUID set at runtime
0xC 0xC RwaLLNode waveListHead Prev wraps to final node, next is first node, and data is nullptr
In wave dictionaries, data is an RwaWave
0x18 0x2 RwUInt8[2] pad Padding
0x1A 0x1 RwUInt8 flagsAux Auxiliary flags
0x1B 0x1 RwUInt8 flags Flags
0x1C 0x4 RwLLLink link Set at runtime
Structure not documented here
0x24 0x4 void* dumpAddr Wave dump address Set at runtime
0x28 0x4 void* waveRAMHandle Wave handle Set at runtime
0x2C 0x4 RwUInt32 waveRAMSize Wave size in memory Set at runtime

RwaUniqueID

Hmmm...
Hmmm...
To do:
Research and list flags.
Offset Length Type Name Description Comments
0x0 0x4 RwaUniqueID__uuid uuid UUID
0x4 0x4 RwaUniqueID__name name Name
0x8 0x4 RwUInt32 flags Flags

RwaLLNode

Offset Length Type Name Description Comments
0x0 0x4 RwaLLNode* prev Previous node
0x4 0x4 RwaLLNode* next Next node
0x8 0x4 void* data Current node's data

RwaWave

Offset Length Type Name Description Comments
0x0 0xC RwaUniqueID uniqueID Wave ID Data set at runtime
0xC 0x4 RwaWaveDef* waveDef Wave definition
Primarily contains function pointers
Set at runtime
Structure not described here
0x10 0x1C RwaWaveFormat format Source wave format
0x2C 0x1C RwaWaveFormat targetFormat Target wave format
0x48 0x4 RwUInt32 uncompressedLength Null in samples. Set at runtime?
0x4C 0x4 void* data Wave data Set at runtime
0x50 0x4 void* state Wave state Set at runtime
0x54 0x4 RwUInt32 flags Flags
0x58 0x4 RwaObj* obj Object data Set at runtime
Structure not described here

RwaWaveFormat

Hmmm...
Hmmm...
To do:
Research and list flags.
Research misc data.
Offset Length Type Name Description Comments
0x0 0x4 RwUInt32 sampleRate Sample rate
0x4 0x4 RwaUUID* dataType Sample format Index in asset, set to pointer at runtime.
See data type
0x8 0x4 RwUInt32 length Duration (milliseconds)
0xC 0x1 uint8_t bitDepth Bit depth
0xD 0x1 uint8_t noChannels Number of channels
0xE 0x2 RwUInt8[2] pad Padding
0x10 0x4 void* miscData Additional platform-specific data Only used on GameCube in practice, where an additional header with coefficients and initial history data is present.
0x14 0x4 RwUInt32 miscDataSize Additional data size
0x18 0x1 uint8_t flags Flags
0x19 0x1 uint8_t reserved
0x1A 0x2 Padding

RwaUUID

Offset Length Type Name Description Comments
0x0 0x4 RwUInt32 time_low Timestamp if version 1, otherwise random Always a random value as UUID version is always 4
See RFC 9562 Section 5.4
0x4 0x2 RwUInt16 time_mid
0x6 0x2 RwUInt16 time_hi_and_version
0x8 0x8 RwUInt8[8] node

Unions

RwaUniqueID__uuid

Length Type Name Description Comments
0x4 RwaUUID* uuid
0x4 RwaUUID* copyUUID

RwaUniqueID__name

Length Type Name Description Comments
0x4 RwChar* uniqueName
0x4 RwChar* copyName

Enumerations

Data type

Index Name Format UUID
0 rwaWAVEFORMAT_VAG PlayStation VAG ADPCM d9ea9798-bbbc-447b-96b2-654759102e16
1 rwaWAVEFORMAT_PCM Signed 16-bit PCM d01bd217-3587-4eed-b9d9-b8e86ea9b995
2 rwaWAVEFORMAT_FLOAT da1e4382-2c99-4c61-ad99-7f364b211537
3 rwaWAVEFORMAT_GCNADPCM Nintendo DSP-ADPCM f86215b0-31d5-4c29-bd37-cdbf9bd10c53
4 rwaWAVEFORMAT_XADPCM Xbox IMA ADPCM 632fa22b-11dd-458f-aa27-a5c346e9790e
5 rwaWAVEFORMAT_WMA Windows Media Audio 3f1d8147-b7c4-41e6-a69b-3cc0025b33c7
6 rwaWAVEFORMAT_MP3 MPEG-1/2 Audio Layer III bacfb36e-529d-4692-bf53-324256b0734f
7 rwaWAVEFORMAT_MP2 MPEG-1/2 Audio Layer II 34d09a54-57d3-409e-a6ad-2bc845aec339
8 rwaWAVEFORMAT_MPG MPEG-1 Audio Layer I 04c15ba7-f907-40ab-a49f-eefef8c4d296
9 rwaWAVEFORMAT_AC3 Dolby AC-3 a30db390-58a9-43c4-b9d2-55d84d3ae754
10 rwaWAVEFORMAT_IMAADPCM IMA ADPCM ef386593-b611-432d-957f-a71ade44227a

IMA ADPCM is uncertain - Standard IMA? Microsoft IMA? Xbox IMA? VGMStream claims the codec under that UUID is identical to Xbox IMA ADPCM for RenderWare Stream .rws.

Platform

Name UUID
rwaHOST_PS2 aaeac9ac-fc38-4917-ae81-64eadbc79353
rwaHOST_WIN32 44e50a10-08ba-4250-b971-69e921b9cf4f
rwaHOST_XBOX 453a2d04-e45f-4bc8-81f0-df758b01f273
rwaHOST_GCN fd9d32d3-e179-426a-8424-14720ac7f648