Song versions¶
This document defines the syntax and semantics of versions in neumaRk: a mechanism for representing multiple variants of the same song in a single file (alternative arrangements, reharmonizations of single sections, complete rewrites).
The user chooses which variant to view/perform through the UI; the preference is persistent in the user-index and not in the NRK file.
1. Definition¶
A version is an alternative variant of a portion of the song, delimited by a named block of the form:
%%NAME
… content …
%%end
There are two classes of blocks:
- Default — block
%%NAMEwithout a label, is part of the linear flow of the song (it is the "canonical" version the reader sees by default); - Variant — block
%%NAME "label"with a label, lives alongside the flow. It is activated explicitly by the user.
A variant replaces all the occurrences of the same-named default block during performance/rendering.
1.1 Minimal example¶
M) [Intro]
… original intro …
%%BRIDGE
M) [Bridge]
… original bridge …
%%end
M) [A]
… original final A …
%%BRIDGE "Bill Evans version"
M) [Bridge]
… Bill Evans bridge …
%%end
The user opens the song and sees the canonical version. By selecting "Bill
Evans version" from the UI selector, the %%BRIDGE block is replaced
by the variant; the rest of the song (Intro, A) remains unchanged.
2. Syntax¶
2.1 Opening the block¶
%%NAME default block
%%NAME "label" variant block
%%must be at the beginning of the line (possibly preceded by spaces only, according to the general whitespace rules of neumaRk).NAMEis an identifier: one or more letters/digits/underscores, case-sensitive. No internal spaces."label"(optional, present only in variants) is a textual container"…"adjacent to the NAME, with a separating space. It admits the unified markup (neumaRk_text_markup.md).
2.2 Closing the block¶
%%end
%%endmust also be at the beginning of the line.- It closes the most recently opened block.
- A
%%endwithout an open block produces warning W148.
2.3 Block content¶
A block contains one or more valid datapacks (see
neumaRk_datapack.md). All the musical rules (markers, chords,
notes, dynamics, etc.) apply normally inside the block.
2.4 Nesting not allowed¶
A %%NAME block cannot be opened inside another block. The
parser produces warning W149 if it encounters %%X while a block is
open.
2.5 Reserved: %%¶
The sequence %% at the beginning of a line is reserved for versions blocks.
It is not allowed in other contexts of the language (NRK comments use
//, see neumaRk_datapack.md for the spec of single-line comments).
3. Structural position¶
3.1 Standalone between datapacks¶
The %%NAME blocks live between musical datapacks, not
inside them. The structure of the document is an alternating sequence of:
- normal datapacks (flow common to all versions);
- default
%%NAMEblocks (named sections of the flow); - variant
%%NAME "label"blocks (variants of the named sections).
[datapack] [datapack] %%BRIDGE [datapack] %%end [datapack]
└─ default ─┘
[datapack] %%BRIDGE "Bill Evans" [datapack] %%end
└─────────── variant ───────────┘
3.2 Position of variants¶
The variants %%NAME "label" may appear in any position
of the document (recommended: immediately after the same-named default
block, or at the end of the document). The matching is by name, not by position.
4. Substitution semantics¶
4.1 Fundamental rule¶
When the user activates the variant %%NAME "label", all the
occurrences of the default block %%NAME in the document are
replaced by the content of the variant.
The portions of the song outside blocks (normal datapacks) remain unchanged in all versions: they belong to the "common trunk".
4.2 Multiple occurrences of the default¶
If a default %%NAME block appears multiple times (e.g. AABA with three distinct %%A),
a single variant %%NAME "label" replaces all
the occurrences.
%%A
… A original …
%%end
%%B
… B …
%%end
%%A
… A original (second occurrence, may be musically identical
or varied) …
%%end
%%A "miles"
… A Miles version …
%%end
Activating "miles": both default %%A are replaced by the
Miles version. For per-position variants (e.g. only the second A is
different), use distinct names: %%A1, %%A2.
4.3 Orthogonal M) markers¶
The markers of the M) line internal to a %%NAME block are
independent of the block name. The parser does not require that
M) [Bridge] appear inside %%BRIDGE: it is the author's convention
to name them the same, but it is not constrained.
%%PEDAL
M) [A pedal]
… …
%%end
PEDAL is the name of the block (for the versions selector); A pedal is
the marker of the section (for PLAY/FORM, render, navigation).
4.4 Total rewrites¶
For complete arrangements (e.g. "Round Midnight, Miles arrangement"),
the author may enclose the entire song in a default %%NAME block
(with a name of choice: %%SONG, %%MAIN, etc.) and provide the rewrite
as a variant.
%%SONG
M) [Intro]
… complete original song …
M) [Outro]
…
%%end
%%SONG "Miles Davis arrangement"
M) [Intro Miles]
… complete Miles arrangement …
M) [Coda]
…
%%end
There is no reserved keyword for "the whole song": any name works, the author chooses the one they prefer.
5. Optional header HV)¶
The document header (neumaRk_header.md) admits a new optional
entry HV) to explicitly declare the available versions
and the default one:
HV) versions: [original, miles, jarrett] default=original
5.1 Syntax¶
HV) versions: [<label1>, <label2>, …] [default=<label>]
versions:mandatory keyword.- List of labels in square brackets, separated by commas.
default=<label>optional: specifies which variant to show at the first opening (in the absence of a user preference). In the absence ofdefault=, the default is the default flow (%%NAMEblocks without a label).
5.2 Functions of HV)¶
- Documentation: makes the song versions explicit in the header.
- UI ordering: the labels are presented in the UI selector in the declared order.
- Named label of the default: without
HV), the default is "unnamed"; withHV)it may receive a name (e.g.original) and appear in the selector together with the variants.
5.3 HV) optional¶
In the absence of HV), the variants are deduced from the
%%NAME "label" blocks present in the document. The order is the order of
appearance in the file. The default is the unlabeled flow.
5.4 Discrepancies¶
A label declared in HV) but absent from the document (or vice versa)
is not an error: the UI selector shows only the variants
actually present. It is the author's responsibility to maintain
consistency.
6. User preference¶
The "current version" state is a user preference saved in
the user-index Firestore (e.g.
users/{uid}/song_view_state/{songId}.version).
- At first opening, the document shows the default (flow without
labeled
%%NAMEblocks, or whatever is declared inHV) default=). - The user changes version through the UI selector (badge with dropdown).
- The choice is persistent for that specific song for that user.
The version state is never written into the NRK file: the file is immutable with respect to the reading preference.
7. Diagnostics¶
7.1 Diagnostic codes¶
| Code | Description |
|---|---|
| W147 | %%NAME block not closed (missing %%end by end of document) |
| W148 | Orphan %%end (no open block) |
| W149 | %%NAME block nested inside another block |
| W150 | Malformed HV) (expected versions: [list] [default=label]) |
7.2 Non-errors¶
- Variant without a same-named default (
%%X "label"but no%%Xdefault): the variant is ignored during performance, but remains in the file. Render UI may flag it as "orphan". - Default without variants (
%%Xonly): allowed; the block is a simple section "prepared for future variants". - Label
%%X "label"repeated multiple times: the last wins (silently), or the render shows a UI warning.
8. Examples¶
8.1 Days of Wine and Roses with Bill Evans bridge¶
HT) Days of Wine and Roses
HC) Henry Mancini
HK) F
HM) 4/4
HV) versions: [original, bill_evans] default=original
M) [Intro]
… intro …
M) [A]
… A original …
%%BRIDGE
M) [Bridge]
… bridge original …
%%end
M) [A]
… final A original …
%%BRIDGE "bill_evans"
M) [Bridge]
… Bill Evans reharmonized bridge …
%%end
8.2 Round Midnight, total Miles rewrite¶
HT) Round Midnight
HC) Thelonious Monk
HV) versions: [original, miles] default=original
%%SONG
M) [Intro]
… standard intro …
M) [A]
… original A …
M) [B]
… original B …
M) [A]
… final A …
%%end
%%SONG "miles"
M) [Intro Miles]
… Miles intro …
M) [A]
… A with changed chords …
M) [B]
… B with added phrase …
M) [Coda]
… Miles coda …
%%end
The user chooses "miles" from the selector → the original %%SONG block is
replaced by the rewrite.
8.3 AABA with A "miles" replacing all the A¶
%%A
… original A …
%%end
%%A
… (second occurrence, identical or varied) …
%%end
%%B
… B …
%%end
%%A
… final A …
%%end
%%A "miles"
… Miles version of the A …
%%end
Activating "miles": the three default %%A are replaced by the variant.
The %%B remains unchanged.
8.4 Per-position variant (distinct names)¶
%%A1
… first A …
%%end
%%B
… B …
%%end
%%A2
… second A (slightly different) …
%%end
%%A2 "minor key"
… A2 in minor mode …
%%end
Only the second A is replaceable by the "minor key" variant. The first
A is not involved because it has a different name (%%A1).
9. Summary¶
| Concept | Syntax | Section |
|---|---|---|
| Default block | %%NAME … %%end |
§2.1 |
| Variant block | %%NAME "label" … %%end |
§2.1 |
| Block closing | %%end |
§2.2 |
| Block position | standalone between datapacks, no nesting | §3.1 |
| Substitution | variant replaces all default %%NAME |
§4.1 |
| M) markers | orthogonal to the block name | §4.3 |
| Total rewrite | enclose the song in a single block (e.g. %%SONG) |
§4.4 |
| Header | HV) versions: [list] default=label (optional) |
§5 |
| User preference | user-index Firestore, not NRK | §6 |
This document defines the song versions in neumaRk: a robust and granular mechanism for representing alternative arrangements, targeted reharmonizations and complete rewrites of the same song within a single file.