Draft 2 Open for comment. The tools that read and write it arrive in Wavelength 0.4.0; the songs on this site already download as .wavelength files.

The .wavelength file

A song is a folder of open files. A .wavelength file is that folder, zipped. Unzip it with anything and read every part in a text editor.

Read the spec Listen to the songs

What's in a song

The job is the song: every note, sound, effect and fader, as JSON. Around it sit the files that explain it, the render that lets you hear it, the comments made while it was built and every revision it went through.

Only the manifest and the job are required. Everything is plain text or a standard file (MP3, PNG, WAV), and nothing in a song needs Wavelength to be read.

express-to-nowhere/
  wavelength.jsonthe manifest: title, credits, licence
  job.jsonthe song: notes, sounds, effects, mix
  make-job.pyhow the job was made (never run)
  NOTES.mdthe story, the credits, the tracks
  media/samples, clips, preset files
  render/mix, picture, report: hear it now
  review.jsoncomments, pinned to what was heard
  history/every revision

Four promises

Open

JSON and plain text, a published spec (CC BY 4.0) and JSON Schemas (CC0). No opaque blobs are needed to read or render a song, and a second, independent reader keeps the spec honest.

Safe to open

A song is data. Opening, checking or rendering one never runs anything inside it, a package can't write outside its folder, and a song never carries a git repository.

Plays anywhere

Paths stay inside the song. Plugins, presets and sample libraries are named, listed in the manifest and given stand-ins, so the song renders on a computer that has none of them.

Remembers every render

Every render is a revision you can undo, restore or compare, and every comment points at the revision and bars that were playing when it was written.

The manifest

wavelength.json says what the song is and what each file does: its title, the people and models who made it, the prompt it started from, its licence, which file is the job, and what it needs from the computer that renders it.

Every song has an ID that survives renames and copies. A remix gets its own and names the song it came from. Tools keep their own data in namespaced fields, and readers skip what they don't understand.

{
  "format": "wavelength.song",
  "formatVersion": "1.0",
  "id": "9b2f6c1e-4d7a-4f0e-9a51-6b3c2d8e1f07",
  "title": "Express to Nowhere",
  "authors": [
    {"name": "Austin Ginder", "role": "producer"},
    {"name": "Claude Opus 5.5", "role": "composer", "kind": "ai"}
  ],
  "prompt": "I'd like to make a trance song...",
  "license": "CC-BY-4.0",
  "job": "job.json",
  "files": [
    {"path": "make-job.py", "role": "source"},
    {"path": "render/mix.mp3", "role": "render"}
  ],
  "requires": [
    {"track": "bass", "plugin": {"name": "Surge XT", "format": "clap"},
     "preset": "Trance Seq Bass", "fallback": true}
  ]
}

Every render is a revision

Each render adds a line to history/log.jsonl with the song's files as they were rendered and how loud each section came out. Save points add a message. The files themselves are stored once each, compressed and named by their SHA-256, so hundreds of revisions of a song take a few megabytes.

Undo, redo and restore never delete: each writes an older revision's files back and adds a line, so it can be undone too. wavelength diff compares two revisions as music: which tracks, bars, sounds and settings changed.

Git is one command away, not inside the file: every revision maps to one git commit, the same on every computer, for anyone who wants a repository or a bundle.

{"rev": 11, "op": "render",
 "by": {"name": "Claude Opus 5.5", "kind": "ai"},
 "files": {"job.json": "sha256:7e3a...",
           "make-job.py": "sha256:91b0..."},
 "render": {"lufs": -12.3, "sections": [...]}}
{"rev": 12, "op": "save",
 "message": "Build holds the filter open", ...}
{"rev": 13, "op": "undo", "parent": 12, "target": 11, ...}
Three revisions from history/log.jsonl. Each is one line in the file, wrapped here to fit.

Comments remember what you heard

A comment written while listening keeps the revision and render that were playing, the bars and seconds selected and the tracks picked. That anchor never changes, so an agent that finds the comment days later can open that exact revision, see what has changed in those bars since, and answer in the same file.

Comments live outside the history: writing one never makes a revision, and undoing a change never loses a comment.

{
  "text": "The filtering on the Arp drowns out the build.",
  "status": "open",
  "anchor": {
    "revision": 11,
    "render": "sha256:55e1...",
    "bars": [53, 56],
    "time": [137.82, 144.67],
    "tracks": ["arp"]
  }
}

Plays anywhere

A song made with Serum 2 still renders on a laptop that has never seen it. Each track can list stand-in sounds, tried in order and ending with Wavelength's built-in synth, which every copy of Wavelength has. The manifest lists what the song needs, so you know before rendering which parts will sound different.

wavelength kit install adds free synthesizers (Surge XT, OB-Xf, Dexed) and a General MIDI SoundFont to any machine, cloud containers included.

{"name": "Bass", "plugin": "Serum 2", "preset": "BA - 303 Punchier",
 "fallback": [
   {"plugin": "Surge XT", "preset": "Trance Seq Bass"},
   {"plugin": "builtin:synth", "preset": "BA Acid", "gain": 1}
 ]}

The package

A .wavelength file is a ZIP whose first entry is mimetype, stored uncompressed, holding application/vnd.wavelength.song+zip. Text is compressed, audio and images are stored as they are. Unpacking one gives the song folder; packing the folder again gives the same file.

  • Paths are relative, stay inside the song and never use ... Names work on every system: no characters Windows forbids, no device names like aux, no two names that differ only in case.
  • No symbolic links, no encryption, nothing named .git.
  • Readers check every entry's CRC-32, refuse packages that break these rules and cap how much a package can unpack to.
  • Rendering a song never reads or writes outside it, and scripts in a song are kept as the record of how it was made, never run.

Open by design

The format borrows from formats that have stayed open for years: OpenDocument and EPUB for the ZIP with its mimetype first, OpenTimelineIO for a folder and a file that are the same thing, glTF for version fields and namespaced extensions, OCI for content-addressed files, and Fossil and Jujutsu for a history where undo is just another entry.

  • Versioned. formatVersion and minReaderVersion; minor versions only add, and readers ignore what they don't know.
  • Checkable. wavelength validate, JSON Schemas and example packages, including ones every reader must refuse.
  • Licensed to use. The spec is CC BY 4.0 and the schemas CC0: anyone can read and write .wavelength files without asking.

Read the full spec on GitHub