Me and Zidane_2 were reverse-engeneering AKAO sequence format for ff7.
*******************************
**********SEQUENCE**********
*******************************
AKAO sequence format consists of following sections:
1. Header:
struct AkaoHeader
{
uint8_t magic[4]; // string "AKAO"
uint16_t id; // AKAO frame ID
uint16_t length; // frame length - sizeof(header)
uint16_t unused1; // unused data in AKAO parser code
uint32_t unused2; // unused data in AKAO parser code
uint8_t unused3; // unused data in AKAO parser code
uint8_t unused4; // unused data in AKAO parser code
};
2. Channels info:
uint32_t with used only 24-bit - mask for used SPU channels (example: 0x00000003 - 11b, 11b means that there is only channel 1 & channel 2)
3. Array of N uint16_t offsets to channel sequence data, where N is channel count. Every channel offset counts from position of this offset number in AKAO frame.
4. Sequence data:
After array of pointers there is sequence data for every enabled channel.
For any channel there is only one sample that are playing using 14 different tones and configuration.
Sequence data consists of SPU "configuration" section and "stream" section.
Configuration section consists of random 1-byte control bytes with parameters (we can say, that "control byte" is "sound opcode"). Every opcode has it's own number of parameters. Every opcode constant is > then A0. Processing of opcodes is finished, when AKAO parser finds byte < A0. This byte and following bytes to the end of channel data is "stream" section. Stream section format isn't fully understood for now, but we are working on it
. There is timing, tone and length information for playing a sample. As we see later, all sample has 14 "tones" for playing. If any byte of the stream section is < 14 * 0x0b it selects length and tone for loaded sample, maybe something else.
Example:
***** MAIN INFO *****
Filename: sensui.snd
Frame ID: 0x59
Frame Length: 44 bytes
Unknown Data 1:0x04
Unknown Data 2:0x22181296
Unknown Data 3:0x46
Unknown Data 4:0x28
Channels count: 2
***** CHANNELS INFO *****
Channel 0:
Length: 0x13
e8 a8 66 [(?Tempo) Parameter: 0x66a8]
ea 00 50 [Parameter: 0x5000]
SPU Right Reverb depth: 0x5000
SPU Left Reverb depth: 0x5000
a8 0d [Volume A8 modifier: 0x0d]
aa 40 [Volume AA modifier: 0x40]
SPU Right volume: 0x0339
SPU Left volume: 0x032c
c2
a1 0c [sample number]
a5 03
c8
stream data:
66 96 ca
Channel 1:
Length: 0x11
aa 40 [Volume AA modifier: 0x40]
a8 11 [Volume A8 modifier: 0x11]
SPU Right volume: 0x0437
SPU Left volume: 0x0426
c2
c6
a1 15 [sample number]
a5 05
c8
stream data:
66 96 ca 00 00 00
*******************************
**********INSTRx.DAT**********
*******************************
This file contains data for each sample in INSTRx.ALL
struct SampleIndex
{
uint32_t attack_offset; // offset to begin of "attack" part of sample (actually for INSTR.ALL real offset is: attack_offset - 0xff0)
uint32_t loop_offset; // offset to begin of "loop?" part of sample (actually for INSTR.ALL real offset is: loop_offset - 0xff0)
uint16_t parameters[4]; // unknown for now
uint32_t tones[12]; // possible "tone" constants for sample
};
Also I want to welcome a new developer Zidane_2 to Q-Gears! He is a great help in reverse-engeneering of AKAO format. He is a fan of FF9, so maybe FF9 support in the future, hehe
P.S. If anyone has a time - clean up this info and add it to the Wiki.