Difference between revisions of "FF7/PSX/Sound/AKAO sequence"
Line 145: | Line 145: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xa5|0xA6]] |
|Increase Octave | |Increase Octave | ||
|1 | |1 | ||
Line 151: | Line 151: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xa5|0xA7]] |
|Decrease Octave | |Decrease Octave | ||
|1 | |1 | ||
Line 187: | Line 187: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xAD]] |
|ADSR: Attack Rate | |ADSR: Attack Rate | ||
|2 | |2 | ||
Line 193: | Line 193: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xAE]] |
|ADSR: Decay Rate | |ADSR: Decay Rate | ||
|2 | |2 | ||
Line 199: | Line 199: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xAF]] |
|ADSR: Sustain Level | |ADSR: Sustain Level | ||
|2 | |2 | ||
Line 205: | Line 205: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xB0]] |
|ADSR: Decay Rate & Sustain Level | |ADSR: Decay Rate & Sustain Level | ||
|3 | |3 | ||
Line 211: | Line 211: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xB1]] |
|ADSR: Sustain Rate | |ADSR: Sustain Rate | ||
|2 | |2 | ||
Line 217: | Line 217: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xB2]] |
|ADSR: Release Rate | |ADSR: Release Rate | ||
|2 | |2 | ||
Line 223: | Line 223: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xB3]] |
|ADSR: Reset ADSR | |ADSR: Reset ADSR | ||
|1 | |1 | ||
Line 229: | Line 229: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB4]] |
|Channel Pitch LFO (Vibrato) | |Channel Pitch LFO (Vibrato) | ||
|4 | |4 | ||
Line 235: | Line 235: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB5]] |
|Channel Pitch LFO Depth | |Channel Pitch LFO Depth | ||
|2 | |2 | ||
Line 241: | Line 241: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB6]] |
|Turn Off Channel Pitch LFO | |Turn Off Channel Pitch LFO | ||
|1 | |1 | ||
Line 247: | Line 247: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xB7]] |
|ADSR: Attack Mode | |ADSR: Attack Mode | ||
|2 | |2 | ||
Line 253: | Line 253: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb8b9|0xB8]] |
|Channel Volume LFO (Tremolo) | |Channel Volume LFO (Tremolo) | ||
|4 | |4 | ||
Line 259: | Line 259: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb8b9|0xB9]] |
|Channel Volume LFO Depth | |Channel Volume LFO Depth | ||
|2 | |2 | ||
Line 265: | Line 265: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xb8b9|0xBA]] |
|Turn Off Channel Volume LFO | |Turn Off Channel Volume LFO | ||
|1 | |1 | ||
Line 271: | Line 271: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/ADSR|0xBB]] |
|ADSR: Sustain Mode | |ADSR: Sustain Mode | ||
|2 | |2 | ||
Line 277: | Line 277: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xbcbd|0xBC]] |
|Channel Pan LFO | |Channel Pan LFO | ||
|3 | |3 | ||
Line 283: | Line 283: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xbcbd|0xBD]] |
|Channel Pan LFO Depth | |Channel Pan LFO Depth | ||
|2 | |2 | ||
Line 289: | Line 289: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xbcbd|0xBE]] |
|Turn Off Channel Pan LFO | |Turn Off Channel Pan LFO | ||
|1 | |1 | ||
Line 301: | Line 301: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc0c1|0xC0]] |
|Channel Transpose (Absolute) | |Channel Transpose (Absolute) | ||
|2 | |2 | ||
Line 307: | Line 307: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc0c1|0xC1]] |
|Channel Transpose (Relative) | |Channel Transpose (Relative) | ||
|2 | |2 | ||
Line 313: | Line 313: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc2c3|0xC2]] |
|Turn On Reverb | |Turn On Reverb | ||
|1 | |1 | ||
Line 319: | Line 319: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc2c3|0xC3]] |
|Turn Off Reverb | |Turn Off Reverb | ||
|1 | |1 | ||
Line 325: | Line 325: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc4c5|0xC4]] |
|Turn On Noise | |Turn On Noise | ||
|1 | |1 | ||
Line 331: | Line 331: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc4c5|0xC5]] |
|Turn Off Noise | |Turn Off Noise | ||
|1 | |1 | ||
Line 337: | Line 337: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc6c7|0xC6]] |
|Turn On Frequency Modulation | |Turn On Frequency Modulation | ||
|1 | |1 | ||
Line 343: | Line 343: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc6c7|0xC7]] |
|Turn Off Frequency Modulation | |Turn Off Frequency Modulation | ||
|1 | |1 | ||
Line 349: | Line 349: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc8c9|0xC8]] |
|Loop Point | |Loop Point | ||
|1 | |1 | ||
Line 355: | Line 355: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc8c9|0xC9]] |
|Return to Loop Point Up to N Times | |Return to Loop Point Up to N Times | ||
|2 | |2 | ||
Line 361: | Line 361: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xc8c9|0xCA]] |
|Return to Loop Point | |Return to Loop Point | ||
|1 | |1 | ||
Line 373: | Line 373: | ||
|Reset sound effects such as noise, frequency modulation, reverb, overlay voice and alternate voice. | |Reset sound effects such as noise, frequency modulation, reverb, overlay voice and alternate voice. | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xcccd|0xCC]] |
|Turn On Legato | |Turn On Legato | ||
|1 | |1 | ||
| | | | ||
− | |This instruction will stop the key on and key off performance of the subsequent notes and update the pitch only. | + | |This instruction will stop the regular key on and key off performance of the subsequent notes and update the pitch only. |
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xcccd|0xCD]] |
|Turn Off Legato | |Turn Off Legato | ||
|1 | |1 | ||
Line 385: | Line 385: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xcecf|0xCE]] |
|Turn On Noise and Toggle Noise On/Off after a Period of Time | |Turn On Noise and Toggle Noise On/Off after a Period of Time | ||
|2 | |2 | ||
Line 391: | Line 391: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xcecf|0xCF]] |
|Toggle Noise On/Off after a Period of Time | |Toggle Noise On/Off after a Period of Time | ||
|2 | |2 | ||
Line 397: | Line 397: | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd0d1|0xD0]] |
− | | | + | |Turn On Full-Length Note Mode |
|1 | |1 | ||
− | | | + | |This instruction will stop the regular key off performance of the subsequent notes. |
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd0d1|0xD1]] |
− | | | + | |Turn Off Full-Length Note Mode |
|1 | |1 | ||
| | | | ||
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd2d3|0xD2]] |
− | | | + | |Turn On Frequency Modulation and Toggle Frequency Modulation On/Off after a Period of Time |
− | | | + | |2 |
− | | | + | |delay: byte |
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd2d3|0xD3]] |
− | | | + | |Toggle Frequency Modulation On/Off after a Period of Time |
− | | | + | |2 |
− | | | + | |delay: byte |
| | | | ||
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd4d5|0xD4]] |
− | | | + | |Turn On Playback Rate Duplication |
|1 | |1 | ||
| | | | ||
− | | | + | |Duplicate and use the playback frequency of the previous voice channel. |
|- | |- | ||
− | |[[FF7/PSX/Sound/Opcodes/ | + | |[[FF7/PSX/Sound/Opcodes/0xd4d5|0xD5]] |
− | | | + | |Turn Off Playback Rate Duplication |
|1 | |1 | ||
| | | |
Revision as of 06:50, 31 May 2020
Contents
Introduction
AKAO frames are most complicated frames in FF7 sound system. ("AKAO" is frame magic, probably developed by Minoru Akao, Square Enix sound programmer :) )
Frame is similar to MIDI sequence - it's custom tracker format for playing sequence sound, well tuned specially for PSX.
This frames are in all FF7 game modules: Field, Battle, Worldmap and in minigames.
All files with exension *.SND are AKAO.
- MINI/ASERI2.SND - Battle Arena theme
- MINI/SENSUI.SND - used in Submarine minigame
- ENEMY6/OVER2.SND - game over sequence
- ENEMY6/FAN2.SND - battle win "fanfare" sequence
- MOVIE/OVER2.SND - same game over sequence, don't know, why to duplicate data
Other AKAO frames are hard-wired in other files.
AKAO frame structure
Header (size: 16 bytes)
struct AkaoHeader { static const uint8_t magic[4]; // "AKAO" C-string aka frame *MAGIC* uint16_t id; // frame ID, used for playing sequence uint16_t length; // frame length - sizeof(header) uint16_t reverb_type; // reverb type (range from 0 to 9) struct AkaoTimeStamp { uint8_t year_bcd; // year (in binary coded decimal) uint8_t month_bcd; // month (in binary coded decimal, between 0x01 - 0x12) uint8_t day_bcd; // day (in binary coded decimal, between 0x01 - 0x31) uint8_t hours_bcd; // hours (in binary coded decimal, between 0x00 - 0x23) uint8_t minutes_bcd; // minutes (in binary coded decimal, between 0x00 - 0x59) uint8_t seconds_bcd; // seconds (in binary coded decimal, between 0x00 - 0x59) } timestamp; };
Channel info (size: 4 bytes + 2 bytes * <channels count>)
struct AkaoChannelInfo { uint32_t mask; // represents bitmask of used channels in this frame uint32_t start_offsets[num_channels]; // offsets to channel opcode data };
int num_channels = 0; while (int bit = 0; ((info.mask & 0xFFFFFF) & (1 << bit)) != 0; bit++) num_channels++;
First there is 32-bit number (offset 0x10), which represents bitmask of used channels in this frame.
After this frame, there is <channels count> offsets to channel opcode data counting from current offset. Each offsets is a relative offset based on the address *next to* the offset itself. (This is a general rule for early versions of AKAO to interpret relative offsets.)
Channel Commands [AKAO Opcodes]
Most complicated part.
For every channel in AKAO frame there is set of commands to perform. This is similar to Field opcodes. Here I'll call this sound commands "opcodes". Every opcode has it's own number of arguments (from no-arguments, to 3 arguments).
Example (home-created AKAO frame):
Header
41 4b 41 4f - AKAO string
34 12 - frame ID: 0x1234
16 00 - frame length 0x16 in hex or 22 in decimal
04 00 - reverb type: 4 (large studio)
96 12 18 22 46 28 - unknown data
Channel info
01 00 00 00 - this indicates, that used only one channel
00 00 - offset to first channel opcodes: in our example 0x00 means that next to this offset is opcodes for first channel
Channel commands
e8 a8 66 - sets tempo, parameter 0x66a8
ea 00 50 - sets reverb depth
a8 55 - load sample 0x55 from INSTR.ALL to channel
aa 40 - sets channel volume
c2 - turns on reverb effect
a1 0c - sets volume pan
c8 - sets loop point
66 - 0x66 % 11 = 3 (3 means to take 3rd number from play length table), 0x66 / 11 = 9 (9 means to take pitch[9] from loaded instrument record index)
ca - returns to saved loop point with opcode c8
This example plays Chocobo "Whoo-Hoo" (instrument number 0x55) repeatedly.
Sound Opcode list
Opcode | Summary | Length | Operands | Note |
---|---|---|---|---|
0xA0 | Finish Channel | 1 | ||
0xA1 | Load Instrument | 2 | instrument: byte | |
0xA2 | Overwrite Next Delta-Time Length | 2 | delta_time: byte | |
0xA3 | Channel Master Volume | 2 | volume: byte | |
0xA4 | Pitch Bend Slide | 3 | length: byte, semitones: signed byte | |
0xA5 | Set Octave | 2 | octave: byte | |
0xA6 | Increase Octave | 1 | ||
0xA7 | Decrease Octave | 1 | ||
0xA8 | Channel Volume | 2 | volume: byte | |
0xA9 | Channel Volume Slide | 3 | length: byte, volume: byte | |
0xAA | Channel Pan | 2 | pan: byte | 64 is the center |
0xAB | Channel Pan Slide | 3 | length: byte, pan: byte | |
0xAC | Noise Clock Frequency | 2 | clock: byte | |
0xAD | ADSR: Attack Rate | 2 | attack_rate: byte | |
0xAE | ADSR: Decay Rate | 2 | decay_rate: byte | |
0xAF | ADSR: Sustain Level | 2 | sustain_level: byte | |
0xB0 | ADSR: Decay Rate & Sustain Level | 3 | decay_rate: byte, sustain_level: byte | |
0xB1 | ADSR: Sustain Rate | 2 | sustain_rate: byte | |
0xB2 | ADSR: Release Rate | 2 | release_rate: byte | |
0xB3 | ADSR: Reset ADSR | 1 | ||
0xB4 | Channel Pitch LFO (Vibrato) | 4 | delay: byte, rate: byte, type: byte | |
0xB5 | Channel Pitch LFO Depth | 2 | depth: byte | |
0xB6 | Turn Off Channel Pitch LFO | 1 | ||
0xB7 | ADSR: Attack Mode | 2 | attack_mode: byte | |
0xB8 | Channel Volume LFO (Tremolo) | 4 | delay: byte, rate: byte, type: byte | |
0xB9 | Channel Volume LFO Depth | 2 | depth: byte | |
0xBA | Turn Off Channel Volume LFO | 1 | ||
0xBB | ADSR: Sustain Mode | 2 | sustain_mode: byte | |
0xBC | Channel Pan LFO | 3 | rate: byte, type: byte | |
0xBD | Channel Pan LFO Depth | 2 | depth: byte | |
0xBE | Turn Off Channel Pan LFO | 1 | ||
0xBF | ADSR: Release Mode | 2 | release_mode: byte | |
0xC0 | Channel Transpose (Absolute) | 2 | semitones: signed byte | |
0xC1 | Channel Transpose (Relative) | 2 | semitones: signed byte | |
0xC2 | Turn On Reverb | 1 | ||
0xC3 | Turn Off Reverb | 1 | ||
0xC4 | Turn On Noise | 1 | ||
0xC5 | Turn Off Noise | 1 | ||
0xC6 | Turn On Frequency Modulation | 1 | ||
0xC7 | Turn Off Frequency Modulation | 1 | ||
0xC8 | Loop Point | 1 | ||
0xC9 | Return to Loop Point Up to N Times | 2 | times: byte | |
0xCA | Return to Loop Point | 1 | ||
0xCB | Reset Sound Effects | 1 | Reset sound effects such as noise, frequency modulation, reverb, overlay voice and alternate voice. | |
0xCC | Turn On Legato | 1 | This instruction will stop the regular key on and key off performance of the subsequent notes and update the pitch only. | |
0xCD | Turn Off Legato | 1 | ||
0xCE | Turn On Noise and Toggle Noise On/Off after a Period of Time | 2 | delay: byte | |
0xCF | Toggle Noise On/Off after a Period of Time | 2 | delay: byte | |
0xD0 | Turn On Full-Length Note Mode | 1 | This instruction will stop the regular key off performance of the subsequent notes. | |
0xD1 | Turn Off Full-Length Note Mode | 1 | ||
0xD2 | Turn On Frequency Modulation and Toggle Frequency Modulation On/Off after a Period of Time | 2 | delay: byte | |
0xD3 | Toggle Frequency Modulation On/Off after a Period of Time | 2 | delay: byte | |
0xD4 | Turn On Playback Rate Duplication | 1 | Duplicate and use the playback frequency of the previous voice channel. | |
0xD5 | Turn Off Playback Rate Duplication | 1 | ||
0xD6 | 1 | |||
0xD7 | 1 | |||
0xD8 | 2 | |||
0xD9 | 2 | |||
0xDA | 2 | |||
0xDB | 1 | |||
0xDC | 2 | |||
0xDD | 3 | |||
0xDE | 3 | |||
0xDF | 3 | |||
0xE8 | Tempo | 3 | u16 tempo | |
0xE9 | 4 | |||
0xEA | Reverb Depth | 3 | u16 depth | |
0xEB | 4 | |||
0xEC | 3 | |||
0xED | 1 | |||
0xEE | 3 | |||
0xEF | 3 | |||
0xF0 | 4 | |||
0xF1 | 4 | |||
0xF2 | 2 | |||
0xF3 | 1 | |||
0xF4 | 3 | |||
0xF5 | 1 | |||
0xF6 | 2 | |||
0xF7 | 3 | |||
0xF8 | 2 | |||
0xF9 | 1 | |||
0xFA | ||||
0xFB | ||||
0xFC | 3 | |||
0xFD | 3 | |||
0xFE | 2 | |||
0xFF |