Articolazioni (riga A))¶
STATO: SPEC. §1-§7 sigillate 2026-05-23 (deduzione
A)attuale, già nel parser); §8-§12 sigillate 2026-05-24 (estensioni: modello token, glissatogl, span legatura/onda). Implementate end-to-end (parser Fase 3.1 + rendering 3.1b); stato/dettagli inneumaRk_changelog.md §0.6. Limite noto: la collisione verticale onda↔legatura è un follow-up di layout. Binding e ordine non sono ridefiniti qui: vedineumaRk_datapack.md §2.1e §3. Decisioni di sigillo in §7 (base) e §12 (estensioni).
1. Definizione¶
La riga A) (Articulations) porta le articolazioni e gli ornamenti da
applicare, posizione per posizione, agli eventi della riga musicale a cui è
legata. È un layer parallelo: non altera ritmo, durate o flusso, solo gli
attributi notazionali degli eventi.
2. Posizione strutturale e binding¶
Marcatore, opzionalità e ordine logico sono definiti in neumaRk_datapack.md
§2.1 (tabella marcatori) e §3 (ordine implicito: A) è opzionale e precede
la riga N) del proprio gruppo di note). In sintesi operativa:
A)lega alla riga sotto ("modello §4.A.5"): i suoi token sono messi in attesa (pending) e drenati sul primo target musicale successivo nello stesso gruppo/rigo.- Target del drain, in ordine di priorità:
- la chord-rhythm della riga
C)immediatamente sotto — solo per lo stave 0 (il chord-rhythm vive inMeasureShared), se laC)ha ritmo; - altrimenti la riga
N)dello stesso stave. - In multi-stave ogni rigo ha il proprio bucket di pending; la voce 2 (
N2) ha un bucketA)indipendente (vedineumaRk_voices.md §3.1).
3. Vocabolario¶
Ogni token è un simbolo (o combinazione) che mappa a un'articolazione o
ornamento. I token sono separati da spazio; più articolazioni sulla stessa
nota si scrivono come token unico senza spazi (es. >!).
| Token | Significato | Tipo |
|---|---|---|
- |
tenuto | articolazione |
> |
accento | articolazione |
! |
staccato | articolazione |
^ |
marcato | articolazione |
+ |
pizzicato (mano sx) | articolazione |
o |
fermata (sopra) | articolazione |
os |
fermata breve | articolazione |
ol |
fermata lunga | articolazione |
-! |
portato (tenuto+staccato) | combinazione |
>! |
accento staccato | combinazione |
tr |
trillo | ornamento |
m |
mordente | ornamento |
M |
mordente inverso | ornamento |
t |
gruppetto | ornamento |
T |
gruppetto inverso | ornamento |
, |
respiro | ornamento |
h |
armonico | articolazione (estensione §8+) |
v |
arco in su | articolazione (estensione §8+) |
n |
arco in giù | articolazione (estensione §8+) |
. |
placeholder: nessuna articolazione su quella posizione | — |
hper l'armonico (il simbolo°non è ASCII eoè già fermata);v/nper gli archi (nricorda il ⊓). A questi si aggiungono un token per-coppia (glissatogl, §9) e due span (legatura( ), onda~, §10), introdotti dal modello di token decomponibile in §8.
Il vocabolario è l'insieme chiuso della tabella sopra (più il placeholder
., i per-coppia/span delle estensioni §8+). Solo questi token sono articolazioni
valide; il charset di classificazione del parser deriva da questo insieme
(vedi §6 e §11). Un token fuori dal vocabolario non è un'articolazione valida.
I marcatori > e ^ rendono una riga univocamente articulations in fase di
classificazione (articulations_specific_marker): nessun'altra riga musicale li
usa isolati.
4. Allineamento count-based¶
La corrispondenza con gli eventi della riga target è strettamente posizionale
per conteggio (come neumaRk_dynamics.md §4.1), left-to-right:
N) | a8 b c d |
A) | > . ! ^ |
↑ ↑ ↑
accento staccato marcato (b: nessuna)
- Il token
.o un token vuoto = nessuna articolazione su quella nota. - Se i token sono meno delle note, le note residue restano senza articolazione (no-op).
- Se i token sono più degli eventi, gli extra sono scartati
silenziosamente (filosofia auto-fix; nota: a differenza di
D)non viene emesso un warning — vedi Decisioni aperte). - L'allineamento conta anche i rest (a differenza di
L), che li salta): una posizione sopra un rest è un evento a tutti gli effetti. È ciò che permette a uno span (§10) di coprire un rest (vi si scrive~e lo span prosegue).
5. Esempi¶
A) | > ! |
N) | c4 d e f | accento su c, staccato su e
A) | >! |
C) | C7 F7 | accento-staccato sul primo evento di chord-rhythm (stave 0)
6. Il vocabolario è parte della deduzione (fonte unica)¶
Il parser non è agnostico rispetto a questo vocabolario: per dedurre che una
riga prefix-less è A) deve riconoscerne i token. Storicamente il vocabolario era
diviso e duplicato — metà sintattica nel parser (charset di
articulations_line / articulations_specific_marker, usato per la
classificazione) e metà semantica nel renderer (nrkArticToModifiers, token-NRK →
codice VexFlow) — e le due metà divergevano (il charset ammetteva _ e lettere
isolate non mappate).
Modello normativo (deciso 2026-05-23): questo documento è la fonte unica. La
spec definisce token-NRK → significato musicale (es. !→staccato); il
significato è normativo, i codici VexFlow no (un altro renderer ne userebbe
altri). Da questa tabella derivano: il charset di classificazione e la
tokenizzazione del parser; la mappa significato → glifo del renderer.
7. Decisioni (chiuse 2026-05-23)¶
- Fonte unica ✓ — la spec è normativa; charset-parser e mappa-renderer ne derivano. Elimina il drift.
- Vocabolario = insieme chiuso ✓ — i simboli fuori tabella (es.
_, lettere isolate) non sono articolazioni valide; il charset va ristretto al vocabolario. - Eccesso di token ✓ —
A)emette W131 comeD)(era silent drop). - Significato normativo, VexFlow implementativo ✓ — la colonna "significato"
è vincolante; i codici
a-/a>/… sono nota d'implementazione.
Follow-up lato codice (D(L)→D(P), tracciato in
docs/feature-deduction-spec-audit.md), tutti ✅ fatti (Fase 3.1): charset di classificazione derivato dal vocabolario chiuso; W131 su eccesso token; W139 (validazione lessicale) su qualsiasi token con sequenza fuori-vocabolario, inclusa la lettera-frammento isolata (sdios,rditr).
Estensioni A) (sigillate 2026-05-24)¶
Le sezioni §8-§12 sono normative e implementate (parser Fase 3.1 + render 3.1b). Estendono il vocabolario per-posizione di §3 con: un modello di token decomponibile (§8), un token per-coppia (glissato
gl, §9) e due span (§10).
8. Modello del token: decomposizione e co-locazioni¶
Il vocabolario base (§3) usa, nel parser attuale, uno switch su token interi
(nrkArticToModifiers, con case ">!"). Le estensioni richiedono un vero
decompositore per-posizione, analogo a parseDynamicsToken di D).
Ogni posizione (token separato da spazi) è una concatenazione order-free
di elementi, decomposta con greedy longest-match sugli atomi multi-char
(prima os/ol di o, prima tr di t):
elemento :=
| onda ~[1-4]? ("…")? # §10.2 (cifra/etichetta solo in apertura)
| legatura-apre ( # §10.1
| legatura-chiude ) # §10.1
| staffa-apre [ ("…")? # §10.3 (etichetta solo in apertura)
| staffa-chiude ] # §10.3
| ottava-apre 8u | 8d # §10.4 (alta / bassa)
| ottava-chiude 8. # §10.4 (8 + punto)
| glissato gl # §9 (verso la nota successiva)
| fermata o | os | ol # greedy: os/ol prima di o
| trillo tr # greedy: tr prima di t
| gruppetto t | T
| mordente m | M
| per-nota 1ch - > ! ^ + , h v n
| placeholder . # nessun elemento su quella posizione
Conseguenza: -! e >! non sono più token speciali ma co-locazioni
(-+! = portato; >+! = accento-staccato). Tutte le combinazioni emergono
dalla concatenazione: (! = legatura-apre + staccato; >gl = accento + glissato.
La voce "combinazione" della tabella §3 resta valida come significato, non come
token atomico.
La decomposizione (tokenize) è separata dalla risoluzione degli span (post-pass), come
D)separaparseDynamicsTokendaextract_hairpins(§10).
9. Glissato fra note (gl)¶
gl sulla posizione di una nota = quella nota glissa verso la successiva. La
direzione (su/giù) è implicita dalle due altezze. È per-coppia, non uno span.
A) . gl . .
N) r4 a b r # a glissa verso b
Distinto dal glissato di singola nota (scoop/fall, entrata/uscita da una
nota), che vive in N) come modificatore fra parentesi — vedi
neumaRk_notes_and_durations.md (estensioni N).
10. Span¶
Due span, mutuati dal modello di D) (apertura/chiusura risolte in un post-pass).
10.1 Legatura di portamento ( ) (span delimitato)¶
Stile LilyPond: ( apre sulla nota della sua posizione, ) chiude sulla nota
della sua posizione; la curva copre dall'apertura alla chiusura.
A) . ( . . )
N) c d e f g # legatura da d a g
- Cross-barline: sì.
- Confinata al rigo: una legatura aperta a fine rigo si chiude lì con
warning; una
)orfana → warning, ignorata. - No sovrapposizione/annidamento (v1): al massimo una legatura aperta per
volta; un secondo
(mentre una è aperta → warning. (Annidamento rinviato.) - Apertura+chiusura sulla stessa nota (
()): degenere → ignorata/warning. - Co-locabile coi per-nota:
(!= legatura-apre + staccato.
10.2 Onda ~[1-4] (span per ripetizione)¶
Una linea ondulata sempre sopra il rigo. Unifica vibrato / shake / long-vibrato / laid-back: l'ampiezza è la larghezza visiva, l'etichetta ne dà il nome.
Ampiezza — cifra opzionale 1–4 (default ~ = livello 1):
~N(con cifra) apre un nuovo span di ampiezza N, chiudendo quello corrente;~(nudo) estende lo span corrente; se nessuno è aperto, ne apre uno di livello 1.
A) ~3 ~ ~ ~1 ~ ~ # onda grande su 3 note, poi onda piccola su 3
Estensione e rest: ~ consecutivi (anche cross-barline) = un'unica onda;
una posizione senza ~ (inclusa una misura vuota) chiude lo span. I rest non
interrompono (l'allineamento conta i rest, §4).
A) ~2 ~ ~ ~ | | ~3 ~ ~ ~
N) a4 b r c | d | a4 b r c
# └─ ampiezza-2 su a b r(rest) c ─┘ (mis.2 vuota → niente onda) └─ ampiezza-3 ─┘
Etichetta (opzionale, solo sul token di apertura): "…" subito dopo
l'onda, resa sopra il suo inizio. L'etichetta è un container di text markup
(neumaRk_text_markup.md §2.2): accetta i marcatori #/##/###, */**,
__; il default è tondo (corsivo/grassetto/underline/size solo via i
marcatori). Ampiezza ed etichetta sono indipendenti.
A) ~3"shake" ~ ~ ~
A) ~"vibrato" ~ ~
A) ~4"laid back" ~ ~ ~ ~
L'etichetta dà la semantica (vibrato vs shake vs laid-back); il glifo ~ da
solo è solo "onda di ampiezza N". Per uno strumento di trascrizione la pagina è la
verità; un eventuale playback inferirà da etichetta/ampiezza.
10.3 Staffa d'analisi [ ] (span delimitato)¶
Una staffa di raggruppamento sopra il rigo, come le parentesi dell'analisi
formale. [ apre sulla nota della sua posizione, ] chiude su quella della sua
(stile LilyPond, esattamente come la legatura §10.1).
A) . . ["triade di DO" . . ] |
N) a a c e | g e c a
- Etichetta (opzionale): stringa
"…"subito dopo[(riusa lo stesso token opaco dell'onda). Resa allineata a sinistra sopra l'apertura ed è un container di text markup (neumaRk_text_markup.md§2.2:#/*/__), tonda di default. Una staffa senza etichetta ([ … ]) è ammessa. - Resa: parentesi quadra sempre sopra il rigo, con i due montanti rivolti verso il basso (verso le note).
- Cross-barline / cross-system: sì.
- No overlap/annidamento (v1): al più una staffa aperta per volta; una
seconda
[con una aperta → warning (W144.bracket_open_overlap); una]orfana → warning (W144.bracket_close_unmatched);[]degenere (apertura+chiusura sulla stessa nota) → warning (W144.bracket_degenerate); staffa non chiusa a fine rigo → chiusura implicita + warning (W144.bracket_unclosed_eol). - Puramente grafica: nessun effetto sul playback (è un'annotazione analitica).
- Nota di sintassi: nelle righe
A)un[ … | … ]è una staffa che attraversa la barra, quindi il|interno è una barline reale — NON un polychord[X|Y](§accordi) né una volta[1.. La mappa sopprime il rilevamento polychord sulle righe Articulations.
10.4 Ottava 8u / 8d … 8 (span delimitato)¶
Una linea di ottava. 8u apre un'8va alta, 8d apre un'8vb bassa;
8. chiude lo span (inclusivo sull'ultima nota coperta). Delimitata
come la legatura (§10.1) — volutamente NON il modello a estensione dell'onda
(§10.2): la linea d'ottava è rada, ripetere un token su ogni nota sarebbe
macchinoso. Un 8 nudo (senza u/d/.) è fuori-vocabolario (probabile
refuso di 8.) → W139.
A) . . . . . . . 8u . . . | . . . 8. |
N) c d e f g a b c d e f | a g f e d c b a g
# └─ 8va dall'8ª nota, attraverso la barra, fino alla chiusura ─┘
- Resa: la sigla SMuFL standard —
8va(alta, glifoU+E511) /8ba(bassa, glifoU+E513) — seguita da una linea orizzontale tratteggiata e un gancio finale verso il rigo; sopra per8u, sotto per8d. (Entrambi i glifi sono nel subset BravuraLS/PetalumaLS.) - Playback: le note coperte sono trasposte di ±12 semitoni (
8u= +12,8d= −12). L'altezza scritta resta invariata — le teste-nota non si muovono; solo la riproduzione viene spostata. - Cross-barline / cross-system: sì.
- No overlap/annidamento (v1): seconda apertura con una aperta → warning
(
W144.octave_open_overlap);8.di chiusura orfano → warning (W144.octave_close_unmatched);8u8.degenere → warning (W144.octave_degenerate); apertura non chiusa a fine rigo → chiusura implicita + warning (W144.octave_unclosed_eol).
Convenzione span (decisa per
A), da riusare per le forcelle/cresc.diD)): ogni span lungo è delimitato — un token di apertura (eventualmente parametrizzato) + un token di chiusura; le posizioni intermedie sono placeholder.. Legatura( ), staffa[ ]e ottava8u…8la seguono. L'onda~mantiene il modello a estensione come unica eccezione documentata, perché il suo glifo è una linea ondulata continua su ogni nota.
11. Impatto sulla deduzione (charset esteso)¶
Le estensioni allargano la superficie di classificazione delle righe
(neumaRk_datapack.md §3.bis):
- Charset
A): include i nuovi simboli( ) ~ h v n ge le cifre1-4, più[ ] 8 u d(§10.3 staffa, §10.4 ottava), oltre al vocabolario base §6 (da cui il charset è derivato — fonte unica). ~è marker specifico: una riga che contiene~è classificata univocamente comeA), malgrado le cifre che altrimenti la avvicinerebbero a chords/notes.[]8dNON sono marker specifici: sono molto sovraccarichi ([= sezione[NAME], etichetta alternate-chord, grace/annotation inN);8/d= durata/nota). Allargano solo il charsetA); la priorità notes-line (TB4) protegge le righeN), e una riga staffa/ottava implicita richiede il prefix esplicitoA)per essere classificata come articolazioni.g/glvs nota G — TB4:g(testa del tokenglglissato, §9) è anche la nota G, e con le durate1–4rende ambigue righe comeg,g4,g g g. La regola TB4 (neumaRk_datapack.md §3.bis.5) dà priorità alle note: una riga che è una notes-line valida (ogni token matcha la grammaticaparse_notes- almeno un pitch reale) è
N), nonA). Il tokenglnon è una nota valida, quindi una riga di articolazioni conglrestaA). - Quote-aware: il contenuto di un'etichetta
"…"(es.shake) è escluso dal match di classificazione — lettere fuori-charset o un~dentro il testo non rompono né marcano falsamente la riga.
12. Decisioni (estensioni, chiuse 2026-05-24)¶
- Glissato fra-note (
gl, §9) ≠ glissato singola-nota (scoop/fall, inN)). ✓ - Vocabolario esteso = insieme chiuso; significato normativo, codici VexFlow implementativi (eredita §6/§7). ✓
- Modello token unificato (decompositore + co-locazioni, §8). ✓
- Legatura
( )delimitata, no overlap v1 (§10.1). ✓ - Arco su
v, giùn; armonicoh(§3). ✓ - Onda
~: livelli 1–4; cifra = nuovo span, nudo = estende; sempre sopra; copre i rest; etichetta"…"in apertura, corsivo (§10.2). ✓ - Shake / long-vibrato / laid-back unificati nell'onda
~N+ etichetta. ✓ - Staffa d'analisi
[ ]delimitata, etichetta"…"opzionale, sempre sopra, puramente grafica; no overlap v1 (§10.3). ✓ (aggiunta 2026-05-31) - Ottava
8u/8d…8.delimitata (8.chiude), tratteggiata sopra/ sotto, trasporta il playback ±12; no overlap v1 (§10.4). ✓ (2026-05-31) - Convenzione span: gli span lunghi sono delimitati (apertura + chiusura); l'onda è l'unica eccezione (estensione), avendo un glifo a linea continua. ✓