17
edits
Changes
From Final Fantasy Inside
no edit summary
== Introduction ==
AKAO frames are sequence is the most complicated frames in part of the FF7 sound system. ("AKAO" is frame magicthe signature string, probably which implies that the sound format has developed by Minoru Akao, Square Enix sound programmer :) Minoru Akao.)
All files with exension *.SND are AKAO.
* '''MOVIE/OVER2.SND''' - same game over sequence, don't know, why to duplicate data
Other AKAO frames sequences are hard-wired in other files.
== AKAO frame structure File Structure ==
=== Header (size: 16 bytes) ===
struct AkaoHeaderAkaoSeqHeader
{
static const uint8_t magic[4]; // "AKAO" C-string aka frame *MAGIC* uint16_t id; // frame song ID, used for playing sequence uint16_t length; // frame data length - sizeof(header)
uint16_t reverb_type; // reverb type (range from 0 to 9)
struct AkaoTimeStamp timestamp; // creation time }; 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 Info (size: 4 bytes + 2 bytes * <channels count>) ===
struct AkaoChannelInfo
{
uint32_t mask; // represents bitmask of used channels in this framesong uint32_t uint16_t start_offsets[num_channels]; // offsets to channel opcode data
};
int num_channels = 0;
while (int bit = 0; bit < 24; bit++) if ((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 song. After this bitmask, 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.)
When a song uses a drum kit with [[FF7/PSX/Sound/Opcodes/0xeced|opcode 0xEC]], a drum instrument map table will be placed at the end of the sequence. The table determines the instrument, channel volume and pan for each keys.
== Example (homeHome-created Created AKAO frameSequence): ==
=== Header ===
'''41 4b 41 4f''' - AKAO string
'''34 12''' - frame song ID: 0x1234
'''16 00''' - frame data length 0x16 in hex or 22 in decimal
'''04 00''' - reverb type: 4 (large studio)
'''96 12 18 22 46 28''' - unknown datacreated at 1996-12-18 22:46:28
=== Channel info Info ===
'''01 00 00 00''' - this indicates, that used only one channel
=== Channel commands Commands ===
'''e8 a8 66''' - sets tempo, parameter 0x66a8
== Sound Opcode list List ==
{| class="wikitable"
|1
|
|The opcode indicates the note key and length. The note will be keyed off 2 ticks before the next note.
|-
|0x9A-0x9F
|Unimplemented
|n/a1|n/a
|Should not be used.
|-
|Load Instrument
|2
|instrument: byte(0-127)
|
|-
|-
|[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB4]]
|Vibrato (Channel Pitch LFO (Vibrato)
|4
|delay: byte, rate: byte, type: byte (0-15)
|When <code>rate</code> is 0, it will be translated to 256 ticks.
|-
|[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB5]]
|Channel Pitch LFO Vibrato Depth
|2
|depth: byte
|The most significant bit of the <code>depth</code> determines the amplitude range. When it is 0, the range is up to about ± 50 cents (amplitude is 15/256 compared with range type 1). When it is 1, the range is up to about ± 700 cents.
|-
|[[FF7/PSX/Sound/Opcodes/0xb4b5|0xB6]]
|Turn Off Channel Pitch LFOVibrato
|1
|
|-
|[[FF7/PSX/Sound/Opcodes/0xb8b9|0xB8]]
|Tremolo (Channel Volume LFO (Tremolo)
|4
|delay: byte, rate: byte, type: byte (0-15)
|When <code>rate</code> is 0, it will be translated to 256 ticks.
|-
|[[FF7/PSX/Sound/Opcodes/0xb8b9|0xB9]]
|Channel Volume LFO Tremolo Depth
|2
|depth: byte
|-
|[[FF7/PSX/Sound/Opcodes/0xb8b9|0xBA]]
|Turn Off Channel Volume LFOTremolo
|1
|
|2
|length_to_add: signed byte
|Ignore the regular length (delta-time) of subsequent notes and set to the fixed length. The length <code>length_to_add</code> parameter is a value based on will be added to the current lengthvalue. (default the initial value is 0)
|-
|[[FF7/PSX/Sound/Opcodes/0xdd|0xDD]]
|Channel Pitch LFO Vibrato Depth Slide
|3
|length: byte, depth: byte
|-
|[[FF7/PSX/Sound/Opcodes/0xde|0xDE]]
|Channel Volume LFO Tremolo Depth Slide
|3
|length: byte, depth: byte
|tempo: uint16
|bpm = tempo / 214.998204 (approximate)
More strictly, <code>bpm = 60.0 / (48 * (65536.0 / tempo) * (0x44E8 / (33868800.0 / 8)))</code>
Note that this coefficient is different from other games with PlayStation AKAO.
|-
|3
|drum_map_offset: signed int16
|The <code>drum_map_offset</code> is a relative offset pointing to the drum instrument map table that maps , which determines the instrument and articulation for each keys.
|-
|[[FF7/PSX/Sound/Opcodes/0xeced|0xED]]
|-
|[[FF7/PSX/Sound/Opcodes/0xf3|0xF3]]
|Use No Delay for Channel Pitch/Volume LFOUnknown
|1
|
|Specific to FF7. This instruction changes the interpretation of the 0xB4 and 0xB8 parameters. There is no actual use in music.
|-
|[[FF7/PSX/Sound/Opcodes/0xf4f5|0xF4]]
|-
|[[FF7/PSX/Sound/Opcodes/0xf4f5|0xF6]]
|Overlay Volume Balance of Overlay Voice
|2
|balance: byte (0-127)
|-
|[[FF7/PSX/Sound/Opcodes/0xf4f5|0xF7]]
|Overlay Volume Balance Slide of Overlay Voice
|3
|length: byte, balance: byte (0-127)
|[[FF7/PSX/Sound/Opcodes/0xfe|0xFE]]
|Measure Number
|23|measure: byteshort
|
|-