Part I: FLP Format & Events#
FLP is a binary format used by Image-Line FL Studio, a music production software, to store project files. Instead of using C-style structs entirely, the FLP format has evolved from what once was a MIDI-like format to a really bad and messy combination of Type-length-value encoded “events” and structs.
Specification#
An FLP file contains of basically 2 sections or “chunks”, one is the header and other is the “data” section, which contains all the “events”.
Header chunk#
struct {
char magic[4]; // 'FLhd'
uint32_t size; // always been 6
int16_t format; // Internal file format
uint16_t num_channels; // Number of channels in channel rack
uint16_t ppq; // Pulses per quarter
}
class Header:
magic: str
size: int
format: int
num_channels: int
ppq: int
See also
Data chunk#
struct {
char magic[4]; // 'FLdt'
uint32_t size; // Total combined size of events
void* events; // Event data
}
Event#
An event can be thought of as a “flattened” dict
of attributes
composing a class. It can roughly be represented as:
struct {
uint8_t type;
void* value;
}
class Event:
type: int
value: object
Types#
There are basically 4 kinds of events depending on the range of type
:
Event ID |
Size of |
||
---|---|---|---|
0-63 |
1 byte |
1 + 1 = 2 |
|
64-127 |
2 bytes |
1 + 2 = 3 |
|
128-191 |
4 bytes |
1 + 4 = 5 |
|
192-255 |
Length prefixed |
>= 2 |
Note
Length prefixed events
These events store the length of the value
they contain after type
in a varint. It can be considered as the only true TLV encoded event type.
struct {
uint8_t type; // 192-255
uint8_t* length; // varint
void* value; // string, struct or subevent
}
It should be clearer by now how the FLP format is a misfit for the data it represents.
Representation#
Event IDs 0-191 are used for storing fixed size data like integers, floats and booleans. IDs from 192-255 are used for storing structs, subevents and strings.