Skip to content

Collections (book / playlist)

This document defines the text format by which an ordered set of songs — a book or a playlist — is represented in a single neumaRk file.

A collection does not introduce a new language: it is a thin container layer around a sequence of songs, each of which is a standalone neumaRk document as already defined by the rest of the specification. The same parser reads single songs and collections; the distinction is made on the first line of the file.


1. Purpose and role

The collection format serves to export, share, and re-import a book or a playlist as a single .nrk file — self-contained and readable.

The guiding principle is portability: the file is a self-sufficient snapshot of the collection. All songs are embedded as snapshots (frozen copies), so that the file can be opened and imported by anyone, even without access to the original songs and even if the originals change or disappear.

Everything that is product-specific (and not part of the musical language) — cover art, curated tags, sharing, roles, database identifiers — is not part of the file (see §7).


2. Collection and single song

A neumaRk file may represent:

  • a single song, whose first line is the version declaration nrk:<major>.<minor> (see neumaRk_header.md §2);
  • a collection, whose first line is nrk-book:<v> or nrk-playlist:<v> (§3).

The distinction is given by the content of the first line alone, never by the file extension: a .nrk may contain either.

A file starting with nrk: is a single song; a file starting with nrk-book: / nrk-playlist: is a collection. The two readings coexist in the same parser.

The term collection is a conceptual umbrella used in this specification and in tooling; it never appears as a token in the file. The type (book or playlist) is written directly into the first-line marker.


3. Opening line and type

The first line of a collection is a version declaration that embeds the type:

nrk-book:0.6

or

nrk-playlist:0.6

Characteristics:

  • it is mandatory and must be the first line of the file;
  • the type (book / playlist) is part of the marker: reading the first line tells you both that the file is a collection and which type;
  • the version follows the same nrk: numbering of the language.

Functional difference between the two types:

  • a book is a curated set of songs, without per-song overrides;
  • a playlist is an executable sequence in which each song may carry a per-occurrence override (§6).

4. Collection header

After the opening line, and any blank lines, a collection header may appear: a block of directives in the form key: value.

nrk-playlist:0.6
name: My Setlist
desc: live at the Blue Note
Directive Meaning Mandatory
name: collection name no (recommended)
desc: free description no

Header directives:

  • use : as the separator (same syntactic family as nrk:);
  • precede any song block;
  • are part of neumaRk (as the HT) title is for the song): the textual identity of the collection.

A header directive appearing after the first song block is out of place (W155): it is ignored and does not enter the song that precedes it. The same holds for a directive written between an item: line and its block: the collection name does not change. Repeated before the first block, a directive takes its last occurrence, with no diagnostics.


5. Song blocks

The body of the collection is a sequence of song blocks. Each block:

  • is a standalone neumaRk document, starting with its own nrk:<v> line and continuing with header and datapacks as usual;
  • is a self-sufficient snapshot (the musical content is embedded, not referenced);
  • is copy-pasteable as a valid .nrk file on its own.

As in a single document, blank lines may stand between the block's nrk:<v> line and its header, and the header may contain // comments on lines of their own: neither is a field, and the title stays the one of HT) (or the first line of the implicit header). The markers of the block header have the meaning given in neumaRk_header.md §6.2: HC) carries the credits, and no H…) marker becomes the song's style.

The song order is the order of the blocks in the file: there is no numeric ordering key.

nrk-playlist:0.6
name: My Setlist

nrk:0.6
First Tune (Author)
F 120bpm
F| Bb| C7| F|

nrk:0.6
Second Tune (Author)
Bb 90bpm
Bb| Eb| F7| Bb|

A collection with no song blocks is degenerate (W156).


6. Per-item override (playlist only)

In a playlist, each song may be preceded by an item: line declaring its overrides for that occurrence in the setlist. The overrides are not properties of the song (the same song in two playlists may have different ones): they are a layer of the setlist entry.

item: transpose=+2 notes="capo 3" form=[Intro] [A|8]x2 [B|8] [A|8]
nrk:0.6
My Tune (Author)
…

Rules:

  • the item: line applies to the song block that immediately follows it (the next nrk:); if it is not followed by any song block it produces warning W154;
  • it appears only if there is at least one override; its absence means "no overlay";
  • it is allowed only in playlists. An item: line in an nrk-book: is out of context (W152).

6.1 Parameter syntax

Parameters are key=value pairs separated by spaces. The = sign distinguishes the inline parameter from the header directive (:), so that no symbol has a double role.

A value:

  • is a simple token (no spaces), e.g. transpose=+2; or
  • is quoted "…" when it contains spaces (literal text, quote-aware as in the rest of neumaRk), e.g. notes="capo 3".

Allowed keys: transpose, notes, form. An unknown key is ignored with diagnostic W153; a token without =value with W179.

Key Type Meaning
transpose signed integer performance transposition (overlay, ± semitones)
notes text personal annotation for this entry
form FORM grammar performance form for this occurrence (§8)

6.2 form= consumes the rest of the line

Since the FORM grammar itself uses "…" containers for labels (see §8), the form= parameter is not quoted: it consumes everything that follows up to end of line, verbatim. For this reason form=, when present, is the last parameter of the item: line.

item: transpose=-1 form="Theme"[A|8]ff [B|4]x2 "Coda"[A|8]&fermata

The quotes here are internal to the FORM grammar (labels), not delimiters of the parameter. (A multi-line form is out of scope in this version.)

A null transpose (+0, no-op) and an empty notes are not errors. A transpose that is not an integer (transpose=abc, transpose=1.5) is ignored with W185.


7. Portability mode: inside and outside the file

The collection carries only music and minimal structure. Everything that is application product is reconstructed on import from defaults, as when creating a new collection.

In the file (it is neumaRk):

  • the type (nrk-book: / nrk-playlist:);
  • name: / desc:;
  • the song order (= order of the blocks);
  • for playlists: the transpose / notes / form overrides on item:;
  • each song in full, as a snapshot.

Outside the file (it is not neumaRk):

  • cover art, curated tags, subscriber count;
  • sharing, roles, permissions;
  • the songs' database identifiers;
  • the dynamic vs snapshot distinction of playlist entries (on export every entry is resolved to a snapshot).

7.1 The file is intentionally anonymous

Consistent with the principle above, a collection file carries no origin identity: no database identifiers, no deduplication keys, no host tags. It is, by design, anonymous.

Consequence: a song's identity (deciding whether two songs are "the same") is not a property of the file — it is a host concern, to be derived from the music (see §7.2), never from an opaque tag stuck to the file. This is deliberate: the format does not carry data it cannot itself understand.

7.2 Import semantics (host behavior)

How a host re-imports a collection is not defined by neumaRk: it is host behavior, described in the documentation of the application that implements it. Two consequences of the file's anonymity (§7.1), however, hold for every host:

  • re-importing the same file cannot recognize the songs already present by an identity: the file carries none;
  • any recognition ("do I already have this song?") can only be based on the music (for example a melodic fingerprint), not on an exact key glued to the file; and it is, by nature, a suggestion rather than an automatism.

7.3 Header absorption on import (lossless)

Each block of the collection is a complete song, header included. An import that splits the header (the song's metadata) from the body (datapack) recovers it in full — title, credits, key, tempo, meter, style, subtitle, year, alternates, languages — and the body is the datapack with leading/trailing blank lines removed: the export→import round-trip is lossless.

Requirement: the split relies on the blank line between header and datapack (which conforming exporters always emit). On hand-written files without that separator, header and body cannot be told apart.


8. FORM at the collection level

The form parameter of a playlist entry (§6) uses the FORM) grammar defined in neumaRk_play_and_form.md (section boxes, informative durations |N, labels, dynamics, keywords, free prose).

8.1 Semantics: replacement

If a playlist entry carries a form, it replaces the FORM) section possibly contained in the song's snapshot, for that occurrence.

It serves to declare: "the form in which we perform this song tonight is this, regardless of the song's original form."

  • override present → the item form wins over the song's FORM);
  • override absent → the song's FORM) remains (if present).

It is a replacement, not a merge.

8.2 Why FORM and not PLAY

FORM) is position-independent (a single, descriptive section at the end of the document; it is not executed): it lends itself to being declared at the setlist level, where only a reference to a song exists.

PLAY) instead is positional/inline: its effect depends on where it is placed among the datapacks (see neumaRk_play_and_form.md §2.1). At the setlist level there is no position inside the song into which to inject it, so PLAY) is not expressible as an entry override. The form override is therefore always descriptive (FORM), never executed: it does not alter what is executed, but what the musicians read as the form.

8.3 Reference resolution

The [NAME] boxes of the item form resolve against the M) markers of the entry's song (the snapshot that follows), with the same model as neumaRk_play_and_form.md §3.1. A box that matches no marker is reference broken: rendered as non-executed text, with no error or warning (neumaRk_play_and_form.md §7.3). This allows informal setlist forms.

Box diagnostics (W141 duration, W142 repeat, W143 keyword) remain applicable; document-placement ones (W140 multiple FORM), W145 FORM) not at the end) do not apply to the item form.


9. Parsing rules

9.1 Split before musical parsing

The collection file is split into blocks at the nrk: lines before any musical analysis. The song parser receives only the text from one nrk: line to the next.

Consequence: the collection tokens (nrk-book: / nrk-playlist:, name: / desc:, item:) live in the segments outside the blocks and cannot collide with musical content.

9.2 Recognition

  • first line nrk-book: → book collection;
  • first line nrk-playlist: → playlist collection;
  • first line nrk: → single song.

In the exchanged file nrk: is the first line of the song (neumaRk_header.md §2); nrk-book: / nrk-playlist: are the collection's alternative first-line tokens. They are distinct literal prefixes: recognition is additive and unambiguous.

Inside a collection the nrk: line is what separates one song from the next, so every song block must open with its own. A song written without nrk: after another block is merged into the previous song, and the parser reports it with W183.

9.3 Blank lines and versions

  • Blank lines separate the collection header from the blocks and the blocks from one another, consistent with datapack delimitation (neumaRk_datapack.md §1).
  • The %%NAME … %%end block (song versions, neumaRk_versions.md) remains internal to the single song block: it is text the song parser sees, not a collection token. The collection layer does not use %%.

10. Diagnostics

Code Description
W152 item: line in an nrk-book: collection (books have no per-item overrides)
W153 Unknown override key in item: (allowed: transpose / notes / form)
W154 item: line not followed by a song block (nrk:)
W155 Collection header directive (name: / desc:) after the first song block, or between item: and its block: ignored
W156 Collection with no song blocks
W179 Token without =value in item: (e.g. item: transpose=+2 capo)
W183 Song block without its nrk: line: merged into the previous song (§9.2)
W185 item: transpose= that is not a signed integer: override ignored (§6.1)

10.1 Non-errors

  • a snapshot block whose FORM) is replaced by the item form (§8.1);
  • an item form box [NAME] with no matching marker (reference broken, §8.3);
  • transpose=+0 (no-op) and empty notes;
  • extra blank lines in the header or between blocks.

11. Examples

11.1 Playlist with overrides

nrk-playlist:0.6
name: Friday Gig
desc: trio set

item: transpose=+2
nrk:0.6
Blue Bossa (Kenny Dorham)
Cm 140bpm
Cm| Fm| Dm7b5| G7| Cm|

item: form=[Intro|4] [A|16]x2 [Solos] [A|16] [Outro]&fermata
nrk:0.6
So What (Miles Davis)

M) [A]
C) | D-7 | % |

M) [Solos]
C) | D-7 | % |

M) [Outro]
C) | D-7 |

The first entry performs Blue Bossa transposed +2; the second declares a performance form that replaces the song's own.

11.2 Book (no overrides)

nrk-book:0.6
name: My Real Book — Vol. 1

nrk:0.6
Autumn Leaves (J. Kosma)
…

nrk:0.6
All The Things You Are (J. Kern)
…

11.3 Single-song collection

nrk-playlist:0.6
name: Solo Spot

nrk:0.6
Naima (J. Coltrane)
…

It degrades transparently: a collection with a single block is valid.


12. Summary

Concept Syntax Section
Book opening nrk-book:<v> §3
Playlist opening nrk-playlist:<v> §3
Collection header name: / desc: §4
Song block nrk:<v> … (snapshot) §5
Order order of the blocks in the file §5
Entry override item: key=value … (playlist only) §6
Entry parameters transpose / notes / form §6.1
Entry form form= (FORM grammar, rest-of-line) §6.2, §8
Form replacement item form replaces the song's FORM) §8.1
Split at nrk: lines, before musical parsing §9.1
Portability all snapshot; cover/tags/roles outside §7

This document defines collections (books and playlists) as neumaRk's portable container layer, built by reuse around the song documents and the song form (neumaRk_play_and_form.md).