Ableton writes a .asd beside every audio file it analyses. It is usually described as a waveform cache, and that is wrong: it holds warp markers, loop points, onsets, pitch marks and time signature — Live's whole reading of the audio. The head is a frame-position grid whose last entry is the source file's exact frame count and whose steps never exceed 30 ms of audio; because that ceiling is a fixed fraction of the sample rate, an orphaned sidecar still describes audio that has been deleted. The body is a serialised object tree whose field names are stored in UTF-16, which is why an ASCII scan makes the file look like noise. It also states a tempo -- not as a number, but as a mapping from seconds to beats that the tempo falls out of. Hover a field to light its bytes.
Three unrelated shapes ship under one brand. .asd is binary and undocumented; the Live Set family is gzipped XML that names its own type; .amxd is a plain chunk chain. They are grouped here because a project folder holds all of them at once.
| ext | what it is | shape |
|---|---|---|
.asd | per-sample analysis sidecar | binary, byte-order-declared |
.adg | device group / rack preset | gzip + XML <GroupDevicePreset> |
.als | Live Set (project) | gzip + XML <LiveSet> |
.alp | Live Pack | gzip archive, not XML |
.alc | Live Clip | gzip + XML <LiveSet> |
.adv | device preset | gzip + XML, device-named root |
.amxd | Max for Live device | ampf chunk chain |
.agr | groove / quantize | gzip + XML <Groove> |
.ams (Operator meta sound), .abl and .ablbundle (Note) and .ask (theme) are the same gzip + <Ableton> XML shape. The root child element names the type, so an unmapped document still identifies itself.A ten-byte head, then the grid. The interesting part is byte 1: it is a byte-order mark in the TIFF style, 'I' for Intel and 'M' for Motorola. Big-endian files, written by PowerPC-era Macs, exist and parse only big-endian. A reader that assumes little-endian silently mangles them.
A 44.1 kHz stereo sidecar, 7.774 s of source audio, written by Live 12.
The grid is a strictly increasing list of absolute sample offsets into the source audio. Two properties make it far more useful than it looks. First, the last entry equals the source file's exact total frame count, with no rounding. Second, no step ever exceeds 30 ms of audio: 1,323 frames at 44.1 kHz, 1,440 at 48 kHz, and so on.
Because the ceiling is a fixed fraction of the rate, the largest observed step identifies the rate, and the last entry then gives the duration.
| quantity | how | confidence |
|---|---|---|
| sample rate | smallest standard rate whose 30 ms grain is not smaller than the largest step | exact when the ceiling was reached, otherwise a lower bound |
| frame count | last grid entry, read directly | exact |
| duration | frame count / rate | inherits the rate's |
.asd in a folder is evidence about a file that no longer exists — its rate, its length, its exact sample count. Nothing else in the toolchain recovers that, because nothing else survives the audio.After the grid comes a serialised object tree that writes its own field names inline. They are length-prefixed UTF-16, so every second byte is zero and an ASCII string scan returns nothing — which is most of why this format has a reputation for being opaque. The names are not gathered in a header; they are interleaved with their data across the whole file, so a parser can seek a field by name instead of by a version-specific offset.
Note the 0x00 after every character.
| group | fields |
|---|---|
| warp | WarpMarkers IsWarped WarpMode TransientResolution |
| clip / loop | LoopStart LoopEnd HiddenLoopStart SampleOffset |
| metre | Numerator Denominator AufTaktData (anacrusis) |
| onsets | OnSets UserOnsets HasUserOnsets PitchMarks |
| staleness | OriginalFileSize |
InitialBPM, Bpms, BeatTrackState, Tonalities) and the overview set (OverViewLevels, UnbiasedTempoEstimate), so they cannot be generations of one another. Versioning is carried per object as individual Version ints, and there is no global version byte.LoopStart, LoopEnd, IsWarped, WarpMode, Numerator and Denominator are all declared here — and LoopEnd is absent from 91% of files whose Set states a real one. Loop points belong to a CLIP, and one audio file can back many clips with different loops. What the sidecar holds is per-file ANALYSIS.A warp marker pins one instant of the recording to one position in the bar. Each record carries its own class name inline, u8-length-prefixed, so the markers are self-locating — there is no count to find and no offset to derive.
Marker id 1 from a real project sidecar. The Live Set that wrote it states exactly these values.
.asd stores a BPM, at any byte offset, as neither f32 nor f64, and in no derived form. But two markers give it directly: (beats / seconds) x 60. Here 0.03125 beats in 0.011029411764705883 s is 170 BPM, and the Live Set declares 170. Across 40 clips the derivation matched the declared tempo every time, and over a 2,000-file sample it yields only clean musical values: 140, 170, 138, 120, 150, 145, 70, 172..asd is written when the audio is analysed, and outlives the projects that use it.Live's transient detection, stored as two length-prefixed arrays back to back: the count, the frame positions, the count again, then one energy per onset. That repeated count is what identifies the structure in a file with no other landmark.
A 13-transient loop. Positions are absolute frame offsets, checkable against the frame count the grid already gave us.
Sitting just above the onsets, in the order the Live Set declares them.
Sets, clips, racks and device presets are all the same thing: a gzip stream wrapping one XML document whose root is <Ableton>. The root carries the Live build that wrote it, which makes these the easiest provenance evidence in the whole ecosystem — an exact version string, not an inference.
<Ableton MajorVersion="5" MinorVersion="12.0_12120"
SchemaChangeCount="2" Creator="Ableton Live 12.1.5"
Revision="18e155016678da1939bdc3938f981adf84ebc96d">
| ext | root's first child | note |
|---|---|---|
.als | <LiveSet> | a project |
.alc | <LiveSet> | identical to a Set in content |
.adg | <GroupDevicePreset> | rack |
.adv | the device's own class | <Operator>, <Wavetable>, ... |
<LiveSet>. Only the extension separates them. There is no content rule that tells them apart, so any reader has to go by the name and say that it is doing so.A Max for Live device is an Ableton Max Patch Format container: the ASCII magic ampf, a version word, and then — before the chunk chain begins — a four-byte marker, aaaa. Only at offset 12 does the chain start: four-byte id, little-endian length, payload. The ptch chunk carries the Max patcher, a short binary preamble followed by JSON.
0x00 "ampf" u32:version "aaaa" <- 12-byte header
0x0C "meta" u32:len ...
0x18 "ptch" u32:len mx@c ... { patcher JSON }
aaaa as an id makes the following four bytes — the ASCII meta — decode as a length of 1,635,018,093 bytes, and the whole chain collapses to one impossible chunk. The chain starts at 12, not 8.ptch chunk ends exactly on the last byte of the file, so a chain that stops short means something is missing.Two things in a real library wear Ableton clothing and are not Ableton documents. Both matter because the honest answer is more useful than a forced one.
Not every file with a .asd extension is a sidecar. ._name.wav.asd resource-fork stubs are left behind when a Mac writes to a non-HFS volume, and they are common enough to matter. They open with 00 05 16 07 and the string Mac OS X.
A .alp is gzip like the Set family, but it is an archive, not a document: there is no <Ableton> element inside. The gzip magic alone therefore cannot tell a Pack from a Set; only the root element can.
<Ableton> root or it does not. The extension is not evidence either way.