Testo cantato (riga L))¶
STATO: SPEC. §1–§7 sigillate 2026-05-23 (semantica di deduzione della riga
L)inline). §8 (blocco di lyrics per sezioneLYRICS)) è DESIGN 2026-05-27 con decisioni sigillate, implementazione in corso (§8.4.1 pickup sigillato 2026-05-28) — vedidocs/feature-lyrics-sections-and-editions.md. Binding e ordine diL)non sono ridefiniti qui: vedineumaRk_datapack.md §2.1e §3. Decisioni di sigillo e note residue in §7; follow-up lato codice indocs/feature-deduction-spec-audit.md.Questo file IT è la source of truth; la versione EN (
../en/neumaRk_lyrics.md) la rispecchia.
1. Definizione¶
La riga L) (Lyrics) porta il testo cantato, sillaba per sillaba, allineato
agli eventi della riga N) a cui è legata. È un layer parallelo: non altera
ritmo né flusso. Più righe L) consecutive dello stesso rigo formano strofe
distinte (multi-verse).
2. Posizione strutturale e binding¶
Marcatore, opzionalità e ordine logico sono definiti in neumaRk_datapack.md
§2.1 e §3 (ordine implicito: L) è opzionale e ultima del gruppo di note).
La riga lega alla N) del proprio gruppo/rigo; la voce 2 (N2) ha le proprie
righe L) (vedi neumaRk_voices.md).
3. Allineamento count-based (solo note, non pause)¶
La corrispondenza è posizionale per conteggio, left-to-right, ma calcolata solo sugli eventi-nota: le pause non ricevono sillabe.
N) | c4 d r e |
L) | la la sol |
↑ ↑ ↑ ↑
la la (pausa: niente) sol
- Il contatore delle sillabe avanza solo sulle note effettive (
isNote()); su una pausa si emette un padding vuoto (mantiene l'allineamento posizionale). - Token
.= placeholder: nessuna sillaba su quella nota (la nota resta senza testo, ma la posizione è consumata). - Token in eccesso oltre il numero di note: emette W131 (come
D); allineato 2026-05-23, follow-up parser).
4. Strofe multiple (multi-verse)¶
Ogni riga L) consecutiva dello stesso rigo è una strofa successiva:
N) | c d e f |
L) | first verse syllables… | ← strofa 1
L) | second verse… | ← strofa 2
- Limite: 10 strofe per misura/rigo; le righe oltre la decima sono scartate silenziosamente.
- Padding fra strofe: per ogni strofa, le note senza token ricevono una sillaba vuota, così tutte le note hanno lo stesso numero di strofe (allineamento verticale fra versi).
5. Meccanica delle sillabe¶
Ogni token di testo è una parola, eventualmente sillabata con -:
| Forma | Effetto |
|---|---|
parola |
una sillaba (parola intera) sulla nota corrente |
pa-ro-la |
tre sillabe su tre note consecutive; le sillabe non finali sono marcate word_continues (trattino di sillabazione in render) |
_ |
melisma: estende la sillaba precedente sulla nota corrente (nessuna nuova sillaba) |
. |
placeholder: nessuna sillaba (vedi §3) |
-coda |
token con - iniziale: continuazione della parola precedente — retro-marca l'ultima sillaba emessa come word_continues e aggiunge coda come sillaba successiva (forma per-sillaba prodotta dal serializer) |
Dettagli di robustezza (come da parser):
- le sillabe vuote generate da trattini spurii (
-mar,mar--ti,-isolato) sono scartate; - una sillaba è
word_continuesse esiste una sillaba non vuota dopo di essa nello stesso token (o se un token di continuazione-Xsegue).
6. Esempi¶
N) | c4 d e f |
L) | Ave- _ ma- ri-a |
Ave (con trattino di sillabazione) → _ estende Ave sulla 2ª nota →
ma/ri proseguono; a chiude la parola.
7. Decisioni (chiuse 2026-05-23) e note residue¶
Chiuse:
- Eccesso di sillabe ✓ — emette W131 come
D)(era silent drop; follow-up parser indocs/feature-deduction-spec-audit.md). - Meccanica di §5 normativa ✓ — sillabazione, melisma
_, continuazione-come descritti.
Note residue (comportamento attuale documentato come normativo salvo revisione, non bloccanti):
- Cap 10 strofe: oltre la decima, silent drop. Limite confermato; il comportamento su overflow (silent vs warning) resta rivedibile.
- Pause: interrompono sempre il conteggio sillabe — la pausa non riceve testo
e il melisma
_non la "scavalca". Normativo. - Forma di sillabazione canonica del serializer: il parser accetta sia
pa-ro-lasia la forma per-sillabapa- -ro- -la; quale forma il serializer emetta è una scelta di output separata (non influisce sul parsing), da fissare quando si lavora al round-trip serializer.
8. Blocco di lyrics per sezione (riga LYRICS))¶
DESIGN 2026-05-27, decisioni sigillate. Roadmap e razionale in
docs/feature-lyrics-sections-and-editions.md.
8.1 Scopo e relazione con L)¶
Il blocco LYRICS) è un modo alternativo di scrivere le stesse strofe
che L) scrive inline. Invece di allineare le sillabe alle note di un
singolo datapack, porta il testo per sezione e lascia al motore il
compito di distribuire le sillabe sulle note di quella sezione
automaticamente.
LYRICS) non introduce un modello di lyrics diverso: alimenta gli
stessi slot Lyric per-nota che alimenta L) (§3, §5). La riga L)
inline resta pienamente valida; i due si compongono (§8.5).
L'equivalenza con L) vale però solo per il rendering: il blocco porta
informazione che l'inline non sa esprimere — l'edizione del testo
(lingua + autore, §8.8). Per questo il round-trip serializer conserva la forma scelta
dall'utente: un blocco LYRICS) riemette LYRICS) (verbatim, lingua inclusa),
una riga L) riemette L). Il serializer NON converte automaticamente l'uno
nell'altro; la conversione esplicita è un'azione utente separata (menu
contestuale WRITE, non ancora implementata). Implementazione: Music::lyrics_blocks
(blocco grezzo + posizione) + Lyric::from_section (sopprime la ri-emissione
inline dei versi che round-trippano come blocco).
8.2 Sintassi¶
LYRICS)
[A] sillabe del verso…
[B] sillabe del verso…
[A] (una seconda riga [A] = secondo verso su A)
- Il blocco si apre con una riga il cui primo token non-blank è il marker
LYRICS)(opzionalmente seguito da un tag di edizione[lingua] [<autore>], §8.8). - Ogni entry inizia con un riferimento di sezione
[NAME](§8.3). Il testo dopo]sulla stessa riga, e/o le righe successive non-blank che non iniziano con[, sono le sillabe di quell'entry. - L'entry può iniziare con un gruppo pickup
<…>— sillabe che legano alle note che precedono la sezione (anacrusi). Vedi §8.4.1. - Righe vuote dentro il blocco sono ammesse (separatori visuali): non chiudono il blocco.
- Il blocco si estende fino al primo top-level marker (
LYRICS),PLAY),FORM),%%…) o prefisso di datapack (M) N) C) A) D) L) F)).
Forma compatta ed estesa sono entrambe accettate ed equivalenti:
LYRICS) LYRICS)
[A] questo è un testo ≡ [A]
questo è un testo
La grammatica delle sillabe è identica a L) (§5): pa-ro-la,
melisma _, placeholder ., continuazione con - iniziale.
8.3 Riferimento di sezione e posizione strutturale¶
[NAME] è lo stesso reference-by-name usato da PLAY) / FORM)
(neumaRk_play_and_form.md §3.1): il matching è per text-equality sul
NAME con markup strippato (neumaRk_text_markup.md §7.1). Un blocco
LYRICS) può apparire ovunque tra i datapack; la posizione nel file
non influenza la sezione a cui un entry si lega (binding by name, come
%%versions).
Un riferimento a una sezione inesistente è reference-broken: warning W157 (non bloccante, §8.9).
8.4 Aggregazione di sezione cross-datapack¶
È il comportamento distintivo: le sillabe di [A] si distribuiscono su
tutte le note della sezione [A], concatenate in ordine di flow,
attraversando i confini datapack / system / misura. (Per contro
L) inline è locale a un singolo datapack.)
Una misura appartiene alla sezione il cui marker […] è il più recente
in cima o prima della misura stessa (le annotazioni "…" non
aprono sezione, neumaRk_markers.md §3.1, §4.1). Una corsa massimale di
misure consecutive con la stessa sezione corrente è un'occorrenza di
quella sezione.
M) [A]
N) a b c d
N) e f g a ← stessa [A], datapack successivo, nessun marker
LYRICS)
[a] mol-te sil-la be su_un ri-go
└─ distribuite su a b c d e f g a (8 note, una occorrenza, cross-datapack) ─┘
Dentro un'occorrenza, le note (primo rigo, voce 1 — §8.7) sono raccolte
in ordine di flow e le sillabe legate esattamente come in L) (§3):
positional-by-count, le pause non ricevono sillabe, . placeholder,
_ melisma.
Più occorrenze (template). Se [A] ricorre più di una volta (es.
AABA), l'entry è un template applicato a ogni occorrenza: le
stesse sillabe sono legate, indipendentemente, a ciascuna occorrenza. Le
sillabe non si distribuiscono attraverso le occorrenze. (Testo
diverso per-occorrenza — es. strofa 1 / strofa 2 cross-ripetizione — è
fuori scope; usa nomi distinti [A1]/[A2], §8.10.)
8.4.1 Sillabe pickup (anacrusi) — <…>¶
DESIGN 2026-05-28, decisioni sigillate. Chiude il gap dei testi che devono iniziare prima del bordo di sezione (anacrusi). Roadmap in
docs/feature-lyrics-sections-and-editions.md§2.5.
Un entry può iniziare con un gruppo pickup delimitato da <…>. Le
sillabe nel gruppo legano alle ultime N note che precedono
l'occorrenza della sezione in ordine di flow, dove N è il conteggio
sillabe del gruppo (dopo espansione della grammatica: pa-ro-la vale
3, _ e . valgono 1 ciascuno). Le sillabe dopo > continuano
normalmente dalla prima nota dell'occorrenza (§8.4).
M) [intro] | a4 a a a |
M) [intro] | h2 r4 c,8 d |
M) [A] | e |
LYRICS)
[A] <do re> mi
│ └─ prima nota dell'occorrenza di [A]
└──────── ultime 2 note della sezione precedente ([intro]: c,8 d)
Dove atterra il pickup. Per ogni occorrenza di [NAME], il pickup
scandisce all'indietro dalla prima nota di quell'occorrenza sulla
corsa contigua di note la cui sezione corrente non è [NAME]. Le N
ultime note di quella corsa ricevono le sillabe pickup (le pause sono
saltate, esattamente come in §3 / §8.6). Lo scan si ferma alla:
- prima nota appartenente a
[NAME](non entra mai nell'occorrenza stessa né in una occorrenza precedente di[NAME]); - testa del brano (nessuna nota prima della prima occorrenza di
[NAME]).
Volte. Quando la corsa precedente contiene volte
(|[1.] … |[2.] …, neumaRk_flow_and_repeats.md §6), solo la
volta finale contribuisce note al pickup; le misure interne a volte
precedenti sono saltate dallo scan all'indietro. L'intuizione è che
l'anacrusi è la rincorsa verso [NAME] lungo il percorso che la
musica effettivamente prende l'ultima volta — quello che termina in
[NAME]. Le misure non-volta contribuiscono normalmente.
Più occorrenze (template). Come per le sillabe post->, il gruppo
pickup è un template: applicato indipendentemente a ciascuna
occorrenza di [NAME], ciascuna guardando indietro nella propria
corsa di note non-[NAME]. In AABA, ogni [A] ha il proprio pickup
dalle note immediatamente precedenti.
Overflow / nessuna nota precedente.
- Se la corsa precedente ha zero note (es. l'occorrenza è all'inizio
del brano), il pickup è silenziosamente droppato per quella
occorrenza — nessun warning. Le sillabe post-
>legano normalmente. - Se
0 < disponibili < N(overflow parziale: la corsa esiste ma è più corta del pickup), le note disponibili ricevono le sillabe pickup finali (le iniziali in eccesso sono droppate) e si emette W158 una volta per occorrenza affetta (non bloccante, §8.9). Le sillabe post->legano normalmente comunque.
Accumulo verse (slot del proprio body, OVERRIDE). Il pickup di un'entry occupa lo stesso slot del body di quella entry sulle pre-notes, sostituendo le sillabe già presenti su quel slot (sigillato 2026-05-28, dopo test su brano reale):
- Il body occupa lo slot naturale della sezione,
verseCount[NAME]— la prima riga libera della sezione, come un'entry senza pickup (§8.5). - Il pickup occupa lo stesso slot del proprio body sulle
pre-notes:
pickupSlot = bodySlot. Se le pre-notes hanno già sillabe su quel slot (ad es. il body della sezione precedente che canta quelle note), il pickup le sovrascrive. Se non le hanno, il pickup ci scrive direttamente (padding implicito).
L'effetto musicale corrisponde alla convenzione tradizionale: la
strofa di [NAME] "ruba" letteralmente le ultime N note del
predecessore alla strofa di quel predecessore (stessa lingua / stessa
posizione di verse), e ci canta l'anacrusi.
Esempio brano multi-strofa (port = slot 0, eng = slot 1): le ultime 2
note di [B] ospitano due sillabe pickup: <E vol> di [A2] port
sostituisce le ultime 2 sillabe del body [B] port (slot 0); <So I>
di [A2] eng sostituisce le ultime 2 del body [B] eng (slot 1). Il
body [A2] (port e eng) resta sui suoi slot naturali (0 e 1), in
continuità con [A1] e [B]. Per ottenere questa sostituzione,
l'engine processa prima tutti i body, poi tutti i pickup
(così il pickup vede e sovrascrive il body già scritto sulle pre-notes).
Vincoli.
- Un solo gruppo pickup per entry, deve venire immediatamente dopo
[NAME](e whitespace opzionale), prima di qualunque sillaba post->. <>vuoto è un no-op silenzioso: consumato senza effetto, nessun warning. Le sillabe post->legano come se il gruppo non esistesse.<e>sono riservati solo dentro gli entryLYRICS); non sono token della grammatica delle sillabe altrove (L),D)).- Dentro
<…>la grammatica è identica aL)(§5):pa-ro-la,_,., continuazione-iniziale. Un token di continuazione-Xcome primo token del gruppo pickup è droppato (non c'è una sillaba precedente nello stesso entry da continuare). - Binding rigo/voce identico al corpo dell'entry: primo rigo, voce 1 (§8.7).
8.5 Accumulo dei versi (L) inline ++ blocchi LYRICS))¶
Per ogni sezione, i versi si impilano top-to-bottom in questo ordine (sigillato 2026-05-27):
versi(sezione) = [ versi L) inline, in ordine ] ++ [ entry [NAME] dai blocchi LYRICS), in ordine di file ]
Ogni entry [NAME] (una riga) aggiunge un verse. Due entry [A]
(stesso blocco o blocchi diversi) aggiungono due versi, in ordine di
apparizione.
Per tenere i versi allineati verticalmente lungo una sezione che si
estende su più datapack (i cui conteggi inline possono differire), il
motore prima padda ogni nota della sezione a
n_inline = max(note.lyrics.size()) su tutta la sezione, poi appende
ogni verse di blocco a un indice uniforme su tutte le occorrenze.
I tre frammenti seguenti producono lo stesso risultato a due versi su [A]:
// (a) tutto inline // (b) misto // (c) tutto a blocco
N) ... N) ... N) ...
L) tes-to u-no L) tes-to u-no LYRICS)
L) tes-to du-e LYRICS) [A] tes-to u-no
[A] tes-to du-e [A] tes-to du-e
8.6 Regole di allineamento (riuso da L))¶
Identiche a §3 e §5: positional-by-count sulle note, le pause non
ricevono sillabe, sillabazione pa-ro-la (word_continues), melisma
_, placeholder ., continuazione - iniziale. Sillabe in eccesso
sulle note di un'occorrenza emettono W131 (come L) / D)); note
in eccesso sulle sillabe ricevono un Lyric{} vuoto (padding).
8.7 Binding rigo / voce¶
Un entry LYRICS) lega sempre al primo rigo, voce 1 (la linea
vocale principale) — sigillato 2026-05-27. Per lyrics su altri righi
o sulla voce 2 (N2) si usa la riga L) inline, che ha già quella
granularità (neumaRk_voices.md). Il blocco scambia la granularità
per-voce con la comodità per-sezione.
8.8 Edizioni del testo (LYRICS) [lingua] [<autore>])¶
DESIGN 2026-05-30, sigillato (Fase B). Generalizza la multilingua (Fase 3): la "lingua" è ora un caso particolare di edizione del testo. Roadmap e decisioni in
docs/feature-lyrics-sections-and-editions.md§9-§11.
Un'edizione è una versione del testo cantato; un brano può averne più
d'una. L'header LYRICS) può portare due elementi opzionali, su assi
distinti e separati anche sintatticamente:
- un token lingua (
LYRICS) pt-br): un codice (it,en,pt-br, …; forma[a-z]{2,3}(-regione)?, case-insensitive, normalizzato in minuscolo) — una traduzione; - un autore fra
<…>(LYRICS) en <Frank Sinatra>): chi ha scritto quel testo. Testo libero, può contenere spazi (le parentesi delimitano: niente euristiche di disambiguazione).
| Forma | Natura |
|---|---|
LYRICS) nudo / L) inline |
neutra (default, no lingua/autore) |
LYRICS) pt-br |
lingua |
LYRICS) en <Frank Sinatra> |
lingua + autore |
LYRICS) <Al Jarreau> |
autore-only (no lingua) |
Un'edizione è identificata dalla coppia (lingua, autore). Sono ammesse
più edizioni nella stessa lingua con autori diversi (vocalese /
traduzioni concorrenti: en <Jon Hendricks> + en <Eddie Jefferson>).
Default — Rule A¶
- neutra (no lingua, no autore) → testo di default;
- lingua (ha lingua, ± autore) → intrinseca, concorre al default;
- autore-only (autore senza lingua) → opt-in, mai default.
Il testo di default è il neutro (L) inline o LYRICS) nudo) se
presente, altrimenti la prima edizione-lingua in ordine di file. Se non
esiste alcuna edizione intrinseca (solo <autore>-only) il brano apre
strumentale: nessun testo di default, le edizioni si attivano dalla
selezione.
Selezione¶
L'edizione attiva è una user preference scalare (una per brano,
chiave = la coppia lingua+autore), selezionabile da menu — stesso pattern
di %%versions ma scalare. Seleziona quale edizione alimenta gli slot
Lyric per-nota; gli entry delle altre edizioni non vengono legati. Se la
coppia attiva non esiste fra le edizioni, si usa il default (Rule A); se
non c'è default (strumentale), nessuna lyric da blocco viene legata.
La riga L) inline è l'edizione neutra di default: si accumula
secondo §8.5 quando l'edizione neutra è il testo mostrato.
Metadati (titolo / autore)¶
- Titolo per lingua: un titolo per lingua (condiviso da tutte le
edizioni di quella lingua — è la traduzione del nome del brano, non cambia
col paroliere), dichiarato col tag
[lingua]sui titoliHT)(neumaRk_header.md§8.1). Vive nei metadati, non nel testo del blocco. - Autore del testo: per il default →
lyricsByglobale (HCL)); per un'edizione taggata → il gruppo<…>sul bloccoLYRICS). Per l'autore- only il nome È il lyricsBy di quell'edizione. Il vecchio credit per-linguaHCL) … [lingua]è rimosso (neumaRk_header.md§9.2).
L'asse edizione è ortogonale all'asse %%versions: due scelte utente
indipendenti che si compongono. Il filtraggio versioni
(applyVersionFiltering) riscrive prima il flow; le lyrics dell'edizione
attiva si legano poi by-name alle note residue. Le lingue disponibili sono
dedotte dai blocchi LYRICS) + dai tag [lingua] dei titoli; non c'è
header di dichiarazione (HL) resta fuori scope, come per l'opzionale HV)).
8.8.1 Ponte titolo ↔ lingua¶
Un titolo che porta un tag lingua (neumaRk_header.md §8.1, es.
HT) No More Blues [EN]) è legato a quel codice. Aprire il brano come
quel titolo (es. da un risultato di ricerca) preseleziona la lingua per la
sessione: il titolo mostrato e la lingua delle lyrics ne seguono la scelta.
È un override di sessione (come un parametro URL): non sovrascrive
una user preference salvata, che resta settabile dal menu.
8.9 Diagnostica¶
| Codice | Severità | Descrizione |
|---|---|---|
| W157 | WARNING | LYRICS) [NAME] riferisce una sezione inesistente (reference-broken) |
| W158 | WARNING | gruppo pickup <…> di LYRICS) eccede la corsa di note precedenti disponibile (corsa più corta di N, eccesso iniziale droppato) — una per occorrenza affetta; silent skip se la corsa è vuota (§8.4.1) |
| W131 | WARNING | sillabe in eccesso sulle note di un'occorrenza (condiviso con L) / D)) |
Tutte non bloccanti. (Il cap di 10 strofe per nota, §4, vale sul totale inline+blocco.)
8.10 Fuori scope (MVP)¶
- Testo per-occorrenza (AABA che canta parole diverse a ogni passata
della stessa
[A]): non coperto — i versi si impilano verticalmente, non per-occorrenza. Workaround: nomi sezione distinti[A1]/[A2]. - Volte
|[1.]/|[2.]con testo diverso per ending. - Binding multilingua a titoli alternativi (Fase 3, §8.8).
8.11 Esempi¶
Due versi su [A], uno su [B], [Instrumental] lasciato senza testo:
M) [A] | c4 d e f |
M) [Instrumental] | g a b c |
M) [B] | c b a g |
LYRICS)
[A] questo è il primo verso qui
[A] e qui passa il secondo verso
[B] il bridge ha le sue parole proprie
Occorrenza cross-datapack (una [A] su due datapack):
M) [A]
N) c d e f
N) g a b c
LYRICS)
[A] ot-to sil-la be su due ri-ghi
Anacrusi con pickup (§8.4.1):
M) [intro] | a4 a a a |
M) [intro] | h2 r4 c,8 d |
M) [A] | e |
LYRICS)
[A] <do re> mi