The data chunk is a list of events, one after another with nothing between them. Each event is one ID byte and a value. The ID says what the value means and also how big it is, so a reader can step over any event, including ones it does not recognise. In these files one event, 172, breaks that rule; see Event 172.
Size classes
The ID byte falls into one of five ranges. The range sets the size of the value.
| IDs | Class | Value |
|---|---|---|
| 0x00 (0) to 0x3F (63) | Byte | 1 byte |
| 0x40 (64) to 0x7F (127) | Word | 2 bytes, little-endian |
| 0x80 (128) to 0xBF (191) | Dword | 4 bytes, little-endian |
| 0xC0 (192) to 0xCF (207) | Text | a variable-length size, then that many bytes of text |
| 0xD0 (208) to 0xFF (255) | Data | a variable-length size, then that many bytes of data |
Three IDs in the data range hold text: 231 (display group name), 239 (track name) and 241 (arrangement name). They were added after the text range was full. They are stored exactly like data events, so the size rule still holds.
Event 172
Event 172 (0xAC) breaks the size rule. It has been seen in files from
FL Studio 2025 and 2026: a proposed change to PyFLP (pull
request 208) was tested on files from 26.1.6. Its ID is in the dword range (128 to
191), so by the rule it carries four bytes, but it carries fewer. A reader that takes
four bytes loses its place in the stream and misreads everything after it: the pull
request reports that a reader working that way got through only 66 of 1,710
events.
Readers disagree on how many bytes it carries. flpkit and dawparse read one byte; PyFLP pull request 208 and ts-flp read three. In the bytes published so far, both readings use up the same bytes:
AC 01 01 00 C0 …
- Read as three bytes, event 172 holds
01 01 00. - Read as one byte, event 172 holds
01, and01 00becomes event 1, a byte event, with the value 0.
Either way the next event starts at C0, so both readers stay in step and
the bytes alone cannot settle which is right. The explorer reads one byte. What the
event means is unknown.
Fixed-size events
Byte, word and dword events are the ID followed straight away by the value.
09 01 loop active: 1
40 00 00 new channel: index 0
9C E0 22 02 00 tempo: 140000, which is 140 BPM
Variable-length size
Text and data events give their size as a variable-length number between the ID and the bytes. Each byte carries seven bits of the number, lowest bits first. The top bit of a byte is set when another byte follows. Sizes under 128 take one byte.
300 in binary = 10 0101100
low seven bits = 0101100 = 0x2C, more follows → 0x2C + 0x80 = 0xAC
next seven bits = 10 = 0x02, last byte → 0x02
stored as = AC 02
To read a size, start at zero and a shift of zero. Take a byte, add its low seven bits shifted left by the shift, and add seven to the shift. Stop after a byte whose top bit is clear.
Text
Text events hold a string followed by a terminating zero. There are two encodings:
- The FL Studio version string (event 199) is ASCII, ending in one zero byte, so a reader can always find out which version saved the file.
- Every other string is UTF-16LE, two bytes per character, ending in two zero bytes.
C7 0C 32 30 2E 38 2E 33 2E 32 33 30 34 00 20.8.3.2304
C2 0A 53 00 6F 00 6E 00 67 00 00 00 Song
How events are grouped
The stream has no nesting. Items such as channels and patterns are built from runs of events: a New event opens an item, and the events after it set that item’s properties until the next New event of the same kind.
| Event | ID | Opens |
|---|---|---|
| Channel New | 0x40 (64) | a channel in the channel rack; the value is its index |
| Pattern New | 0x41 (65) | a pattern; the value is its index |
| Arrangement New | 0x63 (99) | a playlist arrangement, with its tracks and time markers |
| Slot Index | 0x62 (98) | an effect slot in a mixer insert |
Each pattern’s New event appears twice in a project, so one pattern’s events can come in two separate runs. Join them by the pattern index. A pattern notes event can also appear before any New pattern event; see Note records. Mixer inserts have no New event; their events appear insert by insert, in mixer order. Plugin events follow the channel or slot that holds the plugin.
Project events, such as the tempo and the title, can appear anywhere in the stream and always belong to the project as a whole. The event reference lists every known event by the item it belongs to.