Scribe renders music notation in HTML.
Scribe takes a sequence of events – notes, chords, meter changes and so on – and renders notation as symbols in a CSS grid that displays as a bar and stave.
There is a description of the CSS grid system in the blog post Printing Music with CSS Grid.
Scribe 0.3 is a rewrite, and does not yet have a release build.
Development builds are kept in the build/
folder.
Scribe 0.3 is a rewrite, and this custom element is the test bed. To try out the development version of the element, import the css and register the element:
<link rel="stylesheet" href="https://stephen.band/scribe/build/scribe-music/module.css" />
<script type="module" src="https://stephen.band/scribe/build/scribe-music/module.js"></script>
Now the <scribe-music>
element renders music notation from data found in
it's content:
<scribe-music type="sequence" clef="treble" meter="4/4">
0 chord Dmaj 4
0 F#5 0.2 1
0 A4 0.2 1
0 D4 0.2 1
</scribe-music>
Or imported from a file in its src
attribute:
<scribe-music type="application/json" src="/path/to/json"></scribe-music>
Or set on it's data property:
let scribe = document.body.querySelector('scribe-music');
scribe.data = {
name: 'My Song',
events: [...]
};
Scribe consumes Sequence JSON
(and data objects of the same structure). Events are described by arrays of data in
the .events
array:
scribe.data = {
events: [
[0, "note", "G4", 0.2, 3]
]
};
Each event type has its own structure. Scribe 0.3 supports these event types:
beat | type | 2 | 3 | 4 |
---|---|---|---|---|
beat |
"chord" |
root |
mode |
duration |
beat |
"note" |
pitch |
dynamic |
duration |
beat |
"meter" |
duration |
divisor |
|
beat |
"rate" |
number |
||
beat |
"key" |
notename |
||
beat |
"clef" |
clefname |
Scribe 0.3 also parses a shorthand version of this format intended for quick hand authoring, as in the first example above, which is basically Sequence JSON structure with all the JSON syntax – commas and brackets and quotemarks – removed.
Scribe 0.3 also parses ABC (thanks to the parser from ABCjs).
Both an attribute and a property.
Mimetype or type of data to fetch from src
or to parse from text content.
Scribe supports 3 types of data:
- "application/json", or just "json"
- "text/x-abc", or just "abc"
- "sequence"
Both an attribute and a property. The URL of a file containing sequence data in JSON or ABC.
Both an attribute and a property.
The name of the clef, one of "treble"
, "bass"
, "piano"
, "drums"
, "percussion"
or
"chords"
. Defaults to "treble"
.
<scribe-music clef="bass">...</scribe-music>
let scribe = document.body.querySelector('scribe-music');
scribe.clef = "bass";
Both an attribute and a property.
Gets and sets the key signature of the stave. Accepts any chromatic note name,
spelled with unicode sharps ♯
and flats ♭
or with hash #
and small case b
.
This is the name of the tonic of a major scale. Defaults to "C"
.
<scribe-music key="F#">...</scribe-music>
let scribe = document.body.querySelector('scribe-music');
scribe.key = "B♭";
There is no provision for choosing a 'minor' key. Declare its relative major.
The key is the key signature pre-transpose. If scribe.transpose
is something other
than 0
, the key signature is transposed.
Both an attribute and a property.
The meter, expressed as a standard time signature.
This setting is overridden by any meter event found in the data at beat 0
.
If this attribute is omitted (or the property not set in JS), no time signature is displayed (unless the data contains a "meter"
event at beat 0
).
Defaults to "4/4"
.
<scribe-music meter="3/4">...</scribe-music>
let scribe = document.body.querySelector('scribe-music');
scribe.meter = "3/4";
Both an attribute and a property.
Sets scribe to render notation transposed by transpose
semitones. Transposition
is applied to key signature, notes and chords before render, and not to the underlying data.
<scribe-music transpose="2">...</scribe-music>
let scribe = document.body.querySelector('scribe-music');
scribe.transpose = 2;
Property only.
Set a .data
object, structured as a Sequence, to render it.
let scribe = document.body.querySelector('scribe-music');
scribe.data = {
name: 'My Song',
events: [...]
};
Get Scribe's internal data object, whose structure is a Sequence.
To export Sequence JSON, simply stringify scribe.data
:
let scribe = document.body.querySelector('scribe-music');
let mySong = JSON.stringify(scribe.data);
The "sequence"
format is intended for quick hand-authoring, and not as an export format.
The format is basically Sequence JSON events but with all the JSON syntax – commas, quotes, brackets – removed.
Values are delineated by whitespace.
Any value that does not parse as a number becomes a string.
0 meter 4 1
0 chord D maj 4
0 note F#5 0.2 2
1 note A4 0.2 1
4 note D4 0.2 1
If notes have named pitches (as opposed to numbered pitches), declaring the note
type is optional.
0 meter 4 1
0 chord D maj 4
0 F#5 0.2 2
1 A4 0.2 1
4 D4 0.2 1
The same is true for chords.
0 meter 4 1
0 D maj 4
0 F#5 0.2 2
1 A4 0.2 1
4 D4 0.2 1
To install Scribe locally you need several repos served from one directory, as Scribe's modules import modules from these other repos using relative paths.
Assuming you are inside a project repo, add the submodules:
git submodule add [email protected]:stephband/fn path/to/fn
git submodule add [email protected]:stephband/dom path/to/dom
git submodule add [email protected]:stephband/abcjs path/to/abcjs
git submodule add [email protected]:stephband/midi path/to/midi
git submodule add [email protected]:stephband/scribe path/to/scribe
To check things are working launch your server and navigate to
path/to/scribe/scribe-music/index.html
.
Asides from some immediate improvements I can make to Scribe 0.3, like tuning the autospeller and fixing the 1/16th-note beams and detecting and displaying tuplets, here are some longer-term features I would like to investigate:
- Support for SMuFL fonts – changing the font used for notation symbols. So far I have not been able to display their extended character sets reliably cross-browser.
- Support for nested sequences – enabling multi-part tunes.
- Split-stave rendering – placing multiple parts on one stave. The mechanics for this are already half in place – the drums stave and piano stave currently auto-split by pitch.
- Multi-stave rendering – placing multiple parts on multiple, aligned, staves.
Rich Sigler of Sigler Music Fonts (http://www.jazzfont.com/) very kindly granted permission to use JazzFont shapes as SVG paths in this project.
Gavin Band implemented probabalistic key centre analysis.
Scribe logo/mascot by Mariana Alt.
ABC parser borrowed from ABCjs.