This document is a personal memo summarizing the results of my own analysis of amxd file format. It was originally written around the end of 2023. Please do not expect any correctness here. A parser is now publicly available at https://github.com/Ableton/maxdevtools/tree/main/maxdiff, so please refer to that for the correct specifications and further details.
I examined the AMXD file and found it to be an uncompressed format that combines the contents of multiple files. The overall structure resembles a simple chunk-based binary file, similar to RIFF. However, perhaps due to historical reasons, it contains two different chunk styles.
Entire file structure are looks like RIFF format but some difference. In this note, I'll call it Global Chunks. Global chunks looks like;
- There are no inclusion chunks such as RIFF chunks. The entire file is an array of multiple chunks.
- Each chunk has
- 4 byte identifier field
- 4 byte size field as little-endian 32bit unsigned int (except this field itself and the chunk identifier)
- Has no null padding ( I guess. Some text fields looks C-like null terminated string so there are null bytes but it seems they don't respect the even byte order.)
And, there are one more chunk series which appears in ptch chunk, which included in mx@c chunk. In this note, I call it MX Chunks or mx@c archive format. MX chunks looks like;
- There are inclusion chunk with identifier
mx@c. - Each chunk has
- 4 byte identifier field
- 4 byte size field as big-endian 32bit unsigned int (includes this field itself and the chunk identifier. it means this size will always 8 larger than (R)IFF style size value.)
- Has null padding ( I guess. )
| name | type | optional | note |
|---|---|---|---|
| ampf | enum aaaa, iiii or mmmm |
The file signature, and/or M4L plugin type field. (Ableton Max Plugin (Format or File))? The value might be m4l plugin type - aaaa audio effect- iiii instrument- mmmm MIDI effect |
|
| anno | c-style null terminated string? | yes | annotation field which could be set via Max's project inspector |
| meta | unknown | yes | Some amxd file has this meta chunk but I've never seen meaningful value here by now 🙈 |
| ptch | JSON text OR mx@c archive |
content(s) of the M4L plugin |
mx@c archive is made up of 3 sections;
mx@cchunk - size info for data field- data field - concatenated file contents
dlstchunk - list of meta info for file contents
mx@c chunk is a standalone chunk but the value is for size of next data section.
| size | type | note |
|---|---|---|
| 4 | const mx@c |
Must be a chunk signature |
| 4 | Int32BE const 16? | May be the size of this header chunk. Maybe always 16. |
| 4 | ? const 0x00000000? | Unknown null field. ( Combine with next field as 64bit bigint? 1) |
| 4 | UInt32BE | size of data section (includes size of this mx@c chunk (16 bytes)) |
This section is not chunk style. Binary stream of the concatenated files. (Almost of them are JSON text, though) It appears to be padded with null bytes, but the regularity is not clear because after this area is finished, the chunks may have odd starts. To split this stream into original files, need to decode next meta data chunks first.
A collection of hierarchically structured metadata chunks for splitting and restoring archived contents.
dlst chunk has children chunks called dire. Each dire chunks represent file info for archived files and have meta info as various child chunks.
| chunk name | content type | note |
|---|---|---|
| dlst | dire chunks |
directory list? data list? |
| dire | combination of multiple chunks described below - type, fnam, sz32, of32, vers, flag and mdat. |
directory entry? |
| type | ascii | content type. I saw 'JSON', 'TEXT', 'gDSP' and 'WAVE' by now. There must be more variations. |
| fnam | ascii | filename |
| sz32 | UInt32BE | num of bytes of this file in data contents area |
| of32 | UInt32BE | start position of this file content, byte offset from top of mx@c chunk |
| vers | ? | Unknown - version info? |
| flag | ? | Unknown |
| mdat | UInt32BE(Macintosh Time) | Modification Date in Macintosh Time (seconds, elapsed after Jan 1, 1904) |
Although at first glance it looks like a straightforward RIFF file, it actually mixes endianness and uses Macintosh epoch dates (this is the first time I’ve ever seen it used. I figured out it was some kind of epoch time, so I worked backward from the current time to find what seemed like the origin date. When I searched for it and got a Wikipedia hit, I was as excited as when I finally solved Return of the Obra Dinn.), making the reverse-engineering of this file format feel like a great puzzle game—and I thoroughly enjoyed it. Also, I felt a long great history of Max.
Footnotes
-
But this must be smaller than parent
ptchchunk's size field which is 32bit... 🤔 ↩