11 Punkte von GN⁺ 2024-05-01 | 2 Kommentare | Auf WhatsApp teilen
  • Für Musiker, die auf kleinen mobilen Bildschirmen in ein A4-PDF hineinzoomen und dabei spielen, wird eine flüssige und responsive Notendarstellung im Web benötigt

Scribe-Prototyp

  • In der Vergangenheit wurde als Prototyp ein Musik-Renderer namens Scribe erstellt, der aus JSON SVG ausgibt
  • Das ursprüngliche Ziel war ein responsiver Musik-Renderer, doch der Fortschritt war schwierig, weil dafür eine komplexe mehrstufige Layout-Engine hätte geschrieben werden müssen
  • Später wurde CSS Grid in das Projekt eingeführt, und es schien eine Antwort auf die Layout-Probleme zu sein, mit denen Scribe zu tun hatte

Die Klasse .stave

  • Das Notensystem ähnelt einem Grid. Die vertikale Achse ist die Tonhöhe, die horizontale Achse die Zeit
  • In der Klasse .stave werden die Grid-Zeilen für die vertikale Achse definiert
  • Es werden Grid-Zeilen mit fester Größe anhand standardisierter Tonhöhenbezeichnungen erstellt und ein Hintergrundbild zum Zeichnen des Notensystems verwendet
  • Beispiel einer Zeilenzuordnung für ein Notensystem im Violinschlüssel:
    .stave {  
      display: grid;  
      row-gap: 0;  
      grid-template-rows:   
        [A5] 0.25em [G5] 0.25em [F5] 0.25em [E5] 0.25em  
        [D5] 0.25em [C5] 0.25em [B4] 0.25em [A4] 0.25em  
        [G4] 0.25em [F4] 0.25em [E4] 0.25em [D4] 0.25em  
        [C4] 0.25em ;  
      background-image: url('/path/to/stave.svg');  
      background-repeat: no-repeat;  
      background-size: 100% 2.25em;  
      background-position: 0 50%;  
    }  
    
  • Dadurch entstehen Grid-Linien mit Tonhöhenbezeichnungen für jede Notenlinie und jeden Zwischenraum

Tonhöhen auf dem Notensystem platzieren

  • In jeder Zeile des Notensystems können mehrere Tonhöhen liegen
  • Damit DOM-Elemente in der richtigen Zeile landen, wird die Tonhöhenbezeichnung in das Attribut data-pitch geschrieben und per CSS auf die Zeilen des Notensystems gemappt
    .stave > [data-pitch^="G"][data-pitch$="4"] { grid-row-start: G4; }  
    
  • Diese Regel erfasst Tonhöhen, die mit G beginnen und mit 4 enden, und ordnet G♭4, G4, G♯4 usw. der Zeile G4 zu
  • Das muss für alle Zeilen des Notensystems gemacht werden
  • Damit lassen sich nun einige Symbole auf dem Notensystem platzieren

Die Klasse .bar und der Takt

  • Der Rhythmus ist etwas schwieriger zu behandeln
  • Es gibt keine offensichtliche minimale Rhythmusunterteilung, die alle Arten von Rhythmus unterstützt
  • Der Ansatz mit 24 Spalten pro Schlag ist ein guter Ausgangspunkt, weil sich damit Achtel, Sechzehntel, Zweiunddreißigstel und Triolen gleichmäßig platzieren lassen
  • Für vier Schläge werden 4 × 24 = 96 Grid-Spalten definiert und am Anfang und Ende zusätzliche Spalten hinzugefügt:
    .bar {  
      column-gap: 0.03125em;  
      grid-template-columns:  
        [bar-begin]  
        max-content  
        repeat(96, minmax(max-content, auto))  
        max-content  
        [bar-end];  
    }  
    
  • Mit ::before und ::after werden Taktstriche hinzugefügt, und der Notenschlüssel wird mit data-pitch="B4" mittig platziert

Symbole im Takt platzieren

  • Diesmal wird das Attribut data-beat verwendet, um Elementen einen Schlag zuzuweisen, und CSS-Regeln mappen den Schlag auf Grid-Spalten
  • Das CSS-Mapping besteht aus einer Regel pro 1/24 Schlag
  • Durch die Verwendung des Attributselektors ^= für „beginnt mit“ werden die Regeln toleranter gegenüber Ungenauigkeiten
  • In Kombination mit der Klasse .stave können Symbole nach Schlag und Tonhöhe platziert werden, indem data-beat auf einen Schlag zwischen 1 und 5 und data-pitch auf einen Notennamen gesetzt wird

Flüssige und responsive Notendarstellung

  • Wenn mehrere solcher Takte in einen Flexbox-Container gelegt werden, erhält man eine responsive Notendarstellung
  • Es fehlt noch vieles, aber es ist eine gute Grundlage für den Start
  • Zeilenumbrüche funktionieren bereits deutlich eleganter als bei bestehenden Online-Musik-Renderern

Abstand zwischen Noten

  • Notenköpfe, die zeitlich näher beieinander liegen, werden etwas dichter gerendert
  • Das ist ein subtiler und beabsichtigter Effekt, der durch ein kleines column-gap entsteht und als eine Art zeitlicher „Äther“ fungiert, in den die Symbolelemente eingesetzt werden
  • Die Spalten selbst haben eine Breite von 0, wenn kein Notenkopf vorhanden ist, aber zwischen Ereignissen, die weiter auseinanderliegen, gibt es mehr Spaltenabstände — 24 pro Schlag — und dadurch mehr Abstand
  • Über das Margin der Symbole lässt sich ein gleichmäßiger Abstand steuern

Schlüssel und Taktarten

  • Der Grund für getrennte Klassen für vertikale und horizontale Abstände ist, dass sich eines austauschen lässt, ohne das andere zu berühren
  • Um dieselbe Melodie im Bassschlüssel anzuzeigen, muss die Klasse .stave nur durch eine Klasse bass-stave ersetzt werden, die dasselbe Attribut data-pitch auf die Zeilen eines Bass-Notensystems mappt
  • Wenn per CSS data-duration="5" auf 120 Grid-Template-Spalten von .bar gemappt wird, lässt sich demselben Notensystem auch eine Taktart 5/4 geben

Akkorde und Liedtext

  • Mit CSS Grid lassen sich auch andere Symbole innerhalb des Noten-Grids ausrichten
  • Akkorde, Liedtext, Dynamikangaben usw. können an zeitlich definierte Ereignisse ausgerichtet und darüber gespannt werden

Notenhälse

  • Notenhälse, Akkorde und einige lange Pausen werden über das Attribut data-duration auf einen grid-column-end-Spannenwert gemappt, damit sie sich über mehrere Spalten erstrecken

Skalierung

  • Das gesamte System ist in em dimensioniert, daher kann die Größe allein durch Ändern von font-size skaliert werden

Grenzen von Flex und Grid

  • Es ist kein perfektes System. Die Grenzen sind:
    1. CSS kann bei Zeilenumbrüchen nicht automatisch einen neuen Schlüssel oder neue Vorzeichen platzieren
    2. Bindebögen oder Balken können nicht mit neuen Noten in einer neuen Zeile verbunden werden
    3. Geneigte Notenhälse kennen ihre exakte Position erst, nachdem Grid sie platziert hat, was die Ausrichtung erschwert
  • Für den vollständigen Feinschliff wird etwas aufräumendes JavaScript benötigt, aber weil CSS den Großteil der Layout-Arbeit übernimmt, bleibt in JavaScript deutlich weniger Layout-Arbeit übrig

Benutzerdefiniertes Element

  • Rund um dieses neue CSS-System wurde ein Interpreter geschrieben und in ein Element eingebettet
  • Es ist noch nicht produktionsreif, aber es kann responsive Leadsheets rendern und Schlagzeugnotation darstellen, was es interessant und nützlich macht
  • Es rendert Noten aus den Inhaltsdaten, aus Dateien, die über das Attribut src geladen werden, und aus JS-Objekten, die in der Eigenschaft .data des Elements gesetzt werden
  • Der aktuelle Development-Build kann in eine Webseite eingebunden und ausprobiert werden

Ausblick

  • Zusätzlich zu den Verbesserungen in Scribe 0.3 gibt es langfristig Funktionen, die untersucht werden sollen:
    • Unterstützung für SMuFL-Schriften – Wechsel der für Notationssymbole verwendeten Schrift
    • Unterstützung für verschachtelte Sequenzen – Aktivierung von Stücken mit mehreren Stimmen
    • Rendering geteilter Notensysteme – mehrere Stimmen auf einem Notensystem platzieren
    • Rendering mehrerer Notensysteme – mehrere Stimmen auf mehreren ausgerichteten Notensystemen platzieren

Meinung von GN⁺

  • Notation im Web flüssig und responsiv zu rendern, wäre sowohl für Musiker als auch für Musikliebhaber sehr nützlich. Es könnte die Unbequemlichkeit beseitigen, PDF-Noten auf kleinen Bildschirmen hinein- und herauszuzoomen
  • Der Ansatz mit den CSS-Layouts Grid und Flex ist interessant. Er ist ein gutes Beispiel dafür, wie sich auch ohne komplexe Layout-Engine bereits sehr viel allein mit CSS lösen lässt
  • Aufgrund der Eigenschaften von Musiknotation gibt es aber auch Bereiche, in denen CSS allein an Grenzen stößt. Teile, die musikalischen Kontext verstehen müssen — etwa das automatische Platzieren von Schlüsseln oder Vorzeichen bei Zeilenumbrüchen oder das automatische Verbinden von Balken — werden Hilfe von JavaScript brauchen
  • Da bereits recht viel umgesetzt wurde, etwa Rendering von Leadsheets und Unterstützung für Schlagzeugnotation, dürfte es sich bald auf ein gut nutzbares Niveau verbessern lassen. Wenn es Open Source wird und weiterentwickelt wird, könnte es eine gute Alternative zu bestehenden Notationseditoren wie MuseScore sein
  • Wenn die geplanten Funktionen wie SMuFL-Schriftunterstützung sowie Support für mehrere Stimmen und mehrere Notensysteme umgesetzt werden, dürfte die Qualität der Notendarstellung deutlich steigen. Ein spannendes Projekt

2 Kommentare

 
roxie 2024-05-06

Dafür gibt es doch sicher einen Grund.

 
GN⁺ 2024-05-01
Hacker-News-Kommentare
  • Ein Entwickler von Sheet-Music-Software äußert großes Lob für den Ansatz, Noten mit CSS Grid zu rendern
    • Er entwickelt seit über 10 Jahren den webbasierten Noten-Rendering-Dienst Soundslice und hat 2014 erstmals „responsives“ Noten-Rendering im Web umgesetzt
    • Details zur zugrunde liegenden Technik im Vortragsvideo: https://www.youtube.com/watch?v=XH5EtQge_Bg
    • Beispiel für responsives Noten-Rendering von Soundslice: https://www.soundslice.com/slices/zzNlc/
    • Der Dienst bietet verschiedene Tools wie einen webbasierten Editor, Übungsfunktionen und eine Scan-Funktion zum Extrahieren von Notendaten aus Fotos/PDFs
    • Der CSS-Grid-Ansatz kann für leichte Projekte nützlich sein, dürfte aber Schwierigkeiten haben, die komplexen und feinen Ausdrucksformen einer vollständigen Partitur vollständig abzubilden
  • Es wäre vielleicht gut, der CSS-Community Vorschläge zu machen, damit sich so etwas ganz ohne JavaScript nur mit CSS umsetzen lässt
    • Zum Beispiel ähnelt die Wiederholung der Schlüsselanzeige bei Zeilenumbrüchen einem sticky table header und könnte auch außerhalb der Notenschrift nützlich sein
  • Die Syntax des CSS-Attributselektors ([...]) wirkte eindrucksvoll. Beispiel: .stave > [data-pitch^="A"][data-pitch$="5"] { grid-row-start: A5; }
  • Aus Sicht eines Musiksetzers scheint visuell noch viel Verbesserung nötig zu sein. Nur mit CSS dürfte das wegen der begrenzten Präzision schwierig sein
    • Es gibt Probleme bei der Darstellung von Notenhälsen, Bögen und Bindebögen
    • Die meisten Notensysteme im Browser rendern mit SVG oder Canvas als Vektorgrafik, um punktgenaue Präzision zu erreichen
    • Neben CSS gibt es bereits andere Werkzeuge für skalierbare Notendarstellung im Browser, etwa Soundslice und Sibelius Cloud Publishing
  • Anfangs schien es unwahrscheinlich, dass sich Notenschrift gut mit CSS darstellen lässt, aber die typografische Qualität ist für einen einfachen Ansatz beeindruckend. Dem Autor gebührt Lob
    • Es gibt jedoch Bedenken, ob Sonderfälle wie Akkorde, die Abstände von Achtel-/Sechzehntelnoten und die Ausrichtung zwischen Stimmen gut funktionieren. Lilypond hat seine Flexibilität bei solchen komplexen Darstellungen bewiesen
  • CSS Grid ist interessant. Jemand hat damit früher einmal einen Möbeldesigner in pure frontend JS unter Verwendung von CSS Grid umgesetzt: https://alnvdl.github.io/2023/01/07/designing-furniture-using-the-css-grid.html
  • Auch das Custom Element <scribe-music> wirkt vielversprechend
  • Es ist gut, dass eine Alternative zu Lilypond (lilypond.org) auftaucht, aber weil die Notation sehr komplex ist, dürfte der Vorteil der Knappheit nicht lange anhalten
    • Für Asciidoc-Fans lässt sich Lilypond leicht in eine Asciidoc-Toolchain integrieren. Es wird in einer DocBook-PDF-Pipeline verwendet, und die Ausgabe ist ziemlich ordentlich. Ähnlich wie TeX
  • Es erinnert an https://www.musicxml.com und https://opensheetmusicdisplay.org. Das ist deutlich aufwendiger, aber eine vollständige Lösung
  • Es stellt sich die Frage, ob sich die holprigen Notensatzfunktionen von Impro-Visor(https://github.com/Impro-Visor/Impro-Visor) dadurch ersetzen ließen
  • Wirkt ein bisschen wie ein CSS-Benchmark