Generate a ready-to-open DAW project — with audio placed in the arrangement, named, and at the right tempo — without automating the DAW's UI. The project file is written directly, byte-correct, and the DAW is only ever asked to do the one thing it does perfectly reliably: open a file.
Works today for FL Studio, Ableton Live, and Logic Pro.
stems + tempo ──► generate project file ──► headless self-check ──► DAW opens it
(.flp / .als / .logicx) (verify before open) (renderer only)
Setting up a session from a delivery of stems is repetitive studio admin: import each file, name the tracks, set the tempo, lay it out. The usual way to automate a DAW is to drive its UI — click, drag, wait, hope. That path is fragile: it fails mid-state, differently every time, and most DAWs actively resist it (no scripting surface, no drag-drop from synthetic events).
This takes the opposite approach: treat the DAW as a renderer, not a builder. Generate the project file outside the DAW, deterministically, and verify it before the DAW is ever involved. Every failure mode moves before the app launches, where it produces a precise error instead of a half-built session.
Each DAW stores projects differently, and none of the three formats is officially documented for this. The work was reverse-engineering them from real project files and proving each finding:
- FL Studio (
.flp) — a classic TLV event stream. A dependency-free codec with a byte-identical round-trip guarantee, plus the finding that FL's current playlist items are 80-byte structs (older public tooling only knows the 32- and 60-byte layouts). Audio clips are a specific channel type; the channel block is cloned from a donor and patched. - Ableton Live (
.als) — gzipped XML. Clones a track and an unwarped audio clip, and handles the non-obvious bits found by testing: tempo lives in an automation envelope (not just the manual field), unwarped clip length is in sample-seconds, and the sample reference must be set-relative or Live reports the audio offline. - Logic Pro (
.logicx) — an undocumented binary (ProjectData). Tempo is a fixed-offset field; arbitrary track/region names and per-region lengths are patched in place. The corruption boundary was isolated by single-variable bisection: certain length-delimited fields can't be resized, so names are written within the template's byte span and audio is stored under stable filenames.
Nothing is trusted because the code produced it. Every generator ships a self-check that re-parses the file it just wrote and asserts every property checkable without a DAW — tempo, track/clip count, names, sample references resolve, byte round-trip. Only if that passes does the file go near a DAW. An at-machine gate then opens the project, screenshots it, OCR-verifies the tempo and names on screen, quits, and reopens to prove persistence. That "prove it before you claim it" gate is as much the point as the formats.
pip install pytest && pytest # portable codec/parser tests run anywhere
STUDIO_AGENT_LOCAL=1 pytest # + integration tests (need a local DAW + your donor fixture)
The portable tests (codec round-trips, event parsing, struct layouts) are the trust
anchor and run with no DAW installed. The integration tests build real project files and
need a DAW template plus a donor fixture you generate from your own project (--extract);
they skip by default.
research/
fl/ FL Studio .flp codec + generators
ableton/ Ableton .als generator
logic/ Logic .logicx generator + region patching
tests/ deterministic tests
Donor fixtures are generated from your own DAW projects and are not committed.
Reverse-engineering a file format for interoperability. No proprietary code is included; the formats were derived by inspecting files the author's own installed DAWs produced.