This library allows you to view and play music scores (notation) in the browser.
Note: I'm not a professional musician. I began learning classical guitar on my own, later taking lessons in classical guitar. I've also studied music theory independently.
This project has been a slow and steady effort over several years. It's now ready for public release — though please note that there may still be bugs or unexpected behavior.
npm i @tspro/web-music-score
# React is required, it is peer dependency
npm i react
// Import named exports
import * as Score from "@tspro/web-music-score";
// Import default export
import Score from "@tspro/web-music-score";
// Use require
const Score = require("@tspro/web-music-score");
Use in browser via unpkg CDN. Browser version comes without React-components.
<script src="https://unpkg.com/@tspro/web-music-score@1"></script>
<canvas id="scoreCanvas"></canvas><br />
<button id="playButton"></button>
<script>
const Score = window.WebMusicScore;
// ...
</script>
let doc = new Score.MDocument(Score.StaffKind.Treble, 4);
First argument can be Treble, TrebleForGuitar, Bass or Grand. TrebleForGuitar is same as Treble but one octave lower.
Second argument is number of measures per row, and can be omitted.
doc.setHeader("Title", "Composer", "Arranger");
doc.setHeader("Title");
Any of title
, composer
and arranger
can be omitted/set undefined.
let m = doc.addMeasure();
m.endRow();
Manually induce row change. Next measure will be added to new row.
m.setKeySignature("C", Score.ScaleType.Major);
Firat argument is scale key note.
Second argument is ScaleType
, which can be Major
, NaturalMinor
, HarmonicMinor
, Ionian
, Dorian
, Phrygian
, Lydian
, Mixolydian
,
Aeolian
, Locrian
, MajorPentatonic
, MinorPentatonic
, MajorHexatonicBlues
, MinorHexatonicBlues
or HeptatonicBlues
.
m.setTimeSignature("4/4");
Time signature can be "2/4"
, "3/4"
, "4/4"
, "6/8"
or "9/8"
.
m.setTempo(80, Score.NoteLength.Quarter, false);
m.setTempo(80);
First argument is beats per minute.
Second argument is beat length. Third argument tells if beat length is dotted. Second and third arguments can be omitted.
m.addNote(voiceId, note, noteLength, noteOptions?);
m.addChord(voiceId, notes, noteLength, noteOptions);
voiceId
: Voice track id 0
, 1
, 2
or 3
note
: note string | Note
(e.g. "C3"
)notes
: array of notes (string | Note)[]
(e.g. ["C3", "E3"]
)noteLength
: Note length (e.g. NoteLength.Half
), see belownoteOptions
: Optional note otions, see belowExamples:
m.addNote(0, "C3", Score.NoteLength.Quarter);
m.addChord(1, ["C3", "E3", "G3", "C4"], Score.NoteLength.Half, { dotted: true });
NoteLength.Whole
NoteLength.Half
NoteLength.Quarter
NoteLength.Eighth
NoteLength.Sixteenth
NoteLength.ThirtySecond
NoteLength.SixtyFourth
Optional object of note options (e.g. { stem: Stem.Up }
):
Note option | Type | |
---|---|---|
dotted | boolean |
Create dotted note |
stem | Stem |
Set stem direction (Stem.Auto /Up /Down ) |
arpeggio | Arpeggio |
Play column in arpeggio Arpeggio.Up /Down |
staccato | boolean |
Play column in staccato |
diamond | boolean |
Diamond shaped note head |
tieSpan | number | TieLength |
How many notes tied, or TieLength.Short /ToMeasureEnd |
tiePos | ArcPos |
Tie attach point: Arc.Auto /Above /Middle /Below /StemTip |
slurSpan | number |
How many notes slurred |
slurPos | ArcPos |
Slur attach point: Arc.Auto /Above /Middle /Below /StemTip |
triplet | boolean |
Make this note part of triplet |
m.addRest(voideId, restLength, restOptions?);
voiceId
: Voice track id 0
, 1
, 2
or 3
.restLength
: Rest length using NoteLength
(e.g. NoteLength.Half
), see above.restOptions
: Optional rest otions, see below.Example:
m.addRest(0, Score.NoteLength.Quarter);
Optional object of rest options (e.g. { hide: true }
):
Rest option | Type | |
---|---|---|
dotted | boolean |
Create dotted rest |
pitch | string | Note |
Positions rest at level of note (e.g. "C3" ) |
hide | boolean |
Add invisible rest |
triplet | boolean |
Make this rest part of triplet |
m.addNote(0, "C3", Score.NoteLength.Quarter).addFermata(Score.Fermata.AtNote);
m.addRest(0, Score.NoteLength.Quarter).addFermata();
Adds fermata anchored to previously added note or rest.
m.addFermata(Score.Fermata.AtMeasureEnd);
Adds fermata at measure end.
m.addNavigation(Score.Navigation.DC_al_Fine);
Adds navigational element to measure.
Available navigations are:
Navigation.DC_al_Fine
Navigation.DC_al_Coda
Navigation.DS_al_Fine
Navigation.DS_al_Coda
Navigation.Coda
Navigation.toCoda
Navigation.Segno
Navigation.Fine
Navigation.StartRepeat
Navigation.EndRepeat
Navigation.Ending
Navigation.EndRepeat
Takes optional second argument which is number of repeats. Defaults to 1 if omitted.
m.addNavigation(Score.Navigation.EndRepeat, 2);
Navigation.Ending
takes variable number of arguments, each is a passage number.
m.addNavigation(Score.Navigation.Ending, 1, 2);
m.addNavigation(Score.Navigation.Ending, 3);
m.addChord(0, ["D3", "F3", "A3"], Score.NoteLength.Quarter).addLabel(Score.Label.Chord, "Dm");
Available Label types are:
Label.Note
is used to label notes and is positioned below note.Label.Chord
is used to label chords and is positioned on top.m.addNote(0, "C3", Score.NoteLength.Quarter).addAnnotation(Score.Annotation.Dynamics, "fff");
First argument is Annotation
, second argument is the annotation text.
Available annotations are:
Annotation.Dynamics
could be for example "fff"
, "cresc."
, "dim."
, etc.Annotation.Tempo
could be for example "accel."
, "rit."
, "a tempo"
, etc.m.addNote(0, "C3", Score.NoteLength.Quarter).
addAnnotation(Score.Annotation.Tempo, "accel.").
addExtension(Score.NoteLength.Whole * 2, true);
Adds extension line to element, annotation in this case.
First argument is extension length, of type number. NoteLength
values can be used as number, and NoteLength
values can be multiplied to set desired extension length.
Second argument is true
/false
whether extension line is visible. This argument cvan be omitted, extension line is visible by default.
Adding stuff to measures can be queued like this:
doc.addMeasure()
.addNote(1, "C3", Score.NoteLength.Quarter)
.addChord(1, ["C3", "E3", "G3"], Score.NoteLength.Quarter).addLabel(Score.Label.Chord, "C")
.addRest(1, Score.NoteLength.Quarter);
Beams are detected and added automatically.
Score.Audio.setInstrument(Score.Audio.Instrument.ClassicalGuitar);
Sets instrument. Instrument can be ClassicalGuitar or Synth.
doc.play();
Plays the document.
let player = new MPlayer(doc);
player.play();
player.pause();
player.stop();
MPlayer.stopAll();
More playback methods.
// Draw document
<Score.MusicScoreView doc={doc} />
// Add playback buttons
<Score.PlaybackButtons doc={doc} buttonLayout={Score.PlaybackButtonsLayout.PlayStopSingle}/> // Single Play/Stopo button
<Score.PlaybackButtons doc={doc} buttonLayout={Score.PlaybackButtonsLayout.PlayStop}/> // Play and Stop buttons
<Score.PlaybackButtons doc={doc} buttonLayout={Score.PlaybackButtonsLayout.PlayPauseStop}/> // Play, Pause and Stop buttons
Bootstrap is used for better visual appearance but you must load it.
<!-- Add canvas -->
<canvas id="canvasId"></canvas>
<!-- Add play button -->
<button id="playButtonId"></button>
<!-- Add pause button -->
<button id="pauseButtonId"></button>
<!-- Add stop button -->
<button id="stopButtonId"></button>
<!-- Or add combined play/stop button -->
<button id="playStopButtonId"></button>
// Draw document
let r = new Score.MRenderer().
setCanvas("canvasId").
setDocument(doc).
draw();
// Add playback buttons
let p = new Score.MPlaybackButtons().
setPlayButton("playButtonId").
setPauseButton("pauseButtonId").
setStopButton("stopButtonId").
setDocument(doc);
// You can also set combined play/stop button.
p.setPlayStopButton("playStopButtonId")
// You can also pass HTMLButtonElement instead of element id.
p.setPlayButton(playButtonElement)
try {
// Invalid note "C" without octave.
m.addNote(0, "C", Score.NoteLength.Quarter);
}
catch(e) {
// MusicError is raised on errors.
if(e instanceof Score.MusicError) {
console.log(e);
}
}
This library is bundled to ESM, CJS and UMD formats.
While designed for compatibility in mind, the library has not been explicitly tested against specific Node.js or browser versions.
Found a bug or unexpected behavior?
You can also suggest a feature or impovement.
Thanks for helping improve the project!
This project is licensed under the MIT License.
It also bundles the Tone.js library, which is licensed under the MIT License.