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 reader chooses which variant to view/perform; the choice is a preference kept by the host and not in the NRK file (§6).
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 reader opens the song and sees the canonical version. By choosing "Bill
Evans version", 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.%%endcloses the version region and returns to the common trunk.- A new
%%NAMEcloses the open block implicitly: a chain of alternatives takes a single%%end, at the end. - A
%%endwithout an open block produces warning W148. - A
%%NAMEblock left unclosed by the end of the document produces warning W147: everything up to the end of the file is treated as part of it.
%%INTRO "standard"
// … standard intro …
%%INTRO "adams" ← implicitly closes the previous block
// … Adam's Apple intro …
%%end ← closes the region: back to the common trunk
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. Since nesting does not
exist, a %%X encountered while a block is open has only one possible reading:
the previous block has ended (§2.2, implicit close).
Warning W149 ("nested block") is retired: the code stays reserved and must not be reused.
2.4.1 default is a reserved word¶
default cannot be used as a NAME (%%default) nor as a label
(%%INTRO "default"), case-insensitively: it is the name under which the
selector presents the canonical block, and the special value of
HV) … default=. A namesake would produce two indistinguishable entries in the
selector. Violation → warning W151 (the block keeps working: the diagnostic
asks for a rename).
2.4.2 Empty block¶
A block may contain no datapack at all:
%%INTRO "no intro"
%%end
It means: in this version the section is not there. Selecting it makes the section disappear from the flow.
2.4.3 What this version is: INFO)¶
To say what a version is, use INFO) (neumaRk_datapack.md §11.1), written
at the head of the block, before any musical row:
%%INTRO "live78"
INFO) "Montreux live" Faithful transcription of the 4 June 1978 live set.
Special attention to the articulation of the head.
M) [Intro]
// … music …
%%end
The first INFO) of the block counts — at the head of its first datapack, or
standing alone right below %%NAME. One further down the block is information
about the score and has nothing to do with choosing the version. The canonical
block may have one too.
The text is one and shows up in two places: in the selector, to choose with
(the label is the title, the body is the text), and on the score, while that
version is being read — where the label is engraved and the body opens on
request. The selector shows the INFO) of every variant, including the ones not
selected: that is exactly what it is for.
A
"…"line written below%%NAMEis no longer a description: it opens a datapack and will most likely become an engraved annotation.
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¶
A NAME occupies one or more slots in the flow of the song. The slot is the
position of the anchor block: the canonical %%NAME block if the document
has one, otherwise the first block of that NAME in source order. The other
blocks are out-of-flow declarations.
When the user activates a variant, all the occurrences of that NAME show the chosen content.
The portions of the song outside blocks (normal datapacks) remain unchanged in all versions: they belong to the "common trunk".
Intended consequence: a song in which all the blocks of a NAME are labelled (no canonical) works. The first one is what is seen on opening, the others are selectable. In that case the selector does not offer the
defaultentry: it would have no content.
4.1.1 The writing context does not depend on the selection¶
A version block is hermetic with respect to the writing state:
- all the alternatives of a slot start from the same context, the one in force just before the region (relative octave, current duration, clef, meter, key, stave identity, harmony in force);
- after the region, the music continues with the context produced by the anchor block, not by the selected one.
Without this rule the octave and duration of the music that follows would depend on a variant the reader is not looking at, and selecting a variant written an octave higher would transpose the whole rest of the song.
Persisting harmony (neumaRk_chords.md §1.1: an empty chord cell carries the
previous chord on) follows the same rule, and it is the one part of the context
the reader sees printed. If the measure after %%end has an empty cell, the
harmony it inherits is the one the canonical block ends on, whichever version
is selected: the slashes and the chord restated at line start stay the same for
every reader.
When the blocks of a region end on different harmonies, the choice belongs to the
author and not to the selection — and precisely for that reason it is a choice
worth seeing: the editor reports W178, and it is enough to write the chord in
the measure after %%end, or to declare it with the context object ((@X)).
Measure numbers, instead, follow the active block: they number what is shown. A three-measure variant in place of a one-measure one moves the following numbering forward.
A block may be the only place where a stave's clef (or the meter, or the
key) is declared. If that block is not rendered, the declaration leaves with it.
To keep the context independent of any variant, write it where it actually
applies, with the measure-context object (neumaRk_datapack.md §7.3): it is
a construct of its own, and it can sit in a measure with no music.
The canonical block as a contract¶
The context that continues is the anchor block's. If the canonical block contains only a context object, it prints nothing (a context-only measure is not rendered) and becomes a declaration: the context the region guarantees to the rest of the song, whichever version is selected.
%%INTRO
N) (@F, g@3_8) |
%%INTRO "standard"
M) [Intro]
N) (@F) g,8 a b c d e f g |
%%end
M) [Theme]
N) a b c d |
- No selection: there is no intro, the canonical block produces no system.
The Theme starts in bass clef, from the reference
g@3, in eighths. - "standard": the intro is printed, and the Theme has the same pitches and the same durations.
This is how to set the bass clef when the default version has no intro: the
declaration goes in the canonical block, not in the variant. The variant still
starts from the region's entry context, so it declares its own clef ((@F) at
its head).
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.
Borrowing between occurrences. If an occurrence has no block for the chosen label, it shows a copy taken from another occurrence, read in the context of the point where that copy is written, not of the point where it appears. With the context object the author sets the contract themselves: at the head of the variant it makes it independent of where it is written, at the head of the canonical block (or of the music that follows) it declares the context the song resumes with.
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) accepts an optional HV) entry to
declare explicitly the versions of a block and the opening one. One line per
NAME:
HV) INTRO: [standard, adams] default=standard
HV) BRIDGE: [default, miles] default=miles
5.1 Syntax¶
HV) <NAME>: [<label1>, <label2>, …] [default=<label>]
<NAME>is the name of a%%NAMEblock, followed by:.- List of labels in square brackets, separated by commas.
default=<label>optional: which version to show at first opening, in the absence of a reader preference.default=defaultmeans the canonical block.- Several
HV)lines in the same header, one per NAME.
Old form rejected.
HV) versions: [a, b] default=ahad a scalardefault: on a song with two NAMEs it could not be expressed. It produces W150 pointing at the new form.
5.2 Functions of HV)¶
- Documentation: makes the song versions explicit in the header.
- Ordering: whoever offers the choice presents the NAMEs in the order of the
HV)lines; labels in the order of the list. - Opening version:
default=chooses which block is seen on opening. It does not move the anchor, which is structural (§4.1): it only changes what is shown.
5.3 HV) optional¶
In the absence of HV), the variants are deduced from the %%NAME "label"
blocks present in the document, in order of appearance, and the opening version
is the anchor one (§4.1).
5.4 Discrepancies¶
A label declared in HV) but absent from the document (or vice versa) is not
an error: the selector shows only the versions actually present, and a
default= without a match does not apply. It is the author's responsibility to
maintain consistency.
6. Reader preference¶
The "current version" state is a preference of the reader, kept by the host for that song.
- At first opening, the document shows the default (flow without
labeled
%%NAMEblocks, or whatever is declared inHV) default=). - The reader changes version through the choice the host offers.
- The choice holds for that specific song and for that person.
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: the rest of the file is treated as part of it |
| W148 | Orphan %%end (no open block) |
| ~~W149~~ | Retired — a new %%NAME closes implicitly (§2.2/§2.4) |
| W150 | Malformed HV), or old form HV) versions: […] (§5.1) |
| W151 | default used as a NAME or as a label (reserved word, §2.4.1) |
7.2 Non-errors¶
- All blocks labeled, no canonical one: not an error — the first
block in source order is the anchor (§4.1) and the selector does not offer the
defaultentry. - Default without variants (
%%Xonly): allowed; the block is a simple section "prepared for future variants". - Label
%%X "label"repeated multiple times: the last wins, with no diagnostic.
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) BRIDGE: [default, bill_evans] default=default
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) SONG: [default, miles] default=default
%%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) NAME: [list] default=label (one line per NAME) |
§5 |
| Reader preference | kept by the host, not in the NRK file | §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.