Songs & sharing
The .noisesong file and the noise:// link
What a .noisesong file contains, how the noise:// deep link encodes it, and the limits both obey.
A song leaves NØISE in one of two machine-readable forms: a .noisesong file (JSON) or a noise:// link (the same JSON, encoded into a URL). Neither contains audio. Both carry exactly one song.
Warning
Schema 3, since NØISE 0.81 — with no backward compatibility. A song is ONE band with ONE kit, and a section sets its DRUMS and JAM lanes. The app reads nothing older than schema 3: a file with schemaVersion 2 or none opens as nothing, and an older library is set aside on first launch. This site refuses such a file at upload with the same words. Open the song in the app's editor and export it again.
The .noisesong file
EXPORT — in the SONGS plate and in the editor — writes a UTF-8 JSON document. The file type is registered by the app as nl.weap.noise.song ("NØISE Song", conforms to public.json, extension .noisesong), so double-clicking a file opens it in NØISE.
Envelope
{
"version": 3,
"song": { … }
}| Field | Type | Meaning |
|---|---|---|
version | integer | File format version; 3 since 0.81. |
song | object | The song. |
Keys are written sorted and pretty-printed. Dates are ISO-8601 in UTC without fractional seconds (2026-05-01T12:00:00Z) — the app rejects fractional seconds.
The song object
{
"id": "6F1A0E9C-3D4E-4B11-9A0B-1C2D3E4F5A6B",
"name": "Amber Skyline",
"author": "NØISE",
"songDescription": "Demo song for the website",
"style": "rock",
"kit": "rock.classic",
"drums": { "feel": "straight", "preset": { "name": "LAID BACK", "energy": 0.45, "swing": 0.2, "humanize": 0.25, "live": 0.35 } },
"jam": { "intensity": 0.5, "colorLayer": false, "rhythmGuitar": true },
"tempoHint": 112,
"grooveSeed": 4422912175377245,
"schemaVersion": 3,
"createdAt": "2026-05-01T12:00:00Z",
"updatedAt": "2026-05-01T12:00:00Z",
"chart": { … }
}| Field | Type | Required | Meaning |
|---|---|---|---|
id | UUID string | yes | Identity of the song. Importing a song whose id already exists in your library never merges with it — the import gets a fresh UUID and becomes a new, separate song, with the original id recorded in sourceId so the lineage isn't lost. |
name | string | yes | Song name. |
chart | object | yes | The chord chart (below). |
style | string | no | The JAM style of the whole song: pop, rock, blues, jazz, hiphop, funk, metal. Absent = rock. The drum genre follows from it (pop → POP, rock → ROCK, … hiphop → HIP-HOP) and is not a field. While the song plays the band plays the song's own band; your own DRUMS and JAM panels come back when the song is put down. |
tempoHint | number | no | The song's tempo; applied to the session when the song loads. |
songDescription | string | no | Free notes (notes: in the text format). |
author | string | no | Who wrote it. |
kit | string | no | The one JAM kit of the whole song, an id scoped to the style (pop.strings, rock.classic, metal.stock, …). Absent = the style's first kit. A kit of another style is ignored. |
drums | object | no | The song's DRUMS lane — what every section starts from. See The lanes. |
jam | object | no | The song's JAM lane — the same. |
tuning | string | no | GuitarTuning.id: standard, dropD, halfStepDown, fullStepDown, dropC, openG, openD, dadgad. Applied to the session when the song loads, like the key and the tempo — not a hint. Absent means standard: a song that names no tuning is written in standard, and loading it sets that. |
capo | integer | no | The fret the song's capo sits on, 0–9 (since 0.71). Applied on load like the tuning: absent or 0 means no capo, and loading the song takes one off. The chart stays in the shape key; the band and the detectors sound that many frets up. |
grooveSeed | integer | no | The author's groove seed. Every seeded choice the band makes — which of the authored bass and pad bars, the fills, the approach notes, the drum phrase, the walk-outs into the next chord — is drawn from it, so a shared song plays the same way on every Mac and iPad. Absent = a stable hash of the song's id. The app writes one when a new song is saved and stamps the effective seed on export, like the key. A whole number below 2^53, so every JSON reader - JavaScript included - reads it exactly. |
sourceId | UUID string | no | The song this one was imported or forked from (lineage of shared songs). |
schemaVersion | integer | yes | 3. Anything lower, or none, is not read — by the app or by this site. |
createdAt, updatedAt | date | yes | Timestamps. |
feel, drumStyle, drumEnergy, drumHumanize, jamIntensity, colorLayer and rhythmGuitar no longer exist at song level: they live inside drums and jam. A song from a newer app never fails on an extra key; unknown keys are kept on a round trip.
The lanes
The same two blocks sit on the song (what every section starts from) and on a section (what it says itself). Every field is optional and means "not set here" — see the resolution rule.
drums — what a section says to the kit:
| Field | Values | Meaning |
|---|---|---|
off | true / false | The kit is silent for this section (solo space). |
feel | a GrooveFeel tag from the style's list (straight, halfTime, shuffle, swing, …) | The groove — one feel for the drums AND the band. A feel the style does not offer resolves to the style's first. |
fill.in | crash, splash, none, choke | The cymbal on the section's ONE. Absent = the arrangement decides from the transition. choke is carried, not yet played (plays as a crash). |
fill.out | auto, fill, none, break, or a fill's name (busy, tom roll, fill2, …) | What the kit does on the section's way out, on the LAST bar of the last repeat. auto = the arrangement decides; fill = a fill whatever the transition; none = never; a name = that fill of the genre's bank (unknown → auto). break is carried, not yet played (plays as none). |
variation | a list of words | The style's overlays. Carried by the file; the app has no words for it yet. |
preset.name | STOCK, TIGHT, DRIVING, LAID BACK, LOOSE, SMOKY, QUIET, a player's own, or CUSTOM | A LABEL for the four knobs below. The values travel; the name reads. |
preset.energy | 0–1 | How hard the kit plays. |
preset.swing | 0–1 | The grid, 0 straight … 1 full triplet. Absent = the feel's own swing. |
preset.humanize | 0–1 | How much a hand wavers around the part. |
preset.live | 0–1 | How much authored detail (ghosts, the bar-4 variant) is revealed. |
jam — the band's flags:
| Field | Values | Meaning |
|---|---|---|
intensity | 0–1 | How busy the band plays. |
colorLayer | true / false | The band's fourth (colour) layer. |
rhythmGuitar | true / false | The band's strumming layer, where the style has one. |
The resolution rule
Every lane field resolves in one order, per field:
SECTION → THE SECTION BEFORE IT → SONG- A section that sets a field decides it. A section that sets
fill.inand nothing else decides the cymbal and follows for everything else. - A section that leaves a field open plays what the section before it played — say HALF TIME once and it carries on until something says otherwise. In the editor that reads FOLLOW PREV.
- The first section has nothing before it, so it takes the song's lanes (FOLLOW SONG).
- The style, the kit and the genre are the song's on every section. Nothing a section can say.
- The preset name follows only when every knob does. A section that moved one knob under a named preset reads
CUSTOM: the name is a label for exactly those four values. A section that names a preset and sets no knob carries the name AND the knobs of the section before it — the editor always writes a name with its values. - The listener is not in the list. A field the song leaves open is completed with a fixed default, part of the format, so the same document plays the same band everywhere:
| Field | Default |
|---|---|
style | rock |
kit | the style's first kit |
drums.off | false |
drums.feel | the style's first feel |
drums.fill.in | absent — the arrangement decides |
drums.fill.out | auto |
drums.variation | [] |
drums.preset | STOCK: energy 0.5, the feel's own swing, humanize 0.15, live 0.25 |
jam.intensity | 0.5 |
jam.colorLayer | false |
jam.rhythmGuitar | whether the style has the layer at all |
A section's swing and live land on the app's clock (GRID) while the song plays and are never saved as the player's own; the player's come back when the song is put down.
The chart object
{
"writtenKey": { "tonic": 9, "mode": "minor" },
"endBehavior": "end",
"sections": [
{
"id": "…",
"name": "INTRO",
"repeats": 2,
"energy": "sparse",
"color": "cyan",
"drums": { "feel": "straight", "fill": { "in": "none" } },
"items": [
{ "ref": { "degree": { "_0": { "degree": 1, "alteration": 0, "quality": { "minor": {} }, "alterations": [], "secondaryOf": false } } },
"duration": { "bars": 2, "ticks": 0 }, "rawText": "Am" },
{ "ref": { "absolute": { "_0": { "root": { "letter": "F", "accidental": 0 }, "type": { "major": {} }, "alterations": [] } } },
"duration": { "bars": 1, "ticks": 0 }, "rawText": "F" }
]
}
]
}| Field | Meaning |
|---|---|
writtenKey | The key the chart was written in, or absent. Degree cells resolve against it for display; while playing they follow the KEY module. |
endBehavior | "end" = play once, then a final downbeat hit held for a bar and the band stops. Absent = loop forever. Opaque string, so future behaviours never break older readers. |
sections[] | The editor adds up to 24; a file is read in full. Each has id, name, repeats (1–16), energy (base, lift, groove, hold, riff, sparse, stop — an unknown value plays as base), an optional color, and the two optional lanes drums and jam (above). A section carries no style, kit or drum genre, and no endFill — a fill on the way out is drums.fill.out: "fill". A lane field left out always means: what the section before it played, and for the first section the song's lane — never the listener's own setting. |
items[] | At most 32 per section. Each is { ref, duration, rawText }, plus an optional shape and an optional push. |
ref | Exactly one of degree, absolute, noChord, repeatPrevious. Swift encodes the payload under _0. A degree has degree 1–7, alteration (−1/0/+1), optional quality (chord type), alterations (b5 #5 b9 #9 #11 b13 add6 add9 add11 no3 no5) and secondaryOf (true = V/x), plus an optional bassIntervalSemitones (1–11): a slash bass as semitones above the chord's root, so it transposes with the key — { "degree": 1, "bassIntervalSemitones": 4 } is C/E in C and A/C♯ in A. On a chord tone it is an inversion, off it a pedal. An absolute chord has root (letter A–G + accidental), type, alterations and optional bass (a note name). Since 0.71 the band plays the bass; before, it was display only. |
duration | { bars, ticks }. Bars are time-signature relative (a 2-bar chord is 2 bars in 4/4 and in 3/4), ticks are exact sub-bar time at 24 ticks per beat, so { "bars": 0, "ticks": 48 } is two beats. The editor writes any number of beats (a change on beat 4 is { "bars": 0, "ticks": 72 } then { "bars": 0, "ticks": 24 }), and a section need not add up to whole bars. Bars are clamped to 0–32. |
rawText | What the user typed or what the cell showed when it was written. Display only — a chart can show I where the sounding chord is Em. |
shape | The guitar grip the player chose, as a self-describing tag: six frets low E to high e, x for muted, e.g. x32010. Frets of 10 or more need separators (8-10-10-9-8-8), and @n states a base fret that cannot be derived from the notes (x24442@2). Frets are 0–24. Absent means the app draws its own default grip. Rests and repeats never carry one. A grip is a free choice, not a property of the chord — players pick an Em7 voicing on an Em cell — so nothing validates it against the chord, and an unreadable tag simply means "no grip" rather than an invalid song. |
push | "eighth" or "sixteenth" when the chord is anticipated (since 0.71): the band strikes it that much before its written place and holds it over the beat. The place and the duration never move — bar counts, the playhead and winding know nothing of a push. Absent = on the beat; an unknown value reads as absent; the value is never written as "none". In the song text a push is a caret: ^G, ^^G. |
Chord types are the 24 names of the app's ChordType: major minor diminished augmented sus2 sus4 major7 minor7 dominant7 diminished7 halfDiminished7 minorMajor7 augmented7 add9 major9 minor9 dominant9 major11 minor11 dominant11 major13 minor13 dominant13 power. In the file such a name is the key of an empty object, { "minor7": {} }, under type as well as under quality.
What the app accepts on import
importSongs tries three shapes in order and takes the first that decodes:
- a
.noisesongdocument{ "version": …, "song": { … } }, - a bare song object,
- a whole library export
{ "version": …, "songs": [ … ] }— every song that this build can read is imported; unreadable ones are skipped, never the whole file.
In every shape a song with schemaVersion below 3 is skipped: the app logs why, and nothing is converted.
The noise:// link
The website's Open in NØISE button, and the Copy link button beside it, produce this link. The app makes no links itself; it only reads them.
noise://song?d=<payload>- scheme
noise, hostsong, one query parameterd; <payload>is the.noisesongdocument encoded compactly (no whitespace, sorted keys,version: 3,schemaVersion: 3) as base64url (RFC 4648 §5,-and_instead of+and/, no=padding).
When the app opens such a link it decodes the payload with the same rules as a file. It is tolerant: a payload that arrives padded or percent-encoded still decodes. Because the JSON is not compressed, a link is roughly 1.4 × the size of the compact JSON — a four-section song is a few kilobytes. Links longer than what your chat client accepts should be shared as a file instead.
Opening a link never adds anything silently: the app asks first. See Import.
Where your library lives
All songs are stored in one file, inside the app's container:
~/Library/Containers/com.noise-app.macos/Data/Library/Application Support/NØISE/jam-songs.jsonIt is written atomically; the previous version is kept as jam-songs.json.bak on every successful save, and a corrupt main file is silently restored from the backup (the corrupt copy is kept as jam-songs.json.corrupt). The library holds at most 100 songs; beyond that the least recently updated songs are dropped on save. A library written before schema 3 is set aside as jam-songs.v2.json on the first launch of 0.81 and the library starts empty — the songs are not converted, they are written again in the editor.
Warning
Do not edit jam-songs.json while NØISE is running — the app writes the whole file on every save and will overwrite your changes. Export a .noisesong, edit that, and import it back.