AGSC (File Format): Difference between revisions
Jump to navigation
Jump to search
→Normal / Drum Page Entry
imported>Jackoalan |
imported>Jackoalan |
||
(24 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/. | | '''Audio Directory'''. Always "Audio/". Zero-terminated. | ||
|- | |- | ||
| 0x0 + D | | 0x0 + D | ||
Line 103: | Line 103: | ||
==== ObjectID ==== | ==== ObjectID ==== | ||
After this are four tables of objects. Each object is identified with a 16-bit '''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 508: | Line 492: | ||
| colspan="5" {{unknown|}} | | colspan="5" {{unknown|}} | ||
|- | |- | ||
| | | 0x36 | ||
| SETPRIORITY | | SETPRIORITY | ||
| Prio | | Prio | ||
| colspan="6" {{unknown|}} | | colspan="6" {{unknown|}} | ||
|- | |- | ||
| | | 0x37 | ||
| ADDPRIORITY | | ADDPRIORITY | ||
| {{unknown|}} | | {{unknown|}} | ||
Line 519: | Line 503: | ||
| colspan="4" {{unknown|}} | | colspan="4" {{unknown|}} | ||
|- | |- | ||
| | | 0x38 | ||
| AGECNTSPEED | | AGECNTSPEED | ||
| colspan="3" {{unknown|}} | | colspan="3" {{unknown|}} | ||
| colspan="4" | Time | | colspan="4" | Time | ||
|- | |- | ||
| | | 0x39 | ||
| AGECNTVEL | | AGECNTVEL | ||
| {{unknown|}} | | {{unknown|}} | ||
Line 738: | 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 794: | Line 786: | ||
When the size of the table data is exactly 8, it may represent ADSR envelopes with this structure: | 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 801: | Line 795: | ||
|- | |- | ||
| 0x0 | | 0x0 | ||
| | | 2 | ||
| '''Attack time | | '''Attack time'''; in milliseconds | ||
|- | |||
| 0x2 | |||
| 2 | |||
| '''Decay time'''; in milliseconds | |||
|- | |||
| 0x4 | |||
| 2 | |||
| '''Sustain'''; percentage mapped between [0x0,0x1000] | |||
|- | |- | ||
| | | 0x6 | ||
| | | 2 | ||
| ''' | | '''Release time'''; in milliseconds | ||
|- | |- | ||
| | | 0x8 | ||
| | | colspan=2 {{unknown|End of ADSR}} | ||
| ''' | |} | ||
===== 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 | |||
|- | |- | ||
| | | 0x0 | ||
| | | 4 | ||
| ''' | | '''Attack time'''; in time-cents | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
| | | 4 | ||
| '''Sustain | | '''Decay time'''; in time-cents | ||
|- | |||
| 0x8 | |||
| 2 | |||
| '''Sustain'''; percentage mapped between [0x0,0x1000] | |||
|- | |- | ||
| | | 0xA | ||
| | | 2 | ||
| ''' | | '''Release'''; in milliseconds | ||
|- | |- | ||
| | | 0xC | ||
| | | 4 | ||
| ''' | | '''Velocity to Attack Scale'''; 0.1% increments as 16.16 fixed-point | ||
|- | |- | ||
| | | 0x10 | ||
| | | 4 | ||
| ''' | | '''Key to Decay Scale'''; 0.1% increments as 16.16 fixed-point | ||
|- | |- | ||
| | | 0x14 | ||
| colspan=2 {{unknown|End of | | colspan=2 {{unknown|End of DLS ADSR}} | ||
|} | |} | ||
===== Curves ===== | ===== Curves ===== | ||
To express a volume curve, the table data is simply an arbitrarily-sized 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 952: | Line 978: | ||
| 0x6 | | 0x6 | ||
| 1 | | 1 | ||
| ''' | | '''Priority Offset''' | ||
|- | |- | ||
| 0x7 | | 0x7 | ||
| 1 | | 1 | ||
| ''' | | '''Surround Pan'''; (0: extreme forward, 64: center, 127: extreme rearward) | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
| 1 | | 1 | ||
| ''' | | '''Pan'''; (0: extreme left, 64: center, 127: extreme right) | ||
|- | |- | ||
| 0xC | | 0xC | ||
Line 1,031: | 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. | 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 ==== | ==== Sample ID / Table / Keymap / Layer Tables ==== | ||
These function the same way as the SoundMacro ID table, but indexes other types of entities instead. | 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 ==== | ==== Normal / Drum Page Entry ==== | ||
Line 1,067: | Line 1,096: | ||
| '''Padding''' | | '''Padding''' | ||
|} | |} | ||
'''Note:''' The drum table is accessed when the MIDI channel is 10, otherwise the normal table is accessed. | |||
==== SFX Entry ==== | ==== SFX Entry ==== | ||
Line 1,104: | Line 1,135: | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
| | | 1 | ||
| '''Definite Key'''; The default pitch ( | | '''Definite Key'''; The default pitch - usually 0x3C (MIDI C4) | ||
|- | |||
| 0x9 | |||
| 1 | |||
| '''Padding''' | |||
|} | |} | ||
Line 1,116: | Line 1,151: | ||
banks of instruments. | banks of instruments. | ||
Each MIDI Setup starts with a | 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" | {|class="wikitable" | ||
Line 1,181: | Line 1,216: | ||
| 0xC | | 0xC | ||
| 1 | | 1 | ||
| ''' | | '''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,192: | Line 1,227: | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
| | | 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,250: | Line 1,289: | ||
== Tools == | == Tools == | ||
* [https://drive.google.com/file/d/0B9MLV21H7SDvemgwN1daYnliSjA/view?usp=sharing Prime Audio Decoder] by | * [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]] |