Vai al contenuto

Markers

1. Cos’è un Marker

Un marker è un elemento strutturale non musicale che identifica un punto significativo nel flusso del brano. I marker non si riferiscono a un elemento sonoro, non hanno durata musicale propria e non influiscono direttamente sul contenuto musicale (note, accordi, ritmi), ma servono a:

  • segmentare il brano in sezioni logiche;
  • facilitare la lettura e l’orientamento umano;
  • fornire ancoraggi semantici per il rendering, la navigazione e il playback;
  • supportare forme musicali, ripetizioni e riferimenti.

I marker fanno parte del datapack musicale, ma appartengono alla sfera della struttura, non della notazione musicale.

Appartenenza semantica

Un marker appartiene semanticamente a una misura.

Esso identifica, etichetta o qualifica una misura come unità strutturale del brano e non è legato al flusso musicale o all’ordine di esecuzione.


2. Riga dei Markers

I marker sono contenuti in una riga di markers, che può essere:

  • dichiarata esplicitamente con il marcatore di riga M);
  • dedotta implicitamente dal contenuto della riga.

2.1 Posizione nel datapack

  • La riga dei markers, se presente, è la prima riga del datapack.
  • È opzionale.
  • Può comparire una sola riga di markers per datapack.

Best practice: collocare nella riga dei markers anche i decoratori di misura (volta, segno, coda, ecc.), per concentrare la struttura formale in un unico punto.


3. Sintassi dei Markers

Un marker è espresso in due forme container, che differiscono per il ruolo strutturale e per la presenza del box grafico:

  • [<testo>]sezione: unità strutturale del brano, con box;
  • "<testo>"annotazione: testo descrittivo, senza box.
[Intro]            sezione (con box)
[A]                sezione
"freely"           annotazione
"swing feel"       annotazione

Il marker ammette il markup testuale definito in neumaRk_text_markup.md. Lo stile di default è bold, size body, in entrambe le forme.

3.1 Sezione vs annotazione

I due container hanno valore semantico diverso:

Forma Tipo Valore strutturale Target PLAY/FORM Chiude scope collapsible
[…] sezione sì (unità del brano)
"…" annotazione no (testo descrittivo) no no

Una sezione identifica un'unità strutturale ricorribile e referenziabile (Intro, Verse, Chorus, A, B, …). Le sezioni sono i target di PLAY) / FORM) (vedi neumaRk_play_and_form.md §3.1) e delimitano lo scope delle sezioni collassabili (vedi §4).

Un'annotazione è un testo libero senza valore strutturale (es. "freely", "swing feel", "con feeling"). Le annotazioni non sono referenziabili da PLAY) / FORM) e non chiudono lo scope di una sezione collassabile.

Nota normativa. Questa distinzione è un raffinamento della spec 0.5, dove […] e "…" erano considerate semanticamente equivalenti. Documenti esistenti sono retrocompatibili (le annotazioni "…" continuano a esistere come testo); l'unica differenza operativa è il binding selettivo da PLAY/FORM e il comportamento di [? …] (vedi §4).

3.2 Ancoraggio temporale

  • Un marker si riferisce all'inizio della battuta in cui compare.
  • Se preceduto da una barline e nella forma con box […], deve essere separato da essa da almeno uno spazio, per evitare ambiguità con i decoratori di volta.
  • La forma "…" non collide con i decoratori di volta e può essere adiacente alla barline; resta tuttavia raccomandato lo spazio per leggibilità.

Esempio valido:

| [A]
| "freely"

Esempio non valido:

|[A]   // ambiguo: potrebbe essere interpretato come volta

4. Sezioni collassabili

Una sezione può essere dichiarata collassabile (anche detta opzionale) anteponendo il prefisso ? (carattere ? seguito da uno spazio) all'interno del marker:

[? Verse]
[? Solo 2]
[? Outro]

Una sezione collassabile è una proprietà UX del marker: l'utente può espandere/comprimere la sezione nell'interfaccia di lettura (accordion). Lo stato espanso/compresso è preference utente, salvato in user-index (Firestore users/{uid}/song_view_state/{songId}) e non nel file NRK.

4.1 Scope della sezione collassabile

Lo scope di [? NAME] si estende dalla misura del marker fino al primo dei seguenti eventi:

  • inizio di un'altra sezione […] (di qualsiasi nome, collassabile o no, incluso il marker anonimo [!] di §4.2);
  • fine del documento.

Le annotazioni "…" interposte non chiudono lo scope: appartengono comunque alla sezione collassabile corrente.

M) [? Verse] | … | "freely" | … | [Chorus] | …
   └─────── scope di Verse ─────┘
                                  └ Chorus apre nuovo scope

4.2 Marker anonimo [!] (chiusura implicita di sezione opzionale)

Quando una sezione opzionale termina e non c'è un marker successivo che la chiude naturalmente (perché segue flusso "anonimo", non strutturato come sezione), si usa il token speciale [!] (parentesi quadre con un singolo !, senza spazi).

[!] è semanticamente un marker di apertura di sezione non-opzionale anonima: aderisce alla convenzione "marker = inizio-misura" (§3.2) e la chiusura dello scope precedente è il side-effect naturale della regola §4.1.

M) [? Coda] | … | … | [!] | … |
   └── scope di Coda ─┘
                       └ flusso non-collassabile, anonimo

Proprietà:

  • Non renderizzato come marker (nessun box, nessuna etichetta).
  • Non referenziabile da PLAY) / FORM): non ha NAME. Se usato come reference è reference-broken (vedi neumaRk_play_and_form.md §7.3).
  • Ammesso ovunque: [!] non richiede una sezione opzionale aperta. Se non c'è scope da chiudere il token è ridondante (warning W146, non bloccante).

4.3 Niente annidamento

Una [? Inner] interna a un'altra [? Outer] chiude lo scope di Outer e apre quello di Inner, secondo la regola generale §4.1. Non esiste un meccanismo di sezioni collassabili annidate.

M) [? Outer] | … | [? Inner] | … |
   └ Outer ──┘   └─ Inner ─────…

4.4 Stato di default

All'apertura di un brano per la prima volta, le sezioni collassabili sono espanse. L'utente le collassa esplicitamente; lo stato è poi persistente in user-index.

Il ? nel marker è ben evidenziato in UI (chevron nel margine, stile distinto del titolo) perché la presenza di sezioni collassabili sia immediatamente riconoscibile, anche quando tutte espanse.

4.5 Riferimenti da PLAY/FORM

Una sezione [? NAME] è referenziata da PLAY) / FORM) usando il solo NAME, senza prefisso ?:

M) [? Verse] | … | [Chorus] | …
PLAY) [Verse] [Chorus]

Il prefisso ? è una proprietà UX della sezione, non parte del nome strutturale. Il binding fra PLAY) e M) è per text-equality sul NAME, ignorando il prefisso ?.

4.6 Esecuzione

Lo stato collassato/espanso è UX-only: il player esegue una sezione collassabile esattamente come una sezione ordinaria, indipendentemente dal fatto che l'utente l'abbia collassata o espansa nella vista.

Una sezione collassata non viene "saltata" dal player. Per omettere una sezione dall'esecuzione esistono altri meccanismi (versioni, PLAY) esplicita che la esclude).

4.7 Vincolo a inizio rigo

Una sezione collassabile deve iniziare e finire a inizio rigo (= a inizio di un system / datapack). Concretamente:

  • il marker [? NAME] deve comparire nella prima misura del system in cui appare;
  • la chiusura dello scope (qualsiasi altro […] o [!]) deve a sua volta comparire nella prima misura del system in cui appare;
  • lo scope termina anche a EOF (caso valido).

Razionale: l'accordion UX comprime righe intere; una sezione che inizia o finisce a metà rigo produrrebbe una resa ambigua (mezzo rigo sparirebbe, lasciando moncheria visiva).

In caso di violazione:

  • emessa W151 (warning, non bloccante);
  • la sezione non è collassabile lato UX: il toggle utente è ignorato sul render (la sezione resta sempre espansa).

5. Rilevanza identitaria

Il prefisso ~ su un marker di sezione la dichiara identitaria: ne segnala il tema come quello che caratterizza il brano ("la parte che fa riconoscere il pezzo"). È una proprietà strutturale e portabile della composizione — viaggia col file — non un dato dell'host.

M) [Intro] | … |
M) [~ Tema] | … |          ← sezione identitaria del brano
M) [Coda] | … |

~ non è renderizzato (nessun box, nessuna etichetta aggiuntiva: la sezione si disegna come una [Tema] normale) ed è preservato in round-trip dal serializer.

La rilevanza identitaria è un'annotazione musicale, non un'etichetta host: indica quale musica caratterizza il brano. Il marker è agnostico alla dimensione d'analisi: l'host può derivarne ciò che serve sotto qualunque profilo — melodia, armonia, ritmo, ritmo armonico, ecc. (elenco non esaustivo). Lo spec definisce quale regione è identitaria; cosa se ne estrae e su quale dimensione è fuori dal linguaggio.

5.1 Scope della regione di rilevanza

Lo scope di [~ NAME] si estende dalla misura del marker fino al primo dei seguenti eventi:

  • l'inizio di una nuova sezione […] priva del prefisso ~;
  • la fine del documento.

Una sezione successiva che porta anch'essa ~ non chiude la regione: la continua. Sezioni ~ consecutive formano quindi un'unica area di rilevanza; solo una sezione senza ~ la chiude.

M) [~ A] | … | [~ B] | … | [C] | … | [~ D] | …
   └──── area di rilevanza 1 (A+B) ────┘        └ area 2 (D)
                              └ C non rilevante, chiude l'area 1

Le annotazioni "…" interposte non chiudono lo scope (come in §4.1).

5.2 Più aree per brano

Sono ammesse più aree di rilevanza melodica nello stesso brano (le ~ non consecutive sono aree distinte, vedi [~ D] sopra). Il modo in cui l'host usa una o più aree (es. quale considerare per quale scopo) non è materia di linguaggio.

5.3 Default (nessun marker ~)

In assenza di qualsiasi [~ …] nel brano, la regione melodicamente rilevante è implicitamente il tratto dall'inizio del brano fino alla prima sezione esclusa (o fino a EOF se non ci sono sezioni). I brani che non usano il marker hanno quindi una regione di rilevanza ben definita e host-independent.

5.4 Marker anonimo [~]

[~] (parentesi quadre con un solo ~, senza spazi) è una sezione anonima identitaria: si comporta come il marker anonimo [!] (§4.2) — apre una sezione non-opzionale e chiude lo scope precedente — ma è flaggata ~. Serve a marcare "da qui è rilevante" quando il tema non è una sezione nominata. Specularmente, un [!] (senza ~) che segue una regione di rilevanza la chiude (è una sezione priva di ~, §5.1).

5.5 Composizione con ? (collassabile + rilevante)

Una sezione può essere insieme collassabile e identitaria. I due prefissi si accettano in ordine libero in input: [?~ NAME] e [~? NAME] sono equivalenti. Essendo semanticamente identiche, il serializer le normalizza alla forma canonica [?~ NAME] (come già normalizza spaziatura e altri aspetti dei marker).

M) [?~ Bridge] | … |     ≡     M) [~? Bridge] | … |

5.6 Riferimenti da PLAY/FORM

Come per ? (§4.5), una sezione [~ NAME] è referenziata da PLAY) / FORM) con il solo NAME, senza prefisso. Il binding è per text-equality sul NAME, ignorando i prefissi ~ e ?.

M) [~ Tema] | … |
PLAY) [Intro] [Tema] [Coda]

5.7 Ancoraggio

[~ NAME] / [~] seguono l'ancoraggio delle sezioni (§3.2, §4.7): compaiono a inizio misura; i confini di scope (sezione senza ~, o EOF) cadono a inizio rigo come ogni altro confine di sezione.


6. Play directive in riga M)

La riga M) ammette, oltre ai marker testuali […] / "…", anche play directive nella forma (=Style,Tempo) per cambiare lo style e/o il tempo del brano a partire da una misura specifica. Vedi neumaRk_play_directive.md per la spec completa.

La play directive convive liberamente con i marker testuali nella stessa misura. La disambiguazione fra i token è per delimitatori:

Token Tipo
[…] sezione (marker strutturale)
[? …] sezione collassabile (vedi §4)
[~ …] sezione identitaria (§5)
[!] sezione anonima non-opzionale (§4.2)
[~] sezione anonima identitaria (§5.4)
"…" annotazione (testo descrittivo)
(=…) play directive

Esempio:

M) | [Intro] (=Rock,120bpm) | | | [A] (=swing,140bpm) |

7. Regole di Validità

Una riga di markers è valida se:

  • contiene solo sezioni […] / [? …] / [~ …], marker anonimi [!] / [~], annotazioni "…" e play directive (=…), separati da spazi e segni di battuta;
  • non contiene pattern riconducibili a note o accordi;
  • rispetta le regole di separazione da barline.

In caso di violazione:

  • la riga non viene riconosciuta come riga di markers;
  • il parsing del datapack prosegue secondo le regole di deduzione standard.

7.1 Codici diagnostici

Codice Severità Descrizione
W146 WARNING [!] ridondante: nessuna sezione opzionale da chiudere
W151 WARNING Sezione opzionale non-collassabile: [? NAME] o la sua chiusura non a inizio rigo (§4.7)