사용자:다메즈마/bnk포맷: 두 판 사이의 차이

(새 문서: 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 o...)
 
(문서를 비움)
태그: 문서를 비웠습니다. 문서 옮기기는 도구-옮기기를 이용하세요.
 
1번째 줄: 1번째 줄:
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 <tt>Play_EmotionalTheme</tt> event, which will play an emotional piece, as defined by the sound designer.
Each Wwise project contains an initialization SoundBank, <tt>Init.bnk</tt>. 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 <tt>.wem</tt> (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) -- see ''hcs64.com/vgm_ripping.html''. 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.
==General format==
*FOR EACH (section) {
**<tt>byte[4]</tt>: four-letter identifier of the section, e.g. <tt>BKHD</tt> or <tt>DIDX</tt>
**<tt>uint32</tt>: length of this section in bytes
**<tt>byte[]</tt>: 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 (<u>B</u>an<u>k</u> <u>H</u>ea<u>d</u>er) contains the version number and the SoundBank id.
*<tt>42 4B 48 44</tt> -- <tt>BKHD</tt>
*<tt>uint32</tt>: length of section
*<tt>uint32</tt>: version number of this SoundBank
*<tt>uint32</tt>: id of this SoundBank
*<tt>uint32</tt>: always zero
*<tt>uint32</tt>: always zero
==DIDX section==
The DIDX (<u>D</u>ata <u>I</u>n<u>d</u>e<u>x</u>) 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.
*<tt>44 49 44 58</tt> -- <tt>DIDX</tt>
*<tt>uint32</tt>: length of section
*FOR EACH (embedded .wem file) {
**<tt>uint32</tt>: .wem file id
**<tt>uint32</tt>: offset from start of DATA section
**<tt>uint32</tt>: 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.
*<tt>44 41 54 41</tt> -- <tt>DATA</tt>
*<tt>uint32</tt>: length of section
*FOR EACH (embedded .wem file) {
**<tt>byte[]</tt>: the .wem file with the length as given in the DIDX section, and starting with <tt>52 49 46 46</tt> -- <tt>RIFF</tt>.
*} 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.
Format:
*<tt>48 49 52 43</tt> -- <tt>HIRC</tt>
*<tt>uint32</tt>: length of section
*<tt>uint32</tt>: number of objects
*FOR EACH (object) {
**<tt>byte</tt>: single byte identifying type of object
**<tt>uint32</tt>: length of object section (= 4-byte id field and additional bytes)
**<tt>uint32</tt>: id of this object
**<tt>byte[]</tt>: additional bytes, depending on type of object and section length
*} END FOR
===type #1: Settings===
Format:
*<tt>01</tt> -- identifier for Settings section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Settings object
*<tt>byte</tt>: number of settings
*FOR EACH (setting) {
**<tt>byte</tt>: type of setting:
***<tt>00</tt>: Voice Volume
***<tt>03</tt>: Voice Low-pass Filter
*} END FOR
*FOR EACH (setting) {
**<tt>float</tt>: setting value
*} END FOR
-- END OF SECTION --
===type #2: Sound SFX/Sound Voice===
Format:
-- BEGINNING OF SECTION --
*<tt>02</tt> -- identifier for Sound SFX section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Sound SFX object
*<tt>byte[4]</tt>: four unknown bytes
*<tt>uint32</tt>: whether the sound is included in the SoundBank or streamed:
**<tt>00</tt>: embedded in the SoundBank, not streamed
**<tt>01</tt>: is streamed
**<tt>02</tt>: is streamed, with Zero Latency (that is, the sound data is prefetched)
*<tt>uint32</tt>: id of the audio file
*<tt>uint32</tt>: 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) {
*<tt>uint32</tt>: offset to the position where the .wem sound file can be found in the SoundBank
*<tt>uint32</tt>: length in bytes of the .wem sound file in the SoundBank
} END IF
*<tt>byte</tt>: type of Sound object:
**<tt>00</tt>: Sound SFX
**<tt>01</tt>: Sound Voice
*<tt>byte[]</tt>: see section [[#Sound structure|Sound structure]]
-- END OF SECTION --
===type #3: Event Action===
Format:
*<tt>03</tt> -- identifier for Event Action section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Event Action object
*<tt>byte</tt>: The Scope of this Event Action:
**<tt>01</tt>: Game object: Switch or Trigger
**<tt>02</tt>: Global
**<tt>03</tt>: Game object: ''see referenced object id''
**<tt>04</tt>: Game object: State
**<tt>05</tt>: All
**<tt>09</tt>: All Except ''see referenced object id''
*<tt>byte</tt>: Action Type:
**<tt>01</tt>: Stop
**<tt>02</tt>: Pause
**<tt>03</tt>: Resume
**<tt>04</tt>: Play
**<tt>05</tt>: Trigger
**<tt>06</tt>: Mute
**<tt>07</tt>: UnMute
**<tt>08</tt>: Set Voice Pitch
**<tt>09</tt>: Reset Voice Pitch
**<tt>0A</tt>: Set Voice Volume
**<tt>0B</tt>: Reset Voice Volume
**<tt>0C</tt>: Set Bus Volume
**<tt>0D</tt>: Reset Bus Volume
**<tt>0E</tt>: Set Voice Low-pass Filter
**<tt>0F</tt>: Reset Voice Low-pass Filter
**<tt>10</tt>: Enable State
**<tt>11</tt>: Disable State
**<tt>12</tt>: Set State
**<tt>13</tt>: Set Game Parameter
**<tt>14</tt>: Reset Game Parameter
**<tt>19</tt>: Set Switch
**<tt>1A</tt>: Enable Bypass or Disable Bypass
**<tt>1B</tt>: Reset Bypass Effect
**<tt>1C</tt>: Break
**<tt>1E</tt>: Seek
*<tt>uint32</tt>: id of the game object that is referenced by this Event Action, or zero if there is no game object
*<tt>byte</tt>: always 00
*<tt>byte</tt>: number of additional parameters
*FOR EACH (parameter) {
**<tt>byte</tt>: parameter type:
***<tt>0E</tt>: Delay, given as <tt>uint32</tt> in milliseconds
***<tt>0F</tt>: Play: Fade in time, given as <tt>uint32</tt> in milliseconds
***<tt>10</tt>: Probability, given as <tt>float</tt>
*} END FOR
*FOR EACH (parameter) {
**<tt>byte[]</tt>: parameter value, format depending on parameter type (see above)
*} END FOR
*<tt>byte</tt>: always 00
*IF (Action Type == "Set State", 0x12) {
**<tt>uint32</tt>: State Group id
**<tt>uint32</tt>: State id
*ELSE IF (Action Type == "Set Switch", 0x19) {
**<tt>uint32</tt>: Switch Group id
**<tt>uint32</tt>: Switch id
*} END IF
-- END OF SECTION --
More information will follow.
===type #4: Event===
Format:
-- BEGINNING OF SECTION --
*<tt>04</tt> -- identifier for Event section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Event object
*<tt>uint32</tt>: the number of Event Actions this Event has
*FOR EACH (event action) {
**<tt>uint32</tt>: 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 --
*<tt>08</tt> -- identifier for Audio Bus section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Audio Bus object
*<tt>uint32</tt>: id of the parent Audio Bus object, or zero if it is the root (Master Audio Bus)
*<tt>byte</tt>: the number of additional parameters
*FOR EACH (additional parameter) {
**<tt>byte</tt>: parameter type:
***<tt>00</tt> = Voice: Volume
***<tt>02</tt> = Voice: Pitch
***<tt>03</tt> = Voice: Low-pass filter
***<tt>04</tt> = Bus: Volume
*} END FOR
*FOR EACH (additional parameter) {
**<tt>float</tt>: parameter value
*} END FOR
*<tt>byte</tt>: What to do when priority is equal:
**<tt>00</tt> = Discard oldest instance
**<tt>01</tt> = Discard newest instance
*<tt>byte</tt>: What to do when limit is reached:
**<tt>00</tt> = Kill voice
**<tt>01</tt> = Use virtual voice settings
*<tt>uint16</tt>: Limit sound instances to ...
*<tt>boolean</tt>: whether to override parent settings for Playback Limit
*<tt>uint32</tt>: unknown, always <tt>3F 00 00 00</tt> (= 63)
*<tt>uint32</tt>: Auto-ducking: Recover time (ms)
*<tt>float</tt>: Auto-ducking: Maximum ducking volume
*<tt>uint32</tt>: Auto-ducking: Number of ducked busses
*FOR EACH (ducked bus) {
**<tt>uint32</tt>: id of ducked Audio Bus object
**<tt>float</tt>: Volume of ducked bus
**<tt>uint32</tt>: Fade Out (ms) of ducked bus
**<tt>uint32</tt>: Fade In (ms) of ducked bus
**<tt>byte</tt>: shape of curve:
****<tt>00</tt> = Logarithmic (Base 3)
****<tt>01</tt> = Sine (Constant Power Fade In)
****<tt>02</tt> = Logarithmic (Base 1.41)
****<tt>03</tt> = Inverted S-Curve
****<tt>04</tt> = Linear
****<tt>05</tt> = S-Curve
****<tt>06</tt> = Exponential (Base 1.41)
****<tt>07</tt> = Sine (Constant Power Fade Out)
****<tt>08</tt> = Exponential (Base 3)
**<tt>byte</tt>: Target:
***<tt>00</tt>: Voice Volume
***<tt>04</tt>: Bus Volume
*} END FOR
*<tt>byte</tt>: number of effects
*IF (number of effects > 0) {
**<tt>byte</tt>: bit mask specifying which effects should be bypassed:
***<tt>0000 0001</tt> = Bypass Effect 0
***<tt>0000 0010</tt> = Bypass Effect 1
***<tt>0000 0100</tt> = Bypass Effect 2
***<tt>0000 1000</tt> = Bypass Effect 3
***<tt>0001 0000</tt> = Bypass All
**FOR EACH (effect) {
***<tt>byte</tt>: effect index (<tt>00</tt> to <tt>03</tt>)
***<tt>uint32</tt>: id of Effect object
***<tt>byte[2]</tt>: two zero bytes
**} END FOR
*} END IF
*<tt>uint16</tt>: number of RTPCs
*FOR EACH (RTPC) {
**<tt>uint32</tt>: id of Game Parameter on x-axis
**<tt>uint32</tt>: y-axis type:
***<tt>00</tt> = Voice Volume
***<tt>03</tt> = Voice Low-Pass Filter
***<tt>08</tt> = Priority
***<tt>09</tt> = Sound Instance Limit
***<tt>0F</tt> = User-Defined Auxiliary Sends Volume 0
***<tt>10</tt> = User-Defined Auxiliary Sends Volume 1
***<tt>11</tt> = User-Defined Auxiliary Sends Volume 2
***<tt>12</tt> = User-Defined Auxiliary Sends Volume 3
***<tt>13</tt> = Game-Defined Auxiliary Sends Volume
***<tt>16</tt> = Output Bus Volume
***<tt>17</tt> = Output Bus Low-pass Filter
***<tt>18</tt> = Bypass Effect 0
***<tt>19</tt> = Bypass Effect 1
***<tt>1A</tt> = Bypass Effect 2
***<tt>1B</tt> = Bypass Effect 3
***<tt>1C</tt> = Bypass All Effects
***<tt>1D</tt> = Motion Volume Offset
***<tt>1E</tt> = 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:
****<tt>00</tt> = Logarithmic (Base 3)
****<tt>01</tt> = Sine (Constant Power Fade In)
****<tt>02</tt> = Logarithmic (Base 1.41)
****<tt>03</tt> = Inverted S-Curve
****<tt>04</tt> = Linear
****<tt>05</tt> = S-Curve
****<tt>06</tt> = Exponential (Base 1.41)
****<tt>07</tt> = Sine (Constant Power Fade Out)
****<tt>08</tt> = Exponential (Base 3)
****<tt>09</tt> = Constant
**} END FOR
*} END FOR
*<tt>uint32</tt>: number of State Groups
*FOR EACH (State Group) {
**<tt>uint32</tt>: id of State Group object
**<tt>byte</tt>: change occurs at: (only if it is Interactive Music, otherwise this is always zero)
***<tt>00</tt> = Immediate
***<tt>01</tt> = Next Grid
***<tt>02</tt> = Next Bar
***<tt>03</tt> = Next Beat
***<tt>04</tt> = Next Cue
***<tt>05</tt> = Custom Cue
***<tt>06</tt> = Entry Cue
***<tt>07</tt> = Exit Cue
**<tt>uint16</tt>: number of States where settings are different from default settings
**FOR EACH (State with custom settings) {
***<tt>uint32</tt>: id of State object
***<tt>uint32</tt>: id of object that contains the settings (see section [[#type #1: Settings|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.
*<tt>0A</tt> -- identifier for Music Segment section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Music Segment object
*<tt>byte[]</tt>: see section [[#Sound structure|Sound structure]]
*<tt>uint32</tt>: number of child objects
*FOR EACH (child object) {
**<tt>uint32</tt>: id of child object
*} END FOR
*<tt>byte[]</tt>: 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 <tt>activity</tt>, with possible states ranging from <tt>combat</tt>, <tt>stealth</tt>, <tt>exploration</tt>, <tt>rest</tt>, 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.
*<tt>0C</tt> -- identifier for Music Switch Container section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Music Switch Container object
*<tt>byte[]</tt>: see section [[#Sound structure|Sound structure]]
*<tt>uint32</tt>: number of children (Switch/Playlist Containers and Segments) that are part of this Switch container
*FOR EACH (child) {
**<tt>uint32</tt>: id of child object
*} END FOR
*<tt>byte[4]</tt>: four zero bytes
*<tt>float</tt>: unknown float
*<tt>byte[8]</tt>: eight zero bytes
*<tt>float</tt>: tempo (usually 120)
*<tt>byte</tt>: time signature, part 1
*<tt>byte</tt>: time signature, part 2 (usually 4/4)
*<tt>byte</tt>: always <tt>01</tt>
*<tt>byte[4]</tt>: four zero bytes
*<tt>uint32</tt>: number of Transitions (from Source to Destination)
*FOR EACH (Transition) {
**<tt>uint32</tt>: id of Source object, or <tt>FF FF FF FF</tt> if Any, or <tt>00 00 00 00</tt> if Nothing
**<tt>uint32</tt>: id of Destination object, or <tt>FF FF FF FF</tt> if Any, or <tt>00 00 00 00</tt> if Nothing
**<tt>int32</tt>: Source Fade-out Time (ms)
**<tt>uint32</tt>: shape of Source Fade-out curve
**<tt>int32</tt>: Source Fade-out Offset (ms)
**<tt>uint32</tt>: Exit source at:
***<tt>00</tt>: Immediate
***<tt>01</tt>: Next Grid
***<tt>02</tt>: Next Bar
***<tt>03</tt>: Next Beat
***<tt>04</tt>: Next Cue
***<tt>05</tt>: New Custom Cue (see Match)
***<tt>07</tt>: Exit Cue
**''note:'' Newer Wwise versions (2012.1+?) may include an additional <tt>uint32</tt> field here: id of Match for "Next Custom Cue"
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play post-exit section of Source object
**<tt>int32</tt>: Destination Fade-in Time (ms)
**<tt>uint32</tt>: shape of Destination Fade-in curve
**<tt>int32</tt>: Destination Fade-in Offset (ms)
**<tt>uint32</tt>: id of Match for Custom Cue Filter, <tt>00</tt>=Any
**<tt>uint32</tt>: if destination is a Playlist Container, this contains the id of the Playlist item to jump to, otherwise zero
**<tt>uint16</tt>: Sync to:
***<tt>00</tt>: Entry Cue
***<tt>01</tt>: Same Time as Playing Segment
***<tt>02</tt>: Random Cue
***<tt>03</tt>: Random Custom Cue (see Custom Cue Filter)
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = 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)
**<tt>boolean</tt>: whether the Transition has a Transition object specified
**<tt>uint32</tt>: id of the Transition object, or zero if no Transition object
**<tt>int32</tt>: Transition Fade-in Time (ms)
**<tt>uint32</tt>: shape of Transition Fade-in curve
**<tt>int32</tt>: Transition Fade-in Offset (ms)
**<tt>int32</tt>: Transition Fade-out Time (ms)
**<tt>uint32</tt>: shape of Transition Fade-out curve
**<tt>int32</tt>: Transition Fade-out Offset (ms)
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play pre-entry section of Transition object
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play post-exit section of Transition object
*} END FOR
*<tt>uint32</tt>: Switch Type:
**<tt>00 00 00 00</tt>: The current switch of a Switch Group determines which music to play
**<tt>01 00 00 00</tt>: The current state of a State Group determines which music to play
*<tt>uint32</tt>: id of the Switch Group or State Group object
*<tt>uint32</tt>: id of the default Switch/State, or <tt>00 00 00 00</tt> if None
*<tt>boolean</tt>: whether to Continue to play on Switch change
*<tt>uint32</tt>: number of Switches/States
*FOR EACH (Switch or State) {
**<tt>uint32</tt>: id of the Switch/State
**<tt>uint32</tt>: 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.
*<tt>0D</tt> -- identifier for Music Playlist section
*<tt>uint32</tt>: length of this section
*<tt>uint32</tt>: id of this Music Segment object
*<tt>byte[]</tt>: see section [[#Sound structure|Sound structure]]
*<tt>uint32</tt>: number of Music Segments that are part of this playlist
*FOR EACH (Music Segment) {
**<tt>uint32</tt>: Music Segment id
*} END FOR
*<tt>byte[4]</tt>: four zero bytes
*<tt>float</tt>: unknown float
*<tt>byte[8]</tt>: eight zero bytes
*<tt>float</tt>: tempo (usually 120)
*<tt>byte</tt>: time signature, part 1
*<tt>byte</tt>: time signature, part 2 (usually 4/4)
*<tt>byte</tt>: always <tt>01</tt>
*<tt>byte[4]</tt>: four zero bytes
*<tt>uint32</tt>: number of Transitions (from Source to Destination)
*FOR EACH (Transition) {
**<tt>uint32</tt>: id of Source Music Segment, or <tt>FF FF FF FF</tt> if Any, or <tt>00 00 00 00</tt> if Nothing
**<tt>uint32</tt>: id of Destination Music Segment, or <tt>FF FF FF FF</tt> if Any, or <tt>00 00 00 00</tt> if Nothing
**<tt>int32</tt>: Source Fade-out Time (ms)
**<tt>uint32</tt>: shape of Source Fade-out curve
**<tt>int32</tt>: Source Fade-out Offset (ms)
**<tt>int32</tt>: unknown, always 7
**''note:'' Newer Wwise versions (2012.1+?) may include an additional unknown <tt>int32</tt> field here.
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play post-exit section of Source segment
**<tt>int32</tt>: Destination Fade-in Time (ms)
**<tt>uint32</tt>: shape of Destination Fade-in curve
**<tt>int32</tt>: Destination Fade-in Offset (ms)
**<tt>int32</tt>: unknown
**<tt>int32</tt>: unknown
**<tt>int16</tt>: unknown
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play pre-entry section of Destination segment
**''note:'' Newer Wwise versions (2012.1+?) may include an additional unknown <tt>00</tt> zero byte here.
**<tt>boolean</tt>: whether the Transition has a Transition segment specified
**<tt>uint32</tt>: id of the Transition segment, or zero if no Transition segment
**<tt>int32</tt>: Transition Fade-in Time (ms)
**<tt>uint32</tt>: shape of Transition Fade-in curve
**<tt>int32</tt>: Transition Fade-in Offset (ms)
**<tt>int32</tt>: Transition Fade-out Time (ms)
**<tt>uint32</tt>: shape of Transition Fade-out curve
**<tt>int32</tt>: Transition Fade-out Offset (ms)
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play pre-entry section of Transition segment
**<tt>byte</tt>: <tt>00</tt> = Nothing, <tt>FF</tt> = Play post-exit section of Transition segment
*} END FOR
*<tt>uint32</tt>: number of Playlist elements (either Groups or Music Segments)
*FOR EACH (Playlist elements) {
**<tt>uint32</tt>: id of the Music Segment, or zero if it is a Group
**<tt>uint32</tt>: id of this element, mostly used by the Wwise sound engine and not that important to know
**<tt>uint32</tt>: if it is a Group, this contains the number of child elements, otherwise it is zero
**<tt>int32</tt>: if it is a Group, this contains the playlist type:
***<tt>00 00 00 00</tt>: Sequence Continuous (play all the child elements, one after another)
***<tt>01 00 00 00</tt>: Sequence Step (play one of the child elements)
***<tt>02 00 00 00</tt>: Random Continuous (play all the child elements, in random order)
***<tt>03 00 00 00</tt>: Random Step (play one random child element)
***<tt>FF FF FF FF</tt>: this element is a Segment, not a Group
**<tt>uint16</tt>: Loop Count (usually <tt>01 00</tt>)
**<tt>uint32</tt>: Weight * 1000, only needed for children of Random Groups (e.g., a weight of 50 would be encoded as 50,000)
**<tt>uint16</tt>: only for Random Groups: Avoid repeating a child track ... times in row
**<tt>byte</tt>: always <tt>01</tt>
**<tt>byte</tt>: only for Random Groups: Random Type: <tt>00</tt> = Standard, <tt>01</tt> = 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:
<pre>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)</pre>
===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.
*<tt>boolean</tt>: whether to override parent settings for Effects section
*<tt>byte</tt>: number of effects
*IF (number of effects > 0) {
**<tt>byte</tt>: bit mask specifying which effects should be bypassed:
***<tt>0000 0001</tt> = Bypass Effect 0
***<tt>0000 0010</tt> = Bypass Effect 1
***<tt>0000 0100</tt> = Bypass Effect 2
***<tt>0000 1000</tt> = Bypass Effect 3
***<tt>0001 0000</tt> = Bypass All
**FOR EACH (effect) {
***<tt>byte</tt>: effect index (<tt>00</tt> to <tt>03</tt>)
***<tt>uint32</tt>: id of Effect object
***<tt>byte[2]</tt>: two zero bytes
**} END FOR
*} END IF
*<tt>uint32</tt>: id of Output Bus, or <tt>00</tt> if Output Bus of parent object should be used
*<tt>uint32</tt>: id of parent object
*<tt>boolean</tt>: whether to override parent settings for Playback Priority section
*<tt>boolean</tt>: whether the "Offset priority by ... at max distance" setting is activated
*<tt>byte</tt>: number of additional parameters; they are only included if they are different from their default values
*FOR EACH (additional parameter) {
**<tt>byte</tt>: type of parameter:
***<tt>00</tt> = General Settings: Voice: Volume, <tt>float</tt>
***<tt>02</tt> = General Settings: Voice: Pitch, <tt>float</tt>
***<tt>03</tt> = General Settings: Voice: Low-pass filter, <tt>float</tt>
***<tt>05</tt> = Advanced Settings: Playback Priority: Priority, <tt>float</tt>
***<tt>06</tt> = Advanced Settings: Playback Priority: Offset priority by ... at max distance, <tt>float</tt>
***<tt>07</tt>: whether to Loop, given as <tt>uint32</tt> = number of loops, or infinite if the value is 0
***<tt>08</tt> = Motion: Audio to Motion Settings: Motion Volume Offset, <tt>float</tt>
***<tt>0B</tt> = Positioning: 2D: Panner X-coordinate, <tt>float</tt>
***<tt>0C</tt> = Positioning: 2D: Panner X-coordinate, <tt>float</tt>
***<tt>0D</tt> = Positioning: Center %, <tt>float</tt>
***<tt>12</tt> = General Settings: User-Defined Auxiliary Sends: Bus #0 Volume, <tt>float</tt>
***<tt>13</tt> = General Settings: User-Defined Auxiliary Sends: Bus #1 Volume, <tt>float</tt>
***<tt>14</tt> = General Settings: User-Defined Auxiliary Sends: Bus #2 Volume, <tt>float</tt>
***<tt>15</tt> = General Settings: User-Defined Auxiliary Sends: Bus #3 Volume, <tt>float</tt>
***<tt>16</tt> = General Settings: Game-Defined Auxiliary Sends: Volume, <tt>float</tt>
***<tt>17</tt> = General Settings: Output Bus: Volume, <tt>float</tt>
***<tt>18</tt> = General Settings: Output Bus: Low-pass filter, <tt>float</tt>
*} END FOR
*FOR EACH (additional parameter) {
**<tt>byte[]</tt>: value of additional parameter, decoded based on the property type, see above
*} END FOR
*<tt>byte</tt>: unknown <tt>00</tt> zero byte
*<tt>boolean</tt>: whether a Positioning section is included (<tt>01</tt>, if object overrides parent or it has no parent)
*IF (Positioning section is included) {
**<tt>byte</tt>: <tt>00</tt> = 2D, <tt>01</tt> = 3D
**IF (Positioning = 2D) {
***<tt>boolean</tt>: whether to Enable Panner
**} ELSE IF (Positioning = 3D) {
***<tt>uint32</tt>: type of Position Source:
****<tt>02</tt> = User-defined
****<tt>03</tt> = Game-defined
***<tt>uint32</tt>: id of Attenuation object, if it exists, otherwise zero
***<tt>boolean</tt>: whether to Enable Spatialization
***IF (Position Source = User-defined, 0x02) {
****<tt>uint32</tt>: Play Type:
*****<tt>00</tt> = Sequence Step
*****<tt>01</tt> = Random Step
*****<tt>02</tt> = Sequence Continuous
*****<tt>03</tt> = Random Continuous
*****<tt>04</tt> = Sequence Step, Pick new path when sound starts
*****<tt>05</tt> = Random Step, Pick new path when sound starts
****<tt>boolean</tt>: whether to Loop (only when Play Type is Continuous, otherwise ignore value of this field)
****<tt>uint32</tt>: Transition time (ms) (only when Play Type is Continuous, otherwise ignore value of this field)
****<tt>boolean</tt>: whether to Follow Listener Orientation
***} ELSE IF (Position Source = Game-defined, 0x03) {
****<tt>boolean</tt>: whether to Update at each frame
***} END IF
**} END IF
*} END IF
*<tt>boolean</tt>: whether to override parent settings for Game-Defined Auxiliary Sends
*<tt>boolean</tt>: whether to Use Game-Defined Auxiliary Sends
*<tt>boolean</tt>: whether to override parent settings for User-Defined Auxiliary Sends
*<tt>boolean</tt>: whether User-Defined Auxiliary Sends exist
*IF (User-Defined Auxiliary Sends exist) {
**<tt>uint32</tt>: id of Auxiliary Bus 0
**<tt>uint32</tt>: id of Auxiliary Bus 1
**<tt>uint32</tt>: id of Auxiliary Bus 2
**<tt>uint32</tt>: id of Auxiliary Bus 3
*} END IF
*<tt>boolean</tt>: unknown parameter for Playback Limit section (note: this value may be bugged)
*IF (unknown parameter) {
**<tt>byte</tt>: What to do when priority is equal:
***<tt>00</tt> = Discard oldest instance
***<tt>01</tt> = Discard newest instance
**<tt>byte</tt>: What to do when limit is reached:
***<tt>00</tt> = Kill voice
***<tt>01</tt> = Use virtual voice settings
**<tt>uint16</tt>: Limit sound instances to ...
*} END IF
*<tt>byte</tt>: How to limit sound instances:
**<tt>00</tt> = Per game object
**<tt>01</tt> = Globally
*<tt>byte</tt>: Virtual voice behavior:
**<tt>00</tt> = Continue to play
**<tt>01</tt> = Kill voice
**<tt>02</tt> = Send to virtual voice
*<tt>boolean</tt>: whether to override parent settings for Playback Limit section
*<tt>boolean</tt>: whether to override parent settings for Virtual Voice section
*<tt>uint32</tt>: number of State Groups
*FOR EACH (State Group) {
**<tt>uint32</tt>: id of State Group object
**<tt>byte</tt>: change occurs at: (only if it is Interactive Music, otherwise this is always zero)
***<tt>00</tt> = Immediate
***<tt>01</tt> = Next Grid
***<tt>02</tt> = Next Bar
***<tt>03</tt> = Next Beat
***<tt>04</tt> = Next Cue
***<tt>05</tt> = Custom Cue
***<tt>06</tt> = Entry Cue
***<tt>07</tt> = Exit Cue
**<tt>uint16</tt>: number of States where settings are different from default settings
**FOR EACH (State with custom settings) {
***<tt>uint32</tt>: id of State object
***<tt>uint32</tt>: id of object that contains the settings (see section [[#type #1: Settings|type #1: Settings]])
**} END FOR
*} END FOR
*<tt>uint16</tt>: number of RTPCs (Real-time Parameter Controls)
*FOR EACH (RTPC) {
**<tt>uint32</tt>: id of Game Parameter on x-axis
**<tt>uint32</tt>: y-axis type:
***<tt>00</tt> = Voice Volume
***<tt>03</tt> = Voice Low-Pass Filter
***<tt>08</tt> = Priority
***<tt>09</tt> = Sound Instance Limit
***<tt>0F</tt> = User-Defined Auxiliary Sends Volume 0
***<tt>10</tt> = User-Defined Auxiliary Sends Volume 1
***<tt>11</tt> = User-Defined Auxiliary Sends Volume 2
***<tt>12</tt> = User-Defined Auxiliary Sends Volume 3
***<tt>13</tt> = Game-Defined Auxiliary Sends Volume
***<tt>16</tt> = Output Bus Volume
***<tt>17</tt> = Output Bus Low-pass Filter
***<tt>18</tt> = Bypass Effect 0
***<tt>19</tt> = Bypass Effect 1
***<tt>1A</tt> = Bypass Effect 2
***<tt>1B</tt> = Bypass Effect 3
***<tt>1C</tt> = Bypass All Effects
***<tt>1D</tt> = Motion Volume Offset
***<tt>1E</tt> = 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:
****<tt>00</tt> = Logarithmic (Base 3)
****<tt>01</tt> = Sine (Constant Power Fade In)
****<tt>02</tt> = Logarithmic (Base 1.41)
****<tt>03</tt> = Inverted S-Curve
****<tt>04</tt> = Linear
****<tt>05</tt> = S-Curve
****<tt>06</tt> = Exponential (Base 1.41)
****<tt>07</tt> = Sine (Constant Power Fade Out)
****<tt>08</tt> = Exponential (Base 3)
****<tt>09</tt> = 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.
*<tt>53 54 49 44</tt> -- <tt>STID</tt>
*<tt>uint32</tt>: length of section
*<tt>uint32</tt>: unknown integer, always <tt>01 00 00 00</tt>
*<tt>uint32</tt>: number of SoundBanks
*FOR EACH (SoundBank) {
**<tt>uint32</tt>: SoundBank id
**<tt>byte</tt>: length of SoundBank name
**<tt>char[]</tt>: 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.
*<tt>53 54 4D 47</tt> -- <tt>STMG</tt>
*<tt>uint32</tt>: length of section
*<tt>float</tt>: Volume Threshold
*<tt>uint16</tt>: Max Voice Instances
*<tt>uint32</tt>: number of State Groups
*FOR EACH (State Group) {
**<tt>uint32</tt>: id of State Group
**<tt>uint32</tt>: default transition time (ms)
**<tt>uint32</tt>: number of Custom Transition Times
**FOR EACH (Custom Transition Time) {
***<tt>uint32</tt>: id of "from" State
***<tt>uint32</tt>: id of "to" State
***<tt>uint32</tt>: transition time (ms)
**} END FOR
*} END FOR
*<tt>uint32</tt>: number of Switch Groups that set the current Switch based on a Game Parameter
*FOR EACH (Switch Group) {
**<tt>uint32</tt>: id of Switch Group
**<tt>uint32</tt>: id of Game Parameter that determines currently set Switch
**<tt>uint32</tt>: 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 <tt>09</tt> = Constant
*} END FOR
*<tt>uint32</tt>: number of Game Parameters
*FOR EACH (Game Parameter) {
**<tt>uint32</tt>: id of Game Parameter
**<tt>float</tt>: default value of Game Parameter
*} 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 at ''www.audiokinetic.com/en/resources/videos'', specifically:
*Using the interface
*Importing Audio Files
*Building Sound Hierarchies
*Creating Events
*Building SoundBanks
*Relation between Sound, Source and Audio File

2015년 8월 8일 (토) 22:39 기준 최신판