AGSC (File Format)

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, but MusyX itself also offers uncompressed PCM as an option.

Format
The AGSC format is essentially four data chunks combined into one resource, each of which is a standard MusyX file. Of the four data chunks (pool, proj, samp, and sdir), there's one for sound engine scripts, one for sound properties, one for actual ADPCM sound data, and one for sound metadata. The main difference between Prime 1 and 2 is the header, and some slight changes in the way the four chunks are organized. In Metroid Prime, each chunk begins with its own size value; in Metroid Prime 2, every chunk instead has its size listed at the beginning of the file, at the end of the header. In addition, in Metroid Prime, the third chunk is samp, and the fourth is sdir; in Metroid Prime 2, it's the other way around.

Pool
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.

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
The first Pool table denotes MusyX's SoundMacros, small scripts that apply various effects on the sounds in the game. Each macro is composed of a header followed by a number of commands; each command specifies its type through a single-byte command ID, then specifies the parameters of that particular command, which vary.

The header of each SoundMacro is eight bytes, and is structured as follows:

On the commands, each 4 bytes were originally little endian, but have been swapped to big endian in the AGSC files (despite not being longs). To read the data as originally formatted, every four bytes needs to be byte-swapped. Each command is 8 bytes, and is structured as follows:

The SoundMacro will continue with commands until it terminates when the END command is executed. The command ID for END is 0 and has null command arguments; the next SoundMacro begins after reading it.

These are the possible commands:

After the last soundmacro, the table terminated by a value of 0xFFFF.

Tables
Tables have two functions: for defining curves for volume scaling, or to be used as ADSR envelopes.

The tables continue until 0xffffffff terminator is reached.

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.

DLS ADSR
MusyX can also express more advanced envelopes using a modified 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:

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:

Note: All fields of the envelope are little endian.

Curves
To express a volume curve, the table data is simply an arbitrarily-sized table of  values (although typically in MIDI range [0,127])

Keymaps
Keymaps are swappable, fixed-length tables mapping 128 MIDI keys to sound-producing objects.

The keymaps continue until 0xffffffff terminator is reached.

Layers
Layers are one-to-many, ranged keyboard mappings to sound-producing objects.

The layers continue until 0xffffffff terminator is reached.

Layer Data
Within the layer data, there is a u32 count of layer range structs:

The entire Pool chunk is terminated by a value of 0xFFFF.

Project
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

After the header are a number of data tables.

SoundMacro ID Table
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.

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.

Normal / Drum Page Entry
Used to map General MIDI program numbers (instruments) to sound entities (macros, keymaps, layers)

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  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.

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):

MIDI setups continue until the group end offset is reached.

Sample
The Sample chunk is all the sound data encoded using the standard Gamecube DSP ADPCM codec. It can be decoded the same way as a DSP file. Each sound's size is padded to 32 bytes before the next sound's data begins.

Sample Directory
The Sample Directory chunk (chunk 4 in Metroid Prime, chunk 3 in Metroid Prime 2) is made up of two sets of tables. The structure of both these tables is identical between both games.

Table A
The first metadata table has one entry per sound, and is terminated with 0xFFFFFFFF; since there's no known sound count anywhere in the file, the only way to read this correctly is to read until you reach the terminator value. Each entry is 0x20 bytes long.

Table B
These are accessed through the offsets in table A's entries; note that it might not match the sound count, because the same entry in this table can be used with multiple sounds. Each entry is 0x28 bytes long.

Tools

 * Prime Audio Decoder by Aruki will dump all sound effects contained in a given AGSC file.