AGSC (File Format): Difference between revisions

Jump to navigation Jump to search
imported>Jackoalan
imported>Jackoalan
 
(40 intermediate revisions by 3 users not shown)
Line 1: Line 1:
'''AGSC''' is the sound effect format for Metroid Prime and Metroid Prime 2: Echoes. Each AGSC file contains a group of sound effects. The first two Metroid Prime games utilize the MusyX audio engine created by Factor5 and as a result, AGSC files are essentially just embedded MusyX files.  
'''AGSC''' is the sound effect format for Metroid Prime and Metroid Prime 2: Echoes. Each AGSC file contains a group of sound effects. The first two Metroid Prime games utilize the MusyX audio engine created by Factor5 and as a result, AGSC files are essentially just embedded MusyX files.  


The audio codec used in AGSC is the standard GameCube DSP ADPCM codec.
The audio codec used in AGSC is the standard GameCube DSP-ADPCM codec, but MusyX itself also offers uncompressed PCM as an option.


{{todo|Better descriptions for how SoundMacros work and a description for what each command does.}}
{{todo|Better descriptions for how SoundMacros work and a description for what each command does.}}
Line 23: Line 23:
| 0x0
| 0x0
| '''D'''
| '''D'''
| '''Audio Directory'''. Always "Audio/." Zero-terminated.
| '''Audio Directory'''. Always "Audio/". Zero-terminated.
|-
|-
| 0x0 + D
| 0x0 + D
Line 50: Line 50:
| 0x4 + D
| 0x4 + D
| 2
| 2
| {{unknown|Copy of '''first project unknown'''; 0xffff if empty}}
| '''Group ID'''; 0xFFFF if unspecified
|-
|-
| 0x6 + D
| 0x6 + D
Line 74: Line 74:
=== Pool ===
=== Pool ===


The Pool chunk contains tables for SoundMacros, ADSR, keymaps, and layers, if applicable. It starts with a 16-byte header before the different data tables begin.
The Pool chunk contains sub-chunk tables for SoundMacros, ADSR, keymaps, and layers, if applicable. It starts with a 16-byte header before the different data tables begin.


{| class="wikitable"
{| class="wikitable"
Line 100: Line 100:
| colspan=2 {{unknown|End of entry}}
| colspan=2 {{unknown|End of entry}}
|}
|}
==== ObjectID ====
After this are four tables of objects. Each object is identified with a 16-bit '''ObjectID'''.
Factor5 designed ObjectIDs to used in a polymorphic manner. The top 2 bits of the ID are used
to differentiate between SoundMacros, Keymaps, and Layers. If the ID passes a mask of 0x4000,
the object is a ''Keymap''. If the ID passes a mask of 0x8000, the object is a ''Layer''.
Otherwise, the object is assumed to be a ''SoundMacro''. ''Tables'' don't require this type of
polymorphism due to the context in which they are accessed.


==== SoundMacros ====
==== SoundMacros ====
Line 114: Line 124:
| 0x0
| 0x0
| 4
| 4
| '''SoundMacro size''' ''(note: includes the size value itself)''
| '''Chunk Size''' ''(note: includes the size value itself)''
|-
|-
| 0x4
| 0x4
| 2
| 2
| '''SoundMacro ID'''
| '''SoundMacro ObjectID'''
|-
|-
| 0x6
| 0x6
| 2
| 2
| {{unknown|'''Unknown'''; usually 0}}
| '''Padding'''
|-
|-
| 0x8
| 0x8
Line 433: Line 443:
|-
|-
| 0x29
| 0x29
| UNTRAP_EVENT
| Event
| colspan="2" {{unknown|}}
| colspan="2" {{unknown|}}
| colspan="2" {{unknown|}}
|-
| 0x2A
| SEND_MESSAGE
| SEND_MESSAGE
| IsVar
| IsVar
| colspan="2" | Macro
| colspan="2" | Macro
| VID
| VID
| Varibale
| Variable
| colspan="2" {{unknown|}}
| colspan="2" {{unknown|}}
|-
|-
| 0x2A
| 0x2B
| GET_MESSAGE
| GET_MESSAGE
| Varibale
| Variable
| colspan="6" {{unknown|}}
| colspan="6" {{unknown|}}
|-
|-
| 0x2B
| 0x2C
| GET_VID
| GET_VID
| Varibale
| Variable
| PLAY_MACRO
| PLAY_MACRO
| colspan="5" {{unknown|}}
| colspan="5" {{unknown|}}
Line 475: Line 492:
| colspan="5" {{unknown|}}
| colspan="5" {{unknown|}}
|-
|-
| 0x34
| 0x36
| SETPRIORITY
| SETPRIORITY
| Prio
| Prio
| colspan="6" {{unknown|}}
| colspan="6" {{unknown|}}
|-
|-
| 0x35
| 0x37
| ADDPRIORITY
| ADDPRIORITY
| {{unknown|}}
| {{unknown|}}
Line 486: Line 503:
| colspan="4" {{unknown|}}
| colspan="4" {{unknown|}}
|-
|-
| 0x36
| 0x38
| AGECNTSPEED
| AGECNTSPEED
| colspan="3" {{unknown|}}
| colspan="3" {{unknown|}}
| colspan="4" | Time
| colspan="4" | Time
|-
|-
| 0x37
| 0x39
| AGECNTVEL
| AGECNTVEL
| {{unknown|}}
| {{unknown|}}
Line 705: Line 722:
| colspan="2" | Immediate
| colspan="2" | Immediate
| {{unknown|}}
| {{unknown|}}
|-
| 0x65
| SET_VAR
| Ctrl
| A =
| colspan="1" {{unknown|}}
| colspan="2" | Immediate
| colspan="2" {{unknown|}}
|-
|-
| 0x70
| 0x70
Line 744: Line 769:
| 0x0
| 0x0
| 4
| 4
| '''Table size'''; (usually 0x10)
| '''Chunk Size'''
|-
|-
| 0x4
| 0x4
Line 754: Line 779:
| '''Padding'''
| '''Padding'''
|-
|-
| Varies
| Chunk Size
| colspan=2 {{Unknown|ADSR/Curve data}}
| colspan=2 {{Unknown|ADSR/Curve data}}
|}
|}


===== ADSR =====
===== ADSR =====
When the size of the table data is exactly 8, it may represent ADSR envelopes with this structure:
'''Note:''' All fields of the envelope are ''little endian''.


{| class="wikitable"
{| class="wikitable"
Line 766: Line 795:
|-
|-
| 0x0
| 0x0
| 1
| 2
| '''Attack time (0-255 milliseconds)'''; no multiplication is done to the value
| '''Attack time'''; in milliseconds
|-
| 0x2
| 2
| '''Decay time'''; in milliseconds
|-
| 0x4
| 2
| '''Sustain'''; percentage mapped between [0x0,0x1000]
|-
|-
| 0x1
| 0x6
| 1
| 2
| '''Attack time (0-65280 milliseconds)'''; multiply value by 256
| '''Release time'''; in milliseconds
|-
|-
| 0x2
| 0x8
| 1
| colspan=2 {{unknown|End of ADSR}}
| '''Decay time (0-255 milliseconds)''';  no multiplication is done to the value
|}
 
===== DLS ADSR =====
 
MusyX can also express more advanced envelopes using a modified [[wikipedia:DLS format|DLS]] representation.
This representation includes scaling coefficients to respond to played note and velocity
(so slamming down a key harder plays longer).
 
The attack and decay members are expressed in ''time-cents''. This may be converted to seconds using:
<code>2<sup>timecents / (1200.0 * 65536.0)</sup></code>
 
The attack and decay scale members are expressed as 0.1% increments in 16.16 fixed-point.
This may be converted to a normalized factor using:
<code>scale / (1000.0 * 65536.0)</code>
 
'''Note:''' All fields of the envelope are ''little endian''.
 
{| class="wikitable"
! Offset
! Size
! Description
|-
|-
| 0x3
| 0x0
| 1
| 4
| '''Decay time (0-65280 milliseconds)'''; multiply value by 256
| '''Attack time'''; in time-cents
|-
|-
| 0x4
| 0x4
| 1
| 4
| '''Sustain (percentage)'''; multiply value by 0.0244
| '''Decay time'''; in time-cents
|-
| 0x8
| 2
| '''Sustain'''; percentage mapped between [0x0,0x1000]
|-
|-
| 0x5
| 0xA
| 1
| 2
| '''Sustain (percentage)'''; multiply value by 6.25
| '''Release'''; in milliseconds
|-
|-
| 0x6
| 0xC
| 1
| 4
| '''Release time (0-255 milliseconds)'''; no multiplication is done to the value
| '''Velocity to Attack Scale'''; 0.1% increments as 16.16 fixed-point
|-
|-
| 0x7
| 0x10
| 1
| 4
| '''Release time (0-65280 milliseconds)'''; multiply value by 256
| '''Key to Decay Scale'''; 0.1% increments as 16.16 fixed-point
|-
|-
| 0x8
| 0x14
| colspan=2 {{unknown|End of entry}}
| colspan=2 {{unknown|End of DLS ADSR}}
|}
|}


===== Curves =====
===== Curves =====


To express a curve, the table data is simply a 128-element table of <code>uint8_t</code> values  
To express a volume curve, the table data is simply an arbitrarily-sized table of <code>uint8_t</code> values (although typically in MIDI range [0,127])


==== Keymaps ====
==== Keymaps ====
Line 818: Line 879:
| 0x0
| 0x0
| 4
| 4
| '''Keymap size'''; (usually 0x1032)
| '''Chunk Size'''; (usually 0x1032)
|-
|-
| 0x4
| 0x4
Line 828: Line 889:
| '''Padding'''
| '''Padding'''
|-
|-
| 0x1032
| Chunk Size
| colspan=2 {{Unknown|128 Keymap entries}}
| colspan=2 {{Unknown|128 Keymap entries}}
|}
|}
Line 872: Line 933:
| 0x0
| 0x0
| 4
| 4
| '''Layer size'''
| '''Chunk Size'''
|-
|-
| 0x4
| 0x4
Line 882: Line 943:
| '''Padding'''
| '''Padding'''
|-
|-
| Varies
| Chunk Size
| colspan=2 {{Unknown|Layer data}}
| colspan=2 {{Unknown|Layer data}}
|}
|}
Line 917: Line 978:
| 0x6
| 0x6
| 1
| 1
| '''Pan'''
| '''Priority Offset'''
|-
|-
| 0x7
| 0x7
| 1
| 1
| '''Priority Offset'''
| '''Surround Pan'''; (0: extreme forward, 64: center, 127: extreme rearward)
|-
|-
| 0x8
| 0x8
| 1
| 1
| '''Unknown'''; usually 0x40
| '''Pan'''; (0: extreme left, 64: center, 127: extreme right)
|-
|-
| 0xC
| 0xC
Line 936: Line 997:


The Project properties chunk contains values for the sounds, including priority, polyphony, volume, etc.
The Project properties chunk contains values for the sounds, including priority, polyphony, volume, etc.
Structurally, the Project is the root of the Audio Group tree, defining one or more ''Song Groups'' or ''SFX Groups''


{|class="wikitable"
{|class="wikitable"
Line 944: Line 1,007:
| 0x0
| 0x0
| 4
| 4
| '''Proj chunk size'''
| '''Group end offset''' (points to next group in project)
|-
|-
| 0x2
| 0x2
| 2
| 2
| {{unknown|'''Unknown'''}}
| '''Group ID'''
|-
|-
| 0x4
| 0x4
| 2
| 2
| '''Group ID'''; 0 for SongGroup (for use with [[CSNG (File Format)|CSNG]]), 1 for SFXGroup.
| '''Group Type'''; 0 for SongGroup (for use with [[CSNG (File Format)|CSNG]]), 1 for SFXGroup.
|-
|-
| 0x8
| 0x8
Line 976: Line 1,039:
| 0x1C
| 0x1C
| 4
| 4
| '''SoundMacro Settings Table offset'''
| '''Normal page table''' (SongGroup) / '''SFX table offset''' (SFXGroup)
|-
|-
| 0x20
| 0x20
| 4
| 4
| '''Unknown Table D offset''' ''(usually 0, indicating table is not present)''
| '''Drum page table offset''' (SongGroup)
|-
|-
| 0x24
| 0x24
| 4
| 4
| '''Unknown Table E offset''' ''(usually 0, indicating table is not present)''
| '''MIDI Setup table offset''' (SongGroup)
|-
|-
| 0x20
| 0x20
| colspan=2 {{unknown|End of proj header}}
| colspan=2 {{unknown|End of group header}}
|}
|}


Line 994: Line 1,057:
==== SoundMacro ID Table ====
==== SoundMacro ID Table ====


This is a table of shorts; there's no count value, so it's terminated with a value of 0xFFFF. It's a list of SoundMacro IDs present in the file. Occasionally there's gaps in the list; these gaps are signified by the top bit, 0x8000, being set on the size value preceding the gap.
This is a ranged-table of shorts; there's no count value, so it's terminated with a value of 0xFFFF. It's a list of SoundMacro IDs present in the file. Contiguous ranges are expressed by IDs with most-significant bit set (0x8000). The range begins on the marked ID and incrementally reaches the next ID in the list, including that ID. All other IDs are singular.
 
==== Sample ID / Table / Keymap / Layer Tables ====
 
These function the same way as the SoundMacro ID table, but indexes other types of entities instead.


==== Sample ID Table ====
'''Note:''' Keymap and Layer IDs in these tables have their top 2 bits (indicating their type) masked off.
Keymaps must be OR'd with 0x4000 and Layers must be OR'd with 0x8000 in order to reconstruct the actual IDs.


This functions the same way as the SoundMacro ID table, but it contains a list sample IDs instead.
==== Normal / Drum Page Entry ====


==== SoundMacro Settings ====
Used to map [https://www.midi.org/specifications/item/gm-level-1-sound-set General MIDI program numbers] (instruments)
to sound entities (macros, keymaps, layers)
 
{|class="wikitable"
! Offset
! Size
! Description
|-
| 0x0
| 2
| '''ObjectID'''
|-
| 0x2
| 1
| '''Priority'''; voices are limited, so priority is used to play more important sounds over others
|-
| 0x3
| 1
| '''Max number of voices'''
|-
| 0x4
| 1
| '''GM Program Number'''
|-
| 0x5
| 1
| '''Padding'''
|}
 
'''Note:''' The drum table is accessed when the MIDI channel is 10, otherwise the normal table is accessed.
 
==== SFX Entry ====
 
Used to map auto-generated <code>#define</code> IDs (used by game code) to sound entities (macros, keymaps, layers)


This table begins with a 16-bit count value, then 16 bits of padding. Each entry in the table is 10 bytes.
This table begins with a 16-bit count value, then 16 bits of padding. Each entry in the table is 10 bytes.
Line 1,011: Line 1,112:
| 0x0
| 0x0
| 2
| 2
| '''ID'''; referenced in [[EVNT]]
| '''DefineID'''; referenced by game code
|-
|-
| 0x2
| 0x2
| 2
| 2
| '''SoundMacro ID'''
| '''ObjectID'''
|-
|-
| 0x4
| 0x4
| 1
| 1
| '''Max number of voices'''
| '''Priority'''; voices are limited, so priority is used to play more important sounds over others
|-
|-
| 0x5
| 0x5
| 1
| 1
| '''Priority'''; voices are limited, so priority is used to play more important sounds over others
| '''Max number of voices'''
|-
|-
| 0x6
| 0x6
Line 1,034: Line 1,135:
|-
|-
| 0x8
| 0x8
| 2
| 1
| '''Definite Key'''; The default pitch (usually 0x3C00... the second byte may possibly be the MIDI channel)
| '''Definite Key'''; The default pitch - usually 0x3C (MIDI C4)
|-
| 0x9
| 1
| '''Padding'''
|}
 
==== MIDI Setup Entry ====
 
Table of fixed-length tables to map all 16 MIDI channels to program numbers
(in-turn resolving to sound entities via the page table).
 
Multiple MIDI Setups may be created to support Song data requiring totally different
banks of instruments.
 
Each MIDI Setup starts with a u16 '''MIDI-Setup-ID''', then 16-bits padding, then 16 entries of the following structure (one for each channel):
 
{|class="wikitable"
! Offset
! Size
! Description
|-
| 0x0
| 1
| '''Program Number'''
|-
| 0x1
| 1
| '''Volume'''
|-
| 0x2
| 1
| '''Panning'''
|-
| 0x3
| 1
| '''Reverb'''
|-
| 0x4
| 1
| '''Chorus'''
|}
|}
MIDI setups continue until the ''group end offset'' is reached.


=== Sample ===
=== Sample ===
Line 1,073: Line 1,216:
| 0xC
| 0xC
| 1
| 1
| '''Pitch'''; usually 0x3C. 0x3C is note C4 "Middle C" on the MIDI Keyboard. The keyboard notes are inverted - i.e., 0x48 is for note C3 and 0x30 is for note C5.
| '''Base Note'''; Corresponds to the MIDI note played in the sample, at the native sample-rate (which MusyX obtains from the INST chunk of .aiff files or SMPL chunk of .wav files, along with looping info). To play at a specified pitch in [[wikipedia:Cent (music)|cents]], set the playback sample rate using this formula: <code>sampleRate * 2<sup>((pitch - baseNote * 100) / 1200.0)</sup></code>
|-
|-
| 0xD
| 0xD
Line 1,084: Line 1,227:
|-
|-
| 0x10
| 0x10
| 4
| 1
| '''Audio format''' <ol start="0"><li>DSP-ADPCM</li><li>DSP-ADPCM (Drum Sample)</li><li>PCM</li><li>N64-VADPCM (Legacy Format)</li></ol>
|-
| 0x11
| 3
| '''Number of samples'''
| '''Number of samples'''
|-
|-
Line 1,142: Line 1,289:
== Tools ==
== Tools ==


* [https://drive.google.com/file/d/0B9MLV21H7SDvemgwN1daYnliSjA/view?usp=sharing Prime Audio Decoder] by Parax will dump all sound effects contained in a given AGSC file.
* [https://drive.google.com/file/d/0B9MLV21H7SDvemgwN1daYnliSjA/view?usp=sharing Prime Audio Decoder] by Aruki will dump all sound effects contained in a given AGSC file.


[[Category:File Formats]]
[[Category:File Formats]]
Anonymous user

Navigation menu