@tspro/web-music-score
    Preparing search index...

    @tspro/web-music-score

    WebMusicScore

    This library allows you to view and play music scores (notation) in the browser.

    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 is a work in progress project. Expect changes, bugs, or unexpected behavior.

    Breaking: Version 2 is major update and brought many changes.

    • Introduced subpath modules instead of one big main module. There is no main export.
    • Theory module had big refactor that affected whole library. Renamed all musical terms that were wrong (e.g. pitch => diatonicId, noteId => chromaticId).
    • Score module stayed mostly same. Some changes (e.g. enum StaffKind => StaffPreset) but nothing major.
    • Classical guitar audio was put into separate module (audio-cg) because it bundles over 1MB of audio samples. Also improved default synthesizer audio.
    • Numerous small changes/improvements.

    Enough changes until next major update!

    Breaking: Version 3 is another major update and brought some important changes.

    • Support score configuration with multiple notation lines (combination of staves and tabs).
    • Introduced DocumentBuilder to create scores, removed old way.
    • DocumentOptions functionality is replaced using functions addScoreConfiguration() and setMeasuresPerRow() in DocumentBuilder.
    • Add ties, slurs and slides using addConnective() in DocumentBuilder. Tie and span options removed from NoteOptions.
    npm i @tspro/web-music-score
    
    // Import core module, it does not contain much.
    import * as Core from "@tspro/web-music-score/core";

    // Import audio module, it can play notes.
    import * as Audio from "@tspro/web-music-score/audio";

    // Import theory module, it contains all music theory stuff.
    import * as Theory from "@tspro/web-music-score/theory";

    // Import score module, it contains music score stuff.
    import * as Score from "@tspro/web-music-score/score";

    // Import react-ui module, it contains all react components.
    // React is peer dependency "^18.0.0 || ^19.0.0".
    import * as ScoreUI from "@tspro/web-music-score/react-ui";

    // Import pieces module, it contains demo songs.
    import * as Pieces from "@tspro/web-music-score/pieces";

    // You can also use require
    const Core = require("@tspro/web-music-score/core");

    // etc.

    This is an experimental module that can be used in html page via unpkg CDN. It declares global variable WebMusicScore that contains Core, Audio, Theory, Score, and Pieces as corresponding subpath modules (excluding react-ui and audio-cg).

    <script src="https://unpkg.com/@tspro/web-music-score@3"></script>
    <script src="https://unpkg.com/@tspro/web-music-score@3.0.0"></script>
    <script src="https://unpkg.com/@tspro/web-music-score@3.0.0/dist/iife/index.global.js"></script>

    <!--
    Use one of above. It is recommended to use version number (e.g. @3.0.0 or at least @3).
    This way if there is breaking change between versions your code does not stop working.
    -->

    <script>
    const { Core, Audio, Theory, Score, Pieces } = window.WebMusicScore;
    // ...
    </script>

    Typedoc API reference is available here. It is not commented but is mostly self explanatory and gives idea of full API.

    Following is the main interface explained.

    Documents are created using DocumentBuilder.

    let builder = new Score.DocumentBuilder();

    // Here build document, e.g.
    builder
    .addMEasure()
    .addNote(0, "C3", Theory.NoteLength.Quarter)
    // etc.

    // When ready, get document:
    let doc = builder.getDocument();

    Setting score configuration takes place in first measure of next row.

    builder.setScoreConfiguration(staffPreset: Score.StaffPreset);
    

    staffPreset can be:

    • Score.StaffPreset.Treble: Staff with treble (G-) clef.
    • Score.StaffPreset.Bass: Staff with bass (F-) clef.
    • Score.StaffPreset.Grand: Both treble and bas staves.
    • Score.StaffPreset.GuitarTreble: Same as Treble but one octave down.
    • Score.StaffPreset.GuitarTab: Guitar tab only.
    • Score.StaffPreset.GuitarCombined: Treble and tab for guitar.
    // Example
    builder.setScoreConfiguration(Score.StaffPreset.GuitarCombined);
    builder.setScoreConfiguration(config: Score.StaffConfig | Score.TabConfig);
    builder.setScoreConfiguration(config: (Score.StaffConfig | Score.TabConfig)[]);

    config is StaffConfig, TabConfig or array of combination.

    StaffConfig contains following properties:

    • type: "staff"
    • clef: Clef can be Score.Clef.G or Score.Clef.F.
    • isOctaveDown: boolean (optional)
    • minNote: string (optional), minimum note allowed in staff.
    • maxNote: string (optional), maximum note allowed in staff.
    • voiceIds: number[] (optional), array of voice ids are visible on this staff.
    • isGrand: boolean (optional), use this to create grand staff.

    TabConfig contains following properties:

    • type: "tab"
    • tuning: string | string[] (optional), tuning name or array of 6 note names for tuning.
    • voiceIds: number[] (optional), array of voice ids are visible on this tab.
    // Example: Staff and tab for guitar
    builder.setScoreConfiguration([
    { type: "staff", clef: Score.Clef.G, isOctaveDown: true },
    { type: "tab", tuning: "Drop D" }
    ]);

    // Example: Grand staff
    builder.setScoreConfiguration([
    { type: "staff", clef: Score.Clef.G, isGrand: true },
    { type: "staff", clef: Score.Clef.F, isGrand: true }
    ]);
    builder.setMesuresPerRow(measuresPerRow: number)
    

    measuresPerRow can be integer >= 1, or Infinity (default).

    builder.setHeader(title?: string, composer?: string, arranger?: string);

    // Example
    builder.setHeader("Demo Song");
    builder.addMeasure();
    
    builder.endRow();
    

    Manually induce row change. Next measure that is added will begin new row.

    builder.setKeySignature(tonic: string, scaleType: Theory.ScaleType);

    // Example: Am
    builder.setKeySignature("A", Theory.ScaleType.Aeolian);

    tonic is scale tonic/root note, e.g. "C" (in "C Major").

    scaleType can be

    • Theory.ScaleType.Major
    • Theory.ScaleType.NaturalMinor
    • Theory.ScaleType.HarmonicMinor
    • Theory.ScaleType.Ionian
    • Theory.ScaleType.Dorian
    • Theory.ScaleType.Phrygian
    • Theory.ScaleType.Lydian
    • Theory.ScaleType.Mixolydian
    • Theory.ScaleType.Aeolian
    • Theory.ScaleType.Locrian
    • Theory.ScaleType.MajorPentatonic
    • Theory.ScaleType.MinorPentatonic
    • Theory.ScaleType.MajorHexatonicBlues
    • Theory.ScaleType.MinorHexatonicBlues
    • Theory.ScaleType.HeptatonicBlues
    builder.setTimeSignature(timeSignature: string);

    // Example
    builder.setTimeSignature("3/4");

    timeSignature can be:

    • "2/4"
    • "3/4"
    • "4/4"
    • "6/8"
    • "9/8"
    builder.setTempo(beatsPerMinute: number, beatLength?: Theory.NoteLength, dotted?: boolean);

    // Example
    builder.setTempo(100, Theory.NoteLength.Quarter);

    beatsPerMinute is self explanatory.

    beatLength tells the length of each beat, e.g. Theory.NoteLength.Quarter.

    dotted tells if beatLength is dotted.

    builder.addNote(voiceId: number, note: string, noteLength: Theory.NoteLength, noteOptions?: Score.NoteOptions);
    builder.addChord(voiceId: number, notes: string[], noteLength: Theory.NoteLength, noteOptions?: Score.NoteOptions);

    // Examples
    builder.addNote(0, "C4", Theory.NoteLength.Half, { dotted: true });
    builder.addChord(1, ["C3", "E3", "G3"], Theory.NoteLength.Whole, { arpeggio: Score.Arpeggio.Down });

    voiceId can be 0, 1, 2 or 3.

    note is note name, e.g. "G#3", "Db3".

    notes: array of notes string[] (e.g. ["C3", "E3"])

    noteLength can be:

    • Theory.NoteLength.Whole
    • Theory.NoteLength.Half
    • Theory.NoteLength.Quarter
    • Theory.NoteLength.Eighth
    • Theory.NoteLength.Sixteenth
    • Theory.NoteLength.ThirtySecond
    • Theory.NoteLength.SixtyFourth

    noteOptions is optional object of note options (e.g. { dotted: true }):

    Note option Type
    dotted boolean Create dotted note.
    stem Score.Stem.Auto/Up/Down Set stem direction.
    arpeggio Score.Arpeggio.Up/Down | boolean Play column in arpeggio.
    staccato boolean Play column in staccato.
    diamond boolean Diamond shaped note head.
    triplet boolean Set this note part of triplet.
    string number | number[] String number for guitar tab. Array of string numbers for chord.
    builder.addRest(voideId: number, restLength: Theory.NoteLength, restOptions?: Score.RestOptions);

    // Example
    builder.addRest(0, Theory.NoteLength.Sixteenth);

    voiceId can be 0, 1, 2 or 3.

    restLength is length of rest, similar as noteLength above.

    restOptions is optional object of rest options (e.g. { hide: true }):

    Rest option Type
    dotted boolean Create dotted rest.
    staffPos string Staff positions (e.g. "C3").
    hide boolean Add invisible rest.
    triplet boolean Set this rest part of triplet.
    builder.addFermata(fermata?: Score.Fermata);

    // Example
    builder.addFermata(Score.Fermata.AtMeasureEnd);

    fermata is typeof Score.Fermata and can be:

    • Score.Fermata.AtNote: Adds fermata anchored to previously added note, chord or rest.
    • Score.Fermata.AtMeasureEnd: Adds fermata at the end of measure.
    // Add tie
    builder.addConnective(connective: Score.Connetive.Tie, span?: Score.ConnectiveSpan, noteAnchor?: Score.NoteAnchor);

    // Add slur
    builder.addConnective(connective: Score.Connetive.Slur, span?: Score.ConnectiveSpan, noteAnchor?: Score.NoteAnchor);

    // Add slide
    builder.addConnective(connective: Score.Connetive.Slide, noteAnchor?: Score.NoteAnchor);
    • span describes how many notes the connective is across. It is integer >= 2 (for tie it can be also Score.TieType.Stub|ToMeasureEnd). Default value is 2.
    • noteAnchor describes the attach point of connective to note. It can be Score.NoteAnchor.Auto|Above|Center|Below|StemTip. Default value is Score.NoteAnchor.Auto.

    Add navigational element to measure.

    builder.addNavigation(navigation: Score.Navigation, ...args?);

    // Examples
    builder.addNavigation(Score.Navigation.StartRepeat);
    builder.addNavigation(Score.Navigation.EndRepeat, 3);
    builder.addNavigation(Score.Navigation.Ending, 1, 2);

    navigation can be:

    • Score.Navigation.DC_al_Fine
    • Score.Navigation.DC_al_Coda
    • Score.Navigation.DS_al_Fine
    • Score.Navigation.DS_al_Coda
    • Score.Navigation.Coda
    • Score.Navigation.toCoda
    • Score.Navigation.Segno
    • Score.Navigation.Fine
    • Score.Navigation.StartRepeat
    • Score.Navigation.EndRepeat
    • Score.Navigation.Ending

    Score.Navigation.EndRepeat takes optional second arg which is number of times to repeat (once if omitted).

    Score.Navigation.Ending takes variable number of number args, each is a passage number.

    Add text label anchored to previously added note, chord or rest.

    builder.addLabel(label: Score.Label, text: string);

    // Example
    builder.addLabel(Score.Label.Chord, "Am);

    label can be:

    • Score.Label.Note: Used to label notes and is positioned below note.
    • Score.Label.Chord: Used to label chords and is positioned on top.

    Add annotation text anchored to previously added note, chord or rest.

    builder.addAnnotation(annotation: Score.Annotation, text: string);

    // Example
    builder.addAnnotation(Score.Annotation.Tempo, "accel.");

    annotation can be:

    • Score.Annotation.Dynamics: text could be for example "fff", "cresc.", "dim.", etc.
    • Score.Annotation.Tempo: text could be for example "accel.", "rit.", "a tempo", etc.

    Adds extension line to element, for example to previously added annotation.

    builder.addExtension(extensionLength: number, visible?: boolean);

    // Example
    builder.addAnnotation(Score.Annotation.Tempo, "accel.").addExtension(Theory.NoteLength.Whole * 2, true);

    extensionLength is number but Theory.NoteLength values can be used as number and multiplied to set desired extension length.

    visible sets visibility of extension line, visible by default (if omitted).

    This library has preliminary guitar tabs rendering. Create document with Score.StaffPreset.GuitarTab or Score.StaffPreset.GuitarCombined, or set score configuration with TabConfig.

    Add notes with { string: number | number[] } to specify which string the fret number is rendered in guitar tab.

    // Single note
    builder.addNote(0, "G3", Theory.NoteLength.Eighth, { string: 3 });

    // Multi note
    builder.addChord(0, ["E4", "C3"], Theory.NoteLength.Eighth, { string: [1, 5] });

    DocumentBuilder operations can be queued.

    let doc = new Score.DocumentBuilder()
    .addScoreConfiguration({ type: "staff", clef: Score.Clef.G, isOctavewDown: true })
    .setMeasuresPerRow(4)
    .addMeasure()
    .addNote(1, "C3", Theory.NoteLength.Quarter)
    .addChord(1, ["C3", "E3", "G3"], Theory.NoteLength.Quarter).addLabel(Score.Label.Chord, "C")
    .addRest(1, Theory.NoteLength.Quarter)
    // etc.
    .getDEocument();

    Beams are detected and added automatically.

    Default instrument is Synthesizer.

    Classical Guitar is available via audio-cg module. It was included as separate module because it contains over 1MB of audio samples bundled in it.

    import { registerClassicalGuitar } from "@tspro/web-music-score/audio-cg";

    registerClassicalGuitar();
    // Simple play
    doc.play();

    // More playback options:
    let player = new MPlayer(doc);

    player.play();
    player.pause();
    player.stop();

    MPlayer.stopAll();
    // Draw document
    <ScoreUI.MusicScoreView doc={doc} />

    // Add playback buttons
    <ScoreUI.PlaybackButtons doc={doc} buttonLayout={ScoreUI.PlaybackButtonsLayout.PlayStopSingle}/> // Single Play/Stopo button
    <ScoreUI.PlaybackButtons doc={doc} buttonLayout={ScoreUI.PlaybackButtonsLayout.PlayStop}/> // Play and Stop buttons
    <ScoreUI.PlaybackButtons doc={doc} buttonLayout={ScoreUI.PlaybackButtonsLayout.PlayPauseStop}/> // Play, Pause and Stop buttons

    Bootstrap is used for better visual appearance, but it needs to be installed and loaded.

    <!-- 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 {
    // Do your music stuff
    }
    catch (e) {
    if(e instanceof Core.MusicError) {
    // There was music error.
    }
    }
    • This library is bundled to ESM, CJS and IIFE formats.
    • Target is to support ES6/ES2015.
    • No polyfills are included.

    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?

    Please open a new issue.

    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.