bnk - themeldingwars/Documentation GitHub Wiki

On this page you can find a file format specification of the .bnk SoundBank files used by Wwise. SoundBanks by Wwise can be used to have a great deal of control over the soundtrack of a game, including the sound effects and the score. SoundBanks contain the individual audio files as well as containers to group the files, e.g. a gun shot container that plays a random gun shot sound. Also, SoundBanks contain events which can play or pause containers or audio files. Events are the only type of object that is visible outside the SoundBanks, and developers can access these events from the game code. For example, during a very emotional scene they could call a Play_EmotionalTheme event, which will play an emotional piece, as defined by the sound designer. Each Wwise project contains an initialization SoundBank, Init.bnk. This SoundBank contains the project settings and is loaded first. The other SoundBanks contain sounds for different parts of the game (e.g. one SoundBank for each area or level). They are loaded into memory whenever the player has reached that part of the game. The sound files are stored via a custom Wwise encoding and have the file extension .wem (before 2011, the Wwise extension was called .wav). For converting these files to .ogg files, I recommend the command-line utility ww2ogg by Halley's Comet Software (hcs). Depending on the game, some files are not embedded in the SoundBanks but are streamed. In this case, look in the game archive for .wem files.

010 Editor Templates

General format

FOR EACH (section) {
    byte[4]: four-letter identifier of the section, e.g. BKHD or DIDX
    uint32:  length of this section in bytes
    byte[]:  section data (see below)
} END FOR
-- END OF FILE --

To avoid errors when reading a .bnk file, it is recommended to always seek to the end of a section by using the byte length field. That way, even the program has reached the end of the section, it will automatically skip to the end in case it has left out something.

BKHD section

The BKHD section (BanK HeaDer) contains the version number and the SoundBank id.

42 4B 48 44 -- BKHD
uint32: length of section
uint32: version number of this SoundBank
uint32: id of this SoundBank
uint32: always zero
uint32: always zero

DIDX section

The DIDX (Data InDeX) section contains the references to the .wem files embedded in the SoundBank. Each sound file is described with 12 bytes, so you can get the number of embedded files by dividing the section length by 12.

44 49 44 58 -- DIDX
uint32: length of section
FOR EACH (embedded .wem file) {
    uint32: .wem file id
    uint32: offset from start of DATA section
    uint32: length in bytes of .wem file
} END FOR

DATA section

The DATA section contains the .wem files, not encoded, and immediately following each other. It is not recommended to read this section by itself but instead to immediately jump to the correct position based on the offset given in the DIDX or HIRC section.

44 41 54 41 -- DATA
uint32: length of section
FOR EACH (embedded .wem file) {
    byte[]: the .wem file with the length as given in the DIDX section,
            and starting with 52 49 46 46 -- RIFF.
} END FOR

ENVS section

The ENVS section (Environments?) section is yet to be analysed.

FXPR section

The FXPR section (Effects production?) section is yet to be analysed.

HIRC section

The HIRC section contains all the Wwise objects, including the events, the containers to group sounds, and the references to the sound files.

48 49 52 43 -- HIRC
uint32: length of section
uint32: number of objects
FOR EACH (object) {
   byte: single byte identifying type of object
   uint32: length of object section (= 4-byte id field and additional bytes)
   uint32: id of this object
   byte[]: additional bytes, depending on type of object and section length
} END FOR

Type #1: Settings

01 -- identifier for Settings section
uint32: length of this section
uint32: id of this Settings object
byte: number of settings
FOR EACH (setting) {
    byte: type of setting:
    00: Voice Volume
    03: Voice Low-pass Filter
} END FOR
FOR EACH (setting) {
    float: setting value
} END FOR
-- END OF SECTION --

Type #2: Sound SFX/Sound Voice

-- BEGINNING OF SECTION --
02 -- identifier for Sound SFX section
uint32: length of this section
uint32: id of this Sound SFX object
byte[4]: four unknown bytes
uint32: whether the sound is included in the SoundBank or streamed:
00: embedded in the SoundBank, not streamed
01: is streamed
02: is streamed, with Zero Latency (that is, the sound data is prefetched)
uint32: id of the audio file
uint32: id of the source:
            If this file is embedded, this will contain the SoundBank id as given in the STID section.
            If the file is being streamed, this number will be identical to the audio file id and can be used to find the .wem file to stream.
IF (file is embedded in a SoundBank) {
    uint32: offset to the position where the .wem sound file can be found in the SoundBank
    uint32: length in bytes of the .wem sound file in the SoundBank
} END IF
byte: type of Sound object:
00: Sound SFX
01: Sound Voice
byte[]: see section Sound structure
-- END OF SECTION --

Type #3: Event Action

03 -- identifier for Event Action section
uint32: length of this section
uint32: id of this Event Action object
byte: The Scope of this Event Action:
01: Game object: Switch or Trigger
02: Global
03: Game object: see referenced object id
04: Game object: State
05: All
09: All Except see referenced object id
byte: Action Type:
01: Stop
02: Pause
03: Resume
04: Play
05: Trigger
06: Mute
07: UnMute
08: Set Voice Pitch
09: Reset Voice Pitch
0A: Set Voice Volume
0B: Reset Voice Volume
0C: Set Bus Volume
0D: Reset Bus Volume
0E: Set Voice Low-pass Filter
0F: Reset Voice Low-pass Filter
10: Enable State
11: Disable State
12: Set State
13: Set Game Parameter
14: Reset Game Parameter
19: Set Switch
1A: Enable Bypass or Disable Bypass
1B: Reset Bypass Effect
1C: Break
1E: Seek
uint32: id of the game object that is referenced by this Event Action, or zero if there is no game object
byte: always 00
byte: number of additional parameters
FOR EACH (parameter) {
    byte: parameter type:
    0E: Delay, given as uint32 in milliseconds
    0F: Play: Fade in time, given as uint32 in milliseconds
    10: Probability, given as float
} END FOR
FOR EACH (parameter) {
    byte[]: parameter value, format depending on parameter type (see above)
} END FOR
byte: always 00
IF (Action Type == "Set State", 0x12) {
    uint32: State Group id
    uint32: State id
ELSE IF (Action Type == "Set Switch", 0x19) {
    uint32: Switch Group id
    uint32: Switch id
} END IF
-- END OF SECTION --

Type #4: Event

-- BEGINNING OF SECTION --
04 -- identifier for Event section
uint32: length of this section
uint32: id of this Event object
uint32: the number of Event Actions this Event has
FOR EACH (event action) {
    uint32: id of the Event Action
} END FOR
-- END OF SECTION --

Type #5: Random Container or Sequence Container

More information will follow.

Type #6: Switch Container

More information will follow.

Type #7: Actor-Mixer

More information will follow.

Type #8: Audio Bus

-- BEGINNING OF SECTION --
08 -- identifier for Audio Bus section
uint32: length of this section
uint32: id of this Audio Bus object
uint32: id of the parent Audio Bus object, or zero if it is the root (Master Audio Bus)
byte: the number of additional parameters
FOR EACH (additional parameter) {
    byte: parameter type:
    00 = Voice: Volume
    02 = Voice: Pitch
    03 = Voice: Low-pass filter
    04 = Bus: Volume
} END FOR
FOR EACH (additional parameter) {
    float: parameter value
} END FOR
byte: What to do when priority is equal:
00 = Discard oldest instance
01 = Discard newest instance
byte: What to do when limit is reached:
00 = Kill voice
01 = Use virtual voice settings
uint16: Limit sound instances to ...
boolean: whether to override parent settings for Playback Limit
uint32: unknown, always 3F 00 00 00 (= 63)
uint32: Auto-ducking: Recover time (ms)
float: Auto-ducking: Maximum ducking volume
uint32: Auto-ducking: Number of ducked busses
FOR EACH (ducked bus) {
    uint32: id of ducked Audio Bus object
    float: Volume of ducked bus
    uint32: Fade Out (ms) of ducked bus
    uint32: Fade In (ms) of ducked bus
    byte: shape of curve:
    00 = Logarithmic (Base 3)
    01 = Sine (Constant Power Fade In)
    02 = Logarithmic (Base 1.41)
    03 = Inverted S-Curve
    04 = Linear
    05 = S-Curve
    06 = Exponential (Base 1.41)
    07 = Sine (Constant Power Fade Out)
    08 = Exponential (Base 3)
    byte: Target:
    00: Voice Volume
    04: Bus Volume
} END FOR
byte: number of effects
IF (number of effects > 0) {
    byte: bit mask specifying which effects should be bypassed:
    0000 0001 = Bypass Effect 0
    0000 0010 = Bypass Effect 1
    0000 0100 = Bypass Effect 2
    0000 1000 = Bypass Effect 3
    0001 0000 = Bypass All
    FOR EACH (effect) {
        byte: effect index (00 to 03)
        uint32: id of Effect object
        byte[2]: two zero bytes
    } END FOR
} END IF
uint16: number of RTPCs
FOR EACH (RTPC) {
    uint32: id of Game Parameter on x-axis
    uint32: y-axis type:
    00 = Voice Volume
    03 = Voice Low-Pass Filter
    08 = Priority
    09 = Sound Instance Limit
    0F = User-Defined Auxiliary Sends Volume 0
    10 = User-Defined Auxiliary Sends Volume 1
    11 = User-Defined Auxiliary Sends Volume 2
    12 = User-Defined Auxiliary Sends Volume 3
    13 = Game-Defined Auxiliary Sends Volume
    16 = Output Bus Volume
    17 = Output Bus Low-pass Filter
    18 = Bypass Effect 0
    19 = Bypass Effect 1
    1A = Bypass Effect 2
    1B = Bypass Effect 3
    1C = Bypass All Effects
    1D = Motion Volume Offset
    1E = Motion Low Pass
    uint32: unknown id
    byte: unknown
    byte: number of points
    byte: unknown
    FOR EACH (point) {
        float: x-coordinate of point
        float: y-coordinate of point
        uint32: shape of curve following this point:
        00 = Logarithmic (Base 3)
        01 = Sine (Constant Power Fade In)
        02 = Logarithmic (Base 1.41)
        03 = Inverted S-Curve
        04 = Linear
        05 = S-Curve
        06 = Exponential (Base 1.41)
        07 = Sine (Constant Power Fade Out)
        08 = Exponential (Base 3)
        09 = Constant
    } END FOR
} END FOR
uint32: number of State Groups
FOR EACH (State Group) {
    uint32: id of State Group object
    byte: change occurs at: (only if it is Interactive Music, otherwise this is always zero)
    00 = Immediate
    01 = Next Grid
    02 = Next Bar
    03 = Next Beat
    04 = Next Cue
    05 = Custom Cue
    06 = Entry Cue
    07 = Exit Cue
    uint16: number of States where settings are different from default settings
    FOR EACH (State with custom settings) {
        uint32: id of State object
        uint32: id of object that contains the settings (see section type #1: Settings)
    } END FOR
} END FOR
-- END OF SECTION --

Type #9: Blend Container

More information will follow.

Type #10: Music Segment

A Music Segment is similar to a Music Track, it contains exactly one song. However, unlike the Music Tracks, a Music Segment can contain multiple audio files, for example one file for each instrument. In this case, all files are played simultaneously, but it is possible to for example mute a certain instrument in the middle of the song, or to otherwise control the volume of individual files.

0A -- identifier for Music Segment section
uint32: length of this section
uint32: id of this Music Segment object
byte[]: see section Sound structure
uint32: number of child objects
FOR EACH (child object) {
    uint32: id of child object
} END FOR
byte[]: unknown bytes

More information will follow.

Type #11: Music Track

A Music Track is the most basic Music object. For each audio file that you import, a Music Track is created. It contains information on where the track is stored. Each Music Track is contained inside one Music Segment, so when working with Containers, you can only use Segments as children, not Tracks. More information will follow.

Type #12: Music Switch Container

A Music Switch Container uses Switches or States to determine which music should be played. For example, a Switch Group could be activity, with possible states ranging from combat, stealth, exploration, rest, etc. The game could change the current value via a Set State or Set Switch Event. Depening on the currently set state, the game would either play the music container specified for combat, the container for stealth, and so on.

0C -- identifier for Music Switch Container section
uint32: length of this section
uint32: id of this Music Switch Container object
byte[]: see section Sound structure
uint32: number of children (Switch/Playlist Containers and Segments) that are part of this Switch container
FOR EACH (child) {
    uint32: id of child object
} END FOR
byte[4]: four zero bytes
float: unknown float
byte[8]: eight zero bytes
float: tempo (usually 120)
byte: time signature, part 1
byte: time signature, part 2 (usually 4/4)
byte: always 01
byte[4]: four zero bytes
uint32: number of Transitions (from Source to Destination)
FOR EACH (Transition) {
    uint32: id of Source object, or FF FF FF FF if Any, or 00 00 00 00 if Nothing
    uint32: id of Destination object, or FF FF FF FF if Any, or 00 00 00 00 if Nothing
    int32: Source Fade-out Time (ms)
    uint32: shape of Source Fade-out curve
    int32: Source Fade-out Offset (ms)
    uint32: Exit source at:
    00: Immediate
    01: Next Grid
    02: Next Bar
    03: Next Beat
    04: Next Cue
    05: New Custom Cue (see Match)
    07: Exit Cue
    note: Newer Wwise versions (2012.1+?) may include an additional uint32 field here: id of Match for "Next Custom Cue"
    byte: 00 = Nothing, FF = Play post-exit section of Source object
    int32: Destination Fade-in Time (ms)
    uint32: shape of Destination Fade-in curve
    int32: Destination Fade-in Offset (ms)
    uint32: id of Match for Custom Cue Filter, 00=Any
    uint32: if destination is a Playlist Container, this contains the id of the Playlist item to jump to, otherwise zero
    uint16: Sync to:
    00: Entry Cue
    01: Same Time as Playing Segment
    02: Random Cue
    03: Random Custom Cue (see Custom Cue Filter)
byte: 00 = Nothing, FF = Play pre-entry section of Destination object
    note: Newer Wwise versions (2012.1+?) may include an additional byte here for Custom Cue Filter: 01=Match source cue name, 00=Match ... (see above)
    boolean: whether the Transition has a Transition object specified
    uint32: id of the Transition object, or zero if no Transition object
    int32: Transition Fade-in Time (ms)
    uint32: shape of Transition Fade-in curve
    int32: Transition Fade-in Offset (ms)
    int32: Transition Fade-out Time (ms)
    uint32: shape of Transition Fade-out curve
    int32: Transition Fade-out Offset (ms)
    byte: 00 = Nothing, FF = Play pre-entry section of Transition object
    byte: 00 = Nothing, FF = Play post-exit section of Transition object
} END FOR
uint32: Switch Type:
00 00 00 00: The current switch of a Switch Group determines which music to play
01 00 00 00: The current state of a State Group determines which music to play
uint32: id of the Switch Group or State Group object
uint32: id of the default Switch/State, or 00 00 00 00 if None
boolean: whether to Continue to play on Switch change
uint32: number of Switches/States
FOR EACH (Switch or State) {
    uint32: id of the Switch/State
    uint32: id of the music object that should be played when this Switch/State is set
} END FOR
-- END OF SEGMENT --

Type #13: Music Playlist Container

The Playlist Container allows you to select a number of segments that should be played during a certain point in the game. Unlike the Music Segment which only contains one track, Playlists can contain multiple Segments that are played one after another. You can control in what order the segments are played. For example, you could choose that one of three segments from the A part should be played first, then a random track from the B part, and then to start over from the beginning. However, all the transitions from one music to the other have to be coded beforehand and it is not possible to change them during game. Instead, use a Switch container to for example stop playing all the peaceful music from the Playlist Container and start playing the combat music Playlist Container.

0D -- identifier for Music Playlist section
uint32: length of this section
uint32: id of this Music Segment object
byte[]: see section Sound structure
uint32: number of Music Segments that are part of this playlist
FOR EACH (Music Segment) {
    uint32: Music Segment id
} END FOR
byte[4]: four zero bytes
float: unknown float
byte[8]: eight zero bytes
float: tempo (usually 120)
byte: time signature, part 1
byte: time signature, part 2 (usually 4/4)
byte: always 01
byte[4]: four zero bytes
uint32: number of Transitions (from Source to Destination)
FOR EACH (Transition) {
    uint32: id of Source Music Segment, or FF FF FF FF if Any, or 00 00 00 00 if Nothing
    uint32: id of Destination Music Segment, or FF FF FF FF if Any, or 00 00 00 00 if Nothing
    int32: Source Fade-out Time (ms)
    uint32: shape of Source Fade-out curve
    int32: Source Fade-out Offset (ms)
    int32: unknown, always 7
    note: Newer Wwise versions (2012.1+?) may include an additional unknown int32 field here.
    byte: 00 = Nothing, FF = Play post-exit section of Source segment
    int32: Destination Fade-in Time (ms)
    uint32: shape of Destination Fade-in curve
    int32: Destination Fade-in Offset (ms)
    int32: unknown
    int32: unknown
    int16: unknown
    byte: 00 = Nothing, FF = Play pre-entry section of Destination segment
    note: Newer Wwise versions (2012.1+?) may include an additional unknown 00 zero byte here.
    boolean: whether the Transition has a Transition segment specified
    uint32: id of the Transition segment, or zero if no Transition segment
    int32: Transition Fade-in Time (ms)
    uint32: shape of Transition Fade-in curve
    int32: Transition Fade-in Offset (ms)
    int32: Transition Fade-out Time (ms)
    uint32: shape of Transition Fade-out curve
    int32: Transition Fade-out Offset (ms)
    byte: 00 = Nothing, FF = Play pre-entry section of Transition segment
    byte: 00 = Nothing, FF = Play post-exit section of Transition segment
} END FOR
uint32: number of Playlist elements (either Groups or Music Segments)
FOR EACH (Playlist elements) {
    uint32: id of the Music Segment, or zero if it is a Group
    uint32: id of this element, mostly used by the Wwise sound engine and not that important to know
    uint32: if it is a Group, this contains the number of child elements, otherwise it is zero
    int32: if it is a Group, this contains the playlist type:
    00 00 00 00: Sequence Continuous (play all the child elements, one after another)
    01 00 00 00: Sequence Step (play one of the child elements)
    02 00 00 00: Random Continuous (play all the child elements, in random order)
    03 00 00 00: Random Step (play one random child element)
    FF FF FF FF: this element is a Segment, not a Group
    uint16: Loop Count (usually 01 00)
    uint32: Weight * 1000, only needed for children of Random Groups (e.g., a weight of 50 would be encoded as 50,000)
    uint16: only for Random Groups: Avoid repeating a child track ... times in row
    byte: always 01
    byte: only for Random Groups: Random Type: 00 = Standard, 01 = Shuffle
} END FOR
-- END OF SECTION --

Note: The playlist elements themselves do not contain a field that tells you which element is the parent or which elements are children. Instead, after each Group element, the children are encoded in the file. When writing a file reader, I recommend a recursive programming style like the following:

function readElement(index, parent) {
  index++
  if (Element is a Group) {
    parent.add(playlist type, number of children)
    for each (child) {
      readElement(index++, this)
    }
  } else (Element is a Segment) {
    parent.add(segment id)
  }
}
readElement(0, root)

Type #14: Attenuation

More information will follow.

Type #15: Dialogue Event

More information will follow.

Type #16: Motion Bus

Only included if a Motion Device is activated under project settings. More information will follow.

Type #17: Motion FX

More information will follow.

Type #18: Effect

More information will follow.

Type #20: Auxiliary Bus

More information will follow.

Sound structure

This sound structure is used in a number of objects, which is why I put it in this separate section. boolean: whether to override parent settings for Effects section

byte: number of effects
IF (number of effects > 0) {
    byte: bit mask specifying which effects should be bypassed:
    0000 0001 = Bypass Effect 0
    0000 0010 = Bypass Effect 1
    0000 0100 = Bypass Effect 2
    0000 1000 = Bypass Effect 3
    0001 0000 = Bypass All
    FOR EACH (effect) {
        byte: effect index (00 to 03)
        uint32: id of Effect object
        byte[2]: two zero bytes
    } END FOR
} END IF
uint32: id of Output Bus, or 00 if Output Bus of parent object should be used
uint32: id of parent object
boolean: whether to override parent settings for Playback Priority section
boolean: whether the "Offset priority by ... at max distance" setting is activated
byte: number of additional parameters; they are only included if they are different from their default values
FOR EACH (additional parameter) {
    byte: type of parameter:
    00 = General Settings: Voice: Volume, float
    02 = General Settings: Voice: Pitch, float
    03 = General Settings: Voice: Low-pass filter, float
    05 = Advanced Settings: Playback Priority: Priority, float
    06 = Advanced Settings: Playback Priority: Offset priority by ... at max distance, float
    07: whether to Loop, given as uint32 = number of loops, or infinite if the value is 0
    08 = Motion: Audio to Motion Settings: Motion Volume Offset, float
    0B = Positioning: 2D: Panner X-coordinate, float
    0C = Positioning: 2D: Panner X-coordinate, float
    0D = Positioning: Center %, float
    12 = General Settings: User-Defined Auxiliary Sends: Bus #0 Volume, float
    13 = General Settings: User-Defined Auxiliary Sends: Bus #1 Volume, float
    14 = General Settings: User-Defined Auxiliary Sends: Bus #2 Volume, float
    15 = General Settings: User-Defined Auxiliary Sends: Bus #3 Volume, float
    16 = General Settings: Game-Defined Auxiliary Sends: Volume, float
    17 = General Settings: Output Bus: Volume, float
    18 = General Settings: Output Bus: Low-pass filter, float
} END FOR
FOR EACH (additional parameter) {
    byte[]: value of additional parameter, decoded based on the property type, see above
} END FOR
byte: unknown 00 zero byte
boolean: whether a Positioning section is included (01, if object overrides parent or it has no parent)
IF (Positioning section is included) {
    byte: 00 = 2D, 01 = 3D
    IF (Positioning = 2D) {
        boolean: whether to Enable Panner
    } ELSE IF (Positioning = 3D) {
        uint32: type of Position Source:
        02 = User-defined
        03 = Game-defined
        uint32: id of Attenuation object, if it exists, otherwise zero
        boolean: whether to Enable Spatialization
        IF (Position Source = User-defined, 0x02) {
            uint32: Play Type:
            00 = Sequence Step
            01 = Random Step
            02 = Sequence Continuous
            03 = Random Continuous
            04 = Sequence Step, Pick new path when sound starts
            05 = Random Step, Pick new path when sound starts
            boolean: whether to Loop (only when Play Type is Continuous, otherwise ignore value of this field)
            uint32: Transition time (ms) (only when Play Type is Continuous, otherwise ignore value of this field)
            boolean: whether to Follow Listener Orientation
        } ELSE IF (Position Source = Game-defined, 0x03) {
            boolean: whether to Update at each frame
        } END IF
    } END IF
} END IF
boolean: whether to override parent settings for Game-Defined Auxiliary Sends
boolean: whether to Use Game-Defined Auxiliary Sends
boolean: whether to override parent settings for User-Defined Auxiliary Sends
boolean: whether User-Defined Auxiliary Sends exist
IF (User-Defined Auxiliary Sends exist) {
    uint32: id of Auxiliary Bus 0
    uint32: id of Auxiliary Bus 1
    uint32: id of Auxiliary Bus 2
    uint32: id of Auxiliary Bus 3
} END IF
boolean: unknown parameter for Playback Limit section (note: this value may be bugged)
IF (unknown parameter) {
    byte: What to do when priority is equal:
    00 = Discard oldest instance
    01 = Discard newest instance
    byte: What to do when limit is reached:
    00 = Kill voice
    01 = Use virtual voice settings
    uint16: Limit sound instances to ...
} END IF
byte: How to limit sound instances:
00 = Per game object
01 = Globally
byte: Virtual voice behavior:
00 = Continue to play
01 = Kill voice
02 = Send to virtual voice
boolean: whether to override parent settings for Playback Limit section
boolean: whether to override parent settings for Virtual Voice section
uint32: number of State Groups
FOR EACH (State Group) {
    uint32: id of State Group object
    byte: change occurs at: (only if it is Interactive Music, otherwise this is always zero)
    00 = Immediate
    01 = Next Grid
    02 = Next Bar
    03 = Next Beat
    04 = Next Cue
    05 = Custom Cue
    06 = Entry Cue
    07 = Exit Cue
    uint16: number of States where settings are different from default settings
    FOR EACH (State with custom settings) {
        uint32: id of State object
        uint32: id of object that contains the settings (see section type #1: Settings)
    } END FOR
} END FOR
uint16: number of RTPCs (Real-time Parameter Controls)
FOR EACH (RTPC) {
    uint32: id of Game Parameter on x-axis
    uint32: y-axis type:
    00 = Voice Volume
    03 = Voice Low-Pass Filter
    08 = Priority
    09 = Sound Instance Limit
    0F = User-Defined Auxiliary Sends Volume 0
    10 = User-Defined Auxiliary Sends Volume 1
    11 = User-Defined Auxiliary Sends Volume 2
    12 = User-Defined Auxiliary Sends Volume 3
    13 = Game-Defined Auxiliary Sends Volume
    16 = Output Bus Volume
    17 = Output Bus Low-pass Filter
    18 = Bypass Effect 0
    19 = Bypass Effect 1
    1A = Bypass Effect 2
    1B = Bypass Effect 3
    1C = Bypass All Effects
    1D = Motion Volume Offset
    1E = Motion Low Pass
    uint32: unknown id
    byte: unknown
    byte: number of points
    byte: unknown
    FOR EACH (point) {
        float: x-coordinate of point
        float: y-coordinate of point
        uint32: shape of curve following this point:
        00 = Logarithmic (Base 3)
        01 = Sine (Constant Power Fade In)
        02 = Logarithmic (Base 1.41)
        03 = Inverted S-Curve
        04 = Linear
        05 = S-Curve
        06 = Exponential (Base 1.41)
        07 = Sine (Constant Power Fade Out)
        08 = Exponential (Base 3)
        09 = Constant
    } END FOR
} END FOR

STID section

The STID section (Sound Type ID?) section contains a list of all the SoundBanks referenced in the HIRC section (including the current SoundBank). In the HIRC section, only the SoundBank ids are given, so this section can be used to match an id with a SoundBank file name.

53 54 49 44 -- STID
uint32: length of section
uint32: unknown integer, always 01 00 00 00
uint32: number of SoundBanks
FOR EACH (SoundBank) {
    uint32: SoundBank id
    byte: length of SoundBank name
    char[]: String with given length, e.g. "music". Can be used to find the SoundBank file name: "music.bnk".
} END FOR

STMG section

The STMG section section can only be found in the Init.bnk SoundBank. It contains the project settings as well as the Switch Groups, State Groups and Game Parameters.

53 54 4D 47 -- STMG
uint32: length of section
float: Volume Threshold
uint16: Max Voice Instances
uint32: number of State Groups
FOR EACH (State Group) {
    uint32: id of State Group
    uint32: default transition time (ms)
    uint32: number of Custom Transition Times
    FOR EACH (Custom Transition Time) {
        uint32: id of "from" State
        uint32: id of "to" State
        uint32: transition time (ms)
    } END FOR
} END FOR
uint32: number of Switch Groups that set the current Switch based on a Game Parameter
FOR EACH (Switch Group) {
    uint32: id of Switch Group
    uint32: id of Game Parameter that determines currently set Switch
    uint32: number of points
    FOR EACH (point) {
        float: value of Game Parameter
        uint32: id of Switch that is set when Game Parameter >= given value
        uint32: shape of curve, always 09 = Constant
    } END FOR
    uint32: number of Game Parameters
    FOR EACH (Game Parameter) {
        uint32: id of Game Parameter
        float: default value of Game Parameter
    } END FOR
} END FOR
-- END OF SECTION --

Further information

You can get Wwise, free for personal use, at Audiokinetic.com, to generate custom SoundBank files and train your converter/reader. Also, I recommend watching the video tutorials, specifically:

  • Using the interface
  • Importing Audio Files
  • Building Sound Hierarchies
  • Creating Events
  • Building SoundBanks
  • Relation between Sound, Source and Audio File

Tools

References