🎵 Music notation engraving library for MEI with MusicXML and Humdrum support and various toolkits (JavaScript, Python)

Overview

License: LGPL v3 PyPI PyPI - Wheel AppVeyor status GH Actions status

Verovio is a fast, portable and lightweight library for engraving Music Encoding Initiative (MEI) digital scores into SVG images. Verovio also contains on-the-fly converters to render Plaine & Easie Code, Humdrum, Musedata, MusicXML, EsAC, and ABC digital scores.

Verovio is written in standard 2017 C++ and can be compiled as a standalone command-line tool, used as a compiled music-rendering library for applications (Qt, python), or compiled into Javascript using the Emscripten LLVM-to-JavaScript compiler. Check out the JavaScript toolkit version of verovio running in the MEI Viewer as well as the app or tutorials for web integration and user interaction.

Choice interaction

Verovio uses the Standard Music Font Layout (SMuFL) specification and the font can be changed for personalizing the output.

The project page is https://www.verovio.org. Verovio is available under the LGPL license (see COPYING and COPYING.LESSER).

Building and use instructions by environment

See the Reference book

LibMEI

The code for the attribute classes of Verovio are generated from the MEI schema using a modified version of LibMEI available here. The code generated is included in the Verovio repository and the LibMEI repository does not need to be cloned for building Verovio.

Major releases of Verovio and MEI versions:

  • Verovio 1.x.x ⇔ MEI 3.0
  • Verovio 2.x.x ⇔ MEI 4.0
  • Verovio 3.x.x ⇔ Development of MEI since 4.0

From Verovio 2.x.x, the plan is to have even version numbers for Verovio releases using a stable version of MEI, and odd version numbers for releases using a development version of MEI. It means that once MEI 5.0 will be released, Verovio will move to version 4.x.x. Older versions of MEI are still supported by newer versions of Verovio. MEI files are internally upgraded when loaded into Verovio. This applies only to the features supported by Verovio. We will try to maintain this in the future.

Other libraries

The following libraries are embedded in Verovio:

library purpose
humlib Humdrum file import/export
JSON++ JSON data parser
MidiFile Standard MIDI file export
pugixml XML data parser
UTF-CPP UTF character conversions
MINIZ-CPP ZIP files reading/writing

Contributing

See the Reference book

Example output

The sample page of music shown below was generated with version 2.4.0-dev-2748fed

Example page

Example resources using verovio

name type description
Verovio Humdrum Viewer editor An online semi-graphical Humdrum data editor (can also be used to textually edit other digital scores compliant with verovio).
MoVI repertory The digital Mozart digital score VIewer at the Mozarteum
Tasso in Music Project repertory Musical settings of the poetry of Torquato Tasso
Measuring Polyphony repertory Late medieval music in black mensural and modern notations
Probstücke Digital repertory open and critical digital edition of Mattheson's test pieces
370 Bach Chorales repertory Online edition of Bach chorales, including an interactive typesetter page that allows for creating musical examples for online display or use in papers.
Humdrum Notation Plugin tool Javascript interface to verovio for displaying multiple musical examples on a webpage
Music Sheet Viewer tool WordPress plugin for displaying graphical music from MEI data

Digital score repositories on Github

Here is a list of digital score repositories on Github that can be displayed with verovio:

link encoding description
MEI complete examples MEI 86 various works encoded in MEI
Mozart Piano Sonatas Humdrum 17 Piano sonatas by W.A. Mozart from the Alte Mozart-Ausgabe (in VHV)
Beethoven Piano Sonatas Humdrum 32 Piano sonatas by L. van Beethoven, edited by Paul Dukas (in VHV)
Josquin Research Project Humdrum Over 1000 scores of early Renaissance music in modern editions (website)
Tasso in Music Project Humdrum Critical edition of 650 Late Renaissance madrigals using the poetry of Torquato Tasso for lyrics. (website)
Music of Scott Joplin Humdrum Digital scores of most of Scott Joplins music
Chopin mazurkas Humdrum Digital scores of Chopin's mazurkas
Chopin preludes Humdrum Digital scores of Chopin's op. 24 preludes
J.N. Hummel preludes, op. 67 Humdrum 24 improvisatory prelude examples in every key
370 Bach chorales Humdrum Chorales collected by C.P.E. Bach after his father's death (website)
Deutscher Liederschatz Humdrum 200 harmonized songs from vol. 1, edited by Ludwig Erk
Beethoven string quartets Humdrum 18 string quartets by Ludwig van Beethoven
Issues
  • implement <annot> display

    implement display

    Rendering of <annot> data would be useful to have in verovio. This would function in a very similar manner to the current <harm> implementation, but both should add horizontal collision avoidance between adjacent <annot> and <harm> entries (similar to the current implementation of <verse>.

    It would also be useful if @n were implemented for <annot> (and perhaps <harm>) which would stack annotations in a similar manner to <verse>; i.e., @n would handle vertical collision avoidance between separate streams of annotations.

    Test data:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="3.0.0">
        <meiHead>
            <fileDesc>
                <titleStmt>
                    <title />
                </titleStmt>
                <pubStmt>
                    <date>2016-12-19 17:26:49</date>
                </pubStmt>
            </fileDesc>
            <encodingDesc>
                <projectDesc>
                    <p>Transcoded from Humdrum with Verovio version 0.9.13-dev-1745ac2</p>
                </projectDesc>
            </encodingDesc>
        </meiHead>
        <music>
            <body>
                <mdiv>
                    <score>
                        <scoreDef>
                            <staffGrp>
                                <staffDef clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5" />
                            </staffGrp>
                        </scoreDef>
                        <section>
                            <measure n="1">
                                <staff n="1">
                                    <layer n="1">
                                        <note dur="4" oct="4" pname="c" accid.ges="n" />
                                        <note dur="4" oct="4" pname="d" accid.ges="n" />
                                        <note dur="4" oct="4" pname="e" accid.ges="n" />
                                        <note dur="4" oct="4" pname="f" accid.ges="n" />
                                    </layer>
                                </staff>
                                <annot n="1" label="test"   staff="1" tstamp="1.000000">this</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="1.000000">0</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="2.000000">1</annot>
                                <annot n="1" label="test"   staff="1" tstamp="3.000000">is</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="3.000000">2</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="4.000000">3</annot>
                            </measure>
                            <measure n="2" right="end">
                                <staff n="1">
                                    <layer n="1">
                                        <note dur="4" oct="4" pname="g" accid.ges="n" />
                                        <note dur="4" oct="4" pname="a" accid.ges="n" />
                                        <note dur="4" oct="4" pname="b" accid.ges="n" />
                                        <note dur="4" oct="5" pname="c" accid.ges="n" />
                                    </layer>
                                </staff>
                                <annot n="1" label="test"   staff="1" tstamp="1.000000">a</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="1.000000">4</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="2.000000">5</annot>
                                <annot n="1" label="test"   staff="1" tstamp="3.000000">test</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="3.000000">6</annot>
                                <annot n="2" label="qstamp" staff="1" tstamp="4.000000">7</annot>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>
    

    Target rendering (placement above/below the staff could be similar to <verse> or <harm> with default above or below the staff).

    screen shot 2016-12-19 at 17 45 03

    Also see discussion for issue #388.

    feature request 
    opened by craigsapp 73
  • note without stem?

    note without stem?

    Is there a way to draw a note without a stem, such as a quarter note?

    I don't see how to do this in the MEI guidlines. The only values for @stem.dir are up and down, so maybe the information can be put there. There is also a @stem.len. And verovio does not process that attribute yet anyway.

    Another idea is: there is a @head.visible, so a @stem.visible would be a nice parallel to add to the MEI spec to hide stems for note elements.

    opened by craigsapp 66
  • Add timestamp attribute for each note in svg

    Add timestamp attribute for each note in svg

    Is it a bad idea to be able to generate the time stamp for each note in the SVG file?

    I want to generate the SVG file on a server application and use it on a client and be able to select active note(s) at a specific time, just as getElementsAtTime (milliseconds) works, without having to load the EMI file.

    feature request 
    opened by k-ljung 44
  • Build test suite with GitHub Actions

    Build test suite with GitHub Actions

    It is now failing on building the doxygen documentation. Error message is

    The job exceeded the maximum log length, and has been terminated.
    

    Weird since it fails after about 5 minutes only. See https://travis-ci.org/github/rism-ch/verovio/builds/733209808

    At this stage I would be quite happy to move to GitHub Actions. Help appreciated ;-)

    enhancement documentation / test suite 
    opened by lpugin 40
  • @n for <harm>

    @n for

    Is there a way to have multiple harmony lines similar to mutiple verses?

    Here is an example where I have two analyses being display via <harm>, but they overstrike each other:

    screen shot 2016-12-18 at 20 39 55

    In this case they cannot be displayed as <verse>s since the data is attached to timestamps rather than notes. (see for example above the whole-measure rests).

    I have tried @y, @x, @n, and @vo, none of which are currently implemented. Perhaps the most convenient method would be @n, working in a similar manner to lyrics, with verovio deciding on the layout adjustments to alter vertical positioning of <harm> elements.

    MEI test data:

    !!!filter: recip -cxaemxhm|metlev -caxemxhm
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="3.0.0">
        <meiHead>
            <fileDesc>
                <titleStmt>
                    <title />
                </titleStmt>
                <pubStmt>
                    <date>2016-12-18 20:53:57</date>
                </pubStmt>
            </fileDesc>
            <encodingDesc>
                <projectDesc>
                    <p>Transcoded from Humdrum with Verovio version 0.9.13-dev-2a282ac-dirty</p>
                </projectDesc>
            </encodingDesc>
            <extMeta>
                <frames xmlns:humxml="http://www.humdrum.org/ns/humxml">
                    <metaFrame n="0" token="!!!filter: recip -cxaemxhm|metlev -caxemxhm" xml:id="loc0">
                        <frameInfo>
                            <startTime float="0" />
                            <frameType>reference</frameType>
                            <referenceKey>filter</referenceKey>
                            <referenceValue>recip -cxaemxhm|metlev -caxemxhm</referenceValue>
                        </frameInfo>
                    </metaFrame>
                    <metaFrame n="1" token="!!!voices: 3" xml:id="loc1">
                        <frameInfo>
                            <startTime float="0" />
                            <frameType>reference</frameType>
                            <referenceKey>voices</referenceKey>
                            <referenceValue>3</referenceValue>
                        </frameInfo>
                    </metaFrame>
                </frames>
            </extMeta>
        </meiHead>
        <music>
            <body>
                <mdiv>
                    <score>
                        <scoreDef xml:id="scoredef-000000199460590">
                            <staffGrp xml:id="m-000000101126834" symbol="bracket">
                                <staffDef xml:id="staffdef-000000002182961" clef.shape="G" clef.line="2" key.sig="0" meter.count="2" meter.unit="1" meter.sym="cut" n="1" label="Superius" label.abbr="S" lines="5" />
                                <staffDef xml:id="staffdef-000000048101113" clef.shape="G" clef.line="2" clef.dis="8" clef.dis.place="below" key.sig="0" meter.count="2" meter.unit="1" meter.sym="cut" n="2" label="Tenor" label.abbr="T" lines="5" />
                                <staffDef xml:id="staffdef-000000091919075" clef.shape="G" clef.line="2" clef.dis="8" clef.dis.place="below" key.sig="0" meter.count="2" meter.unit="1" meter.sym="cut" n="3" label="Contra" label.abbr="C" lines="5" />
                            </staffGrp>
                        </scoreDef>
                        <section xml:id="section-000000093141442">
                            <measure xml:id="measure-L13" n="1">
                                <staff xml:id="staff-L13F3" n="1">
                                    <layer xml:id="layer-L13F3" n="1">
                                        <mRest xml:id="mrest-000000088119035" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L13F2" n="2">
                                    <layer xml:id="layer-L13F2" n="1">
                                        <mRest xml:id="mrest-000000044837993" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L13F1" n="3">
                                    <layer xml:id="layer-L13F1" n="1">
                                        <note xml:id="note-L14F1" dur="4" oct="3" pname="c" accid.ges="n" />
                                        <note xml:id="note-L15F1" dur="4" oct="3" pname="d" accid.ges="n" />
                                        <note xml:id="note-L16F1" dur="4" oct="3" pname="e" accid.ges="n" />
                                        <note xml:id="note-L17F1" dur="4" oct="3" pname="f" accid.ges="n" />
                                        <note xml:id="note-L18F1" dur="2" oct="3" pname="g" accid.ges="n" />
                                        <note xml:id="note-L19F1" dur="2" oct="3" pname="a" accid.ges="n" />
                                    </layer>
                                </staff>
                                <harm xml:id="harm-L14F4" staff="1" tstamp="1.000000">4</harm>
                                <harm xml:id="harm-L14F5" staff="1" tstamp="1.000000">0</harm>
                                <harm xml:id="harm-L15F4" staff="1" tstamp="1.250000">4</harm>
                                <harm xml:id="harm-L15F5" staff="1" tstamp="1.250000">2</harm>
                                <harm xml:id="harm-L16F4" staff="1" tstamp="1.500000">4</harm>
                                <harm xml:id="harm-L16F5" staff="1" tstamp="1.500000">1</harm>
                                <harm xml:id="harm-L17F4" staff="1" tstamp="1.750000">4</harm>
                                <harm xml:id="harm-L17F5" staff="1" tstamp="1.750000">2</harm>
                                <harm xml:id="harm-L18F4" staff="1" tstamp="2.000000">2</harm>
                                <harm xml:id="harm-L18F5" staff="1" tstamp="2.000000">0</harm>
                                <harm xml:id="harm-L19F4" staff="1" tstamp="2.500000">2</harm>
                                <harm xml:id="harm-L19F5" staff="1" tstamp="2.500000">1</harm>
                                <tie xml:id="tie-000000097174124" startid="#note-L19F1" endid="#note-L21F1" />
                            </measure>
                            <measure xml:id="measure-L20" n="2">
                                <staff xml:id="staff-L20F3" n="1">
                                    <layer xml:id="layer-L20F3" n="1">
                                        <mRest xml:id="mrest-000000100615103" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L20F2" n="2">
                                    <layer xml:id="layer-L20F2" n="1">
                                        <mRest xml:id="mrest-000000189426791" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L20F1" n="3">
                                    <layer xml:id="layer-L20F1" n="1">
                                        <note xml:id="note-L21F1" dur="4" oct="3" pname="a" accid.ges="n" />
                                        <note xml:id="note-L22F1" dur="4" oct="3" pname="g" accid.ges="n" />
                                        <note xml:id="note-L23F1" dur="1" oct="4" pname="c" accid.ges="n" />
                                        <note xml:id="note-L24F1" dur="2" oct="3" pname="b" accid.ges="n" />
                                    </layer>
                                </staff>
                                <harm xml:id="harm-L21F4" staff="1" tstamp="1.000000">4</harm>
                                <harm xml:id="harm-L22F4" staff="1" tstamp="1.250000">4</harm>
                                <harm xml:id="harm-L22F5" staff="1" tstamp="1.250000">2</harm>
                                <harm xml:id="harm-L23F4" staff="1" tstamp="1.500000">1</harm>
                                <harm xml:id="harm-L23F5" staff="1" tstamp="1.500000">1</harm>
                                <harm xml:id="harm-L24F4" staff="1" tstamp="2.500000">2</harm>
                                <harm xml:id="harm-L24F5" staff="1" tstamp="2.500000">1</harm>
                            </measure>
                            <measure xml:id="measure-L25" n="3">
                                <staff xml:id="staff-L25F3" n="1">
                                    <layer xml:id="layer-L25F3" n="1">
                                        <mRest xml:id="mrest-000000112486666" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L25F2" n="2">
                                    <layer xml:id="layer-L25F2" n="1">
                                        <note xml:id="note-L26F2" dur="4" oct="3" pname="c" accid.ges="n" />
                                        <note xml:id="note-L27F2" dur="4" oct="3" pname="d" accid.ges="n" />
                                        <note xml:id="note-L28F2" dur="4" oct="3" pname="e" accid.ges="n" />
                                        <note xml:id="note-L29F2" dur="4" oct="3" pname="f" accid.ges="n" />
                                        <note xml:id="note-L30F2" dur="2" oct="3" pname="g" accid.ges="n" />
                                        <note xml:id="note-L31F2" dur="2" oct="3" pname="a" accid.ges="n" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L25F1" n="3">
                                    <layer xml:id="layer-L25F1" n="1">
                                        <note xml:id="note-L26F1" dur="1" oct="4" pname="c" accid.ges="n" />
                                        <rest xml:id="rest-L30F1" dur="2" />
                                        <note xml:id="note-L31F1" dur="2" oct="3" pname="f" accid.ges="n" />
                                    </layer>
                                </staff>
                                <harm xml:id="harm-L26F4" staff="1" tstamp="1.000000">4</harm>
                                <harm xml:id="harm-L26F5" staff="1" tstamp="1.000000">0</harm>
                                <harm xml:id="harm-L27F4" staff="1" tstamp="1.250000">4</harm>
                                <harm xml:id="harm-L27F5" staff="1" tstamp="1.250000">2</harm>
                                <harm xml:id="harm-L28F4" staff="1" tstamp="1.500000">4</harm>
                                <harm xml:id="harm-L28F5" staff="1" tstamp="1.500000">1</harm>
                                <harm xml:id="harm-L29F4" staff="1" tstamp="1.750000">4</harm>
                                <harm xml:id="harm-L29F5" staff="1" tstamp="1.750000">2</harm>
                                <harm xml:id="harm-L30F4" staff="1" tstamp="2.000000">2</harm>
                                <harm xml:id="harm-L30F5" staff="1" tstamp="2.000000">0</harm>
                                <harm xml:id="harm-L31F4" staff="1" tstamp="2.500000">2</harm>
                                <harm xml:id="harm-L31F5" staff="1" tstamp="2.500000">1</harm>
                                <tie xml:id="tie-000000042866793" startid="#note-L31F2" endid="#note-L33F2" />
                                <tie xml:id="tie-000000082856367" startid="#note-L31F1" endid="#note-L33F1" />
                            </measure>
                            <measure xml:id="measure-L32" n="4">
                                <staff xml:id="staff-L32F3" n="1">
                                    <layer xml:id="layer-L32F3" n="1">
                                        <mRest xml:id="mrest-000000126322598" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L32F2" n="2">
                                    <layer xml:id="layer-L32F2" n="1">
                                        <note xml:id="note-L33F2" dur="4" oct="3" pname="a" accid.ges="n" />
                                        <note xml:id="note-L34F2" dur="4" oct="3" pname="g" accid.ges="n" />
                                        <note xml:id="note-L35F2" dur="1" oct="4" pname="c" accid.ges="n" />
                                        <note xml:id="note-L37F2" dur="2" oct="3" pname="b" accid.ges="n" />
                                    </layer>
                                </staff>
                                <staff xml:id="staff-L32F1" n="3">
                                    <layer xml:id="layer-L32F1" n="1">
                                        <note xml:id="note-L33F1" dur="2" oct="3" pname="f" accid.ges="n" />
                                        <note xml:id="note-L35F1" dur="2" oct="3" pname="e" accid.ges="n" />
                                        <note xml:id="note-L36F1" dur="1" oct="3" pname="d" accid.ges="n" />
                                    </layer>
                                </staff>
                                <harm xml:id="harm-L33F4" staff="1" tstamp="1.000000">4</harm>
                                <harm xml:id="harm-L34F4" staff="1" tstamp="1.250000">4</harm>
                                <harm xml:id="harm-L34F5" staff="1" tstamp="1.250000">2</harm>
                                <harm xml:id="harm-L35F4" staff="1" tstamp="1.500000">2</harm>
                                <harm xml:id="harm-L35F5" staff="1" tstamp="1.500000">1</harm>
                                <harm xml:id="harm-L36F4" staff="1" tstamp="2.000000">2</harm>
                                <harm xml:id="harm-L36F5" staff="1" tstamp="2.000000">0</harm>
                                <harm xml:id="harm-L37F4" staff="1" tstamp="2.500000">2</harm>
                                <harm xml:id="harm-L37F5" staff="1" tstamp="2.500000">1</harm>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>
    
    feature request raised priority 
    opened by craigsapp 39
  • Windows compiling problems

    Windows compiling problems

    Sorry for always coming up with this, but ~~verovio is a real diva when it comes to Windows~~ Windows is a real diva when it comes to verovio. After I have already given up to use the python wrapper, I now wanted to simply compile the CLI tool with Visual Studio 2015.

    Here is what I did:

    cd tools
    cmake . -DNO_PAE_SUPPORT=ON -DNO_HUMDRUM_SUPPORT=ON
    

    Then I opened the generated solution Verovio.sln in VS 2015, selected "Release Win32" and hit "Build". The compiler now seems to be caught in an endless loop, it just never finishes and the log messages repeat themselves. Among the first few lines, this error comes up:

    \tools\main.cpp(9): fatal error C1083: Cannot open include file: 'getopt.h': No such file or directory
    

    Is there any way to improve the general Windows compatibility of this project? Maybe automated tests in a VM? I would be really glad to help, but I don't know where to start.

    opened by sonovice 38
  • Issue Importing on Ubuntu/Python3

    Issue Importing on Ubuntu/Python3

    Hello,

    I'm trying to host a web-app using verovio, and I've created a droplet on DigitalOcean to try to host the app. The droplet runs Ubuntu 16.04.2

    I've successfully installed verovio on python3.6 using the installation steps in the wiki (and tweaking the memory of the droplet). However, when I try to import verovio, I get this large error:

    [email protected]:~/verovio/python# python3.6
    Python 3.6.1 (default, Mar 22 2017, 10:05:53)
    [GCC 5.4.1 20170304] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import verovio
    Traceback (most recent call last):
      File "/root/verovio/python/verovio.py", line 18, in swig_import_helper
        fp, pathname, description = imp.find_module('_verovio', [dirname(__file__)])
      File "/usr/lib/python3.6/imp.py", line 296, in find_module
        raise ImportError(_ERR_MSG.format(name), name=name)
    ImportError: No module named '_verovio'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/root/verovio/python/verovio.py", line 28, in <module>
        _verovio = swig_import_helper()
      File "/root/verovio/python/verovio.py", line 20, in swig_import_helper
        import _verovio
    ImportError: /usr/local/lib/python3.6/dist-packages/verovio-0.9.12-py3.6-linux-x86_64.egg/_verovio.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZN3hum17Tool_musicxml2hum7convertERSoRN4pugi12xml_documentE
    Error in sys.excepthook:
    Traceback (most recent call last):
      File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
        from apport.fileutils import likely_packaged, get_recent_crashes
      File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
        from apport.report import Report
      File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
        import apport.fileutils
      File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
        from apport.packaging_impl import impl as packaging
      File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 23, in <module>
        import apt
      File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
        import apt_pkg
    ModuleNotFoundError: No module named 'apt_pkg'
    
    Original exception was:
    Traceback (most recent call last):
      File "/root/verovio/python/verovio.py", line 18, in swig_import_helper
        fp, pathname, description = imp.find_module('_verovio', [dirname(__file__)])
      File "/usr/lib/python3.6/imp.py", line 296, in find_module
        raise ImportError(_ERR_MSG.format(name), name=name)
    ImportError: No module named '_verovio'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/root/verovio/python/verovio.py", line 28, in <module>
        _verovio = swig_import_helper()
      File "/root/verovio/python/verovio.py", line 20, in swig_import_helper
        import _verovio
    ImportError: /usr/local/lib/python3.6/dist-packages/verovio-0.9.12-py3.6-linux-x86_64.egg/_verovio.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZN3hum17Tool_musicxml2hum7convertERSoRN4pugi12xml_documentE
    >>>
    

    Any idea what a solution to this could be? Thank you!

    opened by misingnoglic 36
  • Pitch placement in measure with intermediate clef change

    Pitch placement in measure with intermediate clef change

    A problem occurs in clef assignment for notes when there is a clef change half-way through a measure, and the measure contains more than one layer:

    screen shot 2016-12-28 at 10 24 27

    The note which looks like an E6 in m3 is supposed to be a G4, because the G4 is being displayed in bass clef instead of treble clef. This is caused by the clef change in layer 1 affecting notes at earlier times in layer 2 before the clef change of layer 1 should be occurring in layer 2.

    This is related to #229, but for cases where the clef change is not at the end of the measure but rather in the middle.

    Test MEI data:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="3.0.0">
        <meiHead>
            <fileDesc>
                <titleStmt>
                    <title />
                </titleStmt>
                <pubStmt>
                    <date>2016-12-28 10:28:08</date>
                </pubStmt>
            </fileDesc>
            <encodingDesc>
                <projectDesc>
                    <p>Transcoded from Humdrum with Verovio version 0.9.13-dev-2f22b77</p>
                </projectDesc>
            </encodingDesc>
        </meiHead>
        <music>
            <body>
                <mdiv>
                    <score>
                        <scoreDef xml:id="scoredef-000000007953841">
                            <staffGrp xml:id="m-000000201294796">
                                <staffDef xml:id="staffdef-000000015908972" clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5" />
                            </staffGrp>
                        </scoreDef>
                        <section xml:id="section-000000010732145">
                            <measure xml:id="measure-L4" n="1">
                                <staff xml:id="staff-L4F1" n="1">
                                    <layer xml:id="layer-L4F1" n="1">
                                        <note xml:id="note-L5F1" dur="4" oct="4" pname="c" accid.ges="n" stem.dir="down" />
                                        <note xml:id="note-L6F1" dur="4" oct="4" pname="d" accid.ges="n" stem.dir="down" />
                                        <clef xml:id="clef-000000112079605" shape="F" line="4" />
                                        <note xml:id="note-L8F1" dur="4" oct="4" pname="c" accid.ges="n" stem.dir="up" />
                                        <note xml:id="note-L9F1" dur="4" oct="3" pname="b" accid.ges="n" stem.dir="up" />
                                    </layer>
                                </staff>
                            </measure>
                            <measure xml:id="measure-L10" n="2">
                                <staff xml:id="staff-L10F1" n="1">
                                    <layer xml:id="layer-L10F1" n="1">
                                        <clef xml:id="clef-000000031305307" shape="G" line="2" />
                                        <note xml:id="note-L12F1" dur="2" oct="4" pname="g" accid.ges="n" stem.dir="up" />
                                        <clef xml:id="clef-000000170476090" shape="F" line="4" />
                                        <note xml:id="note-L14F1" dur="2" oct="3" pname="g" accid.ges="n" stem.dir="down" />
                                    </layer>
                                </staff>
                            </measure>
                            <measure xml:id="measure-L15" n="2" right="end">
                                <staff xml:id="staff-L15F1" n="1">
                                    <layer xml:id="layer-L15F1" n="1">
                                        <clef xml:id="clef-000000184701767" shape="G" line="2" />
                                        <note xml:id="note-L18F1" dur="4" oct="4" pname="c" accid.ges="n" stem.dir="down" />
                                        <note xml:id="note-L19F1" dur="4" oct="4" pname="d" accid.ges="n" stem.dir="down" />
                                        <clef xml:id="clef-000000094643353" shape="F" line="4" />
                                        <note xml:id="note-L21F1" dur="4" oct="4" pname="c" accid.ges="n" stem.dir="up" />
                                        <note xml:id="note-L22F1" dur="4" oct="3" pname="b" accid.ges="n" stem.dir="up" />
                                    </layer>
                                    <layer xml:id="layer-L18F2" n="2">
                                        <note xml:id="note-L18F2" dur="2" oct="4" pname="g" accid.ges="n" stem.dir="up" />
                                        <note xml:id="note-L21F2" dur="2" oct="3" pname="g" accid.ges="n" stem.dir="down" />
                                    </layer>
                                </staff>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>
    

    Target rendering:

    screen shot 2016-12-28 at 10 34 34 enhancement low priority 
    opened by craigsapp 34
  • Analytical markup display

    Analytical markup display

    In measure 42 of this file:

    http://www.verovio.org/examples/downloads/Hummel_Concerto_for_trumpet.mei

    verovio displays two fermatas where there should only be one:

    screen shot 2017-10-28 at 9 24 31 pm

    MEI test data:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <?xml-model href="https://raw.githubusercontent.com/music-encoding/music-encoding/develop/schemata/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <?xml-model href="https://raw.githubusercontent.com/music-encoding/music-encoding/develop/schemata/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <mei xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.music-encoding.org/ns/mei" meiversion="3.0.0">
        <meiHead>
            <fileDesc>
                <titleStmt>
                    <title>Trumpet Concerto in E major</title>
                    <respStmt>
                        <persName role="creator">Johann Nepomuk Hummel</persName>
                    </respStmt>
                </titleStmt>
            </fileDesc>
        </meiHead>
        <music>
            <body>
                <mdiv>
                    <score>
                        <scoreDef meter.count="4" meter.unit="4" meter.sym="common" key.sig="4s" key.mode="major" system.leftline="true">
                            <pgHead>
                                <title>
                                    <rend fontsize="24" fontweight="bold" halign="center" valign="top">Trumpet Concerto in E<lb/>
                                    </rend>
                                    <lb/>
                                    <rend fontstyle="italic" fontsize="20" fontweight="bold">for Solo Trumpet &amp; Orchestra</rend>
                                    <lb/>
                                    <rend fontstyle="normal" fontsize="24" fontweight="bold"> </rend>
                                    <rend fontsize="12" fontweight="bold" halign="center" valign="top">Hummel - Trumpet Concerto in E - Score</rend>
                                    <rend fontsize="20" fontweight="bold" valign="top"> </rend>
                                    <lb/>
                                    <rend fontsize="16" fontweight="bold">(17':35")</rend>
                                    <rend fontsize="12" fontweight="bold" halign="right" valign="top">Johhan Nepomuk Hummel (1778 - 1837)<lb/>Arrangement &amp; Cadenza -Michel Rondeau</rend>
                                </title>
                            </pgHead>
                            <pgFoot>
                                <anchoredText x="805" y="49">
                                    <rend fontsize="11" fontweight="bold" halign="center" valign="bottom">© 2010 - Gatineau,Qc.Ca.</rend>
                                </anchoredText>
                            </pgFoot>
                            <staffGrp barthru="false">
                                <staffGrp barthru="true" symbol="bracket">
                                    <staffDef n="1" xml:id="P1" label="Flute" label.abbr="Fl." lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                    <staffDef n="2" xml:id="P2" label="Oboe 1" label.abbr="Ob. 1" lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                    <staffDef n="3" xml:id="P3" label="Oboe 2" label.abbr="Ob. 2" lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                    <staffDef n="4" xml:id="P4" label="Clarinet in Bb 1" label.abbr="Bb Cl. 1" lines="5" clef.line="2" clef.shape="G" key.sig="6s" key.mode="major" trans.semi="-2"
                                        trans.diat="-1"/>
                                    <staffDef n="5" xml:id="P5" label="Clarinet in Bb 2" label.abbr="Bb Cl. 2" lines="5" clef.line="2" clef.shape="G" key.sig="6s" key.mode="major" trans.semi="-2"
                                        trans.diat="-1"/>
                                </staffGrp>
                                <staffGrp symbol="bracket" barthru="true">
                                    <staffDef n="6" xml:id="P6" label="Horn in F 1" label.abbr="Hn. 1" lines="5" clef.line="2" clef.shape="G" key.sig="5s" key.mode="major" trans.semi="-7" trans.diat="-4"/>
                                    <staffDef n="7" xml:id="P7" label="Horn in F 2" label.abbr="Hn. 2" lines="5" clef.line="2" clef.shape="G" key.sig="5s" key.mode="major" trans.semi="-7" trans.diat="-4"
                                    />
                                </staffGrp>
                                <staffDef n="8" xml:id="P8" label="Solo Trumpet in C" label.abbr="S. C Tpt." lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                <staffDef n="9" xml:id="P9" label="Timpani" label.abbr="Timp." lines="5" clef.line="4" clef.shape="F" key.sig="4s" key.mode="major"/>
                                <staffGrp barthru="true" symbol="bracket">
                                    <staffDef n="10" xml:id="P10" label="Violin I" label.abbr="Vln. I" lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                    <staffDef n="11" xml:id="P11" label="Violin II" label.abbr="Vln. II" lines="5" clef.line="2" clef.shape="G" key.sig="4s" key.mode="major"/>
                                    <staffDef n="12" xml:id="P12" label="Viola" label.abbr="Vla." lines="5" clef.line="3" clef.shape="C" key.sig="4s" key.mode="major"/>
                                    <staffDef n="13" xml:id="P13" label="Cello" label.abbr="Vc." lines="5" clef.line="4" clef.shape="F" key.sig="4s" key.mode="major"/>
                                    <staffDef n="14" xml:id="P14" label="Contrabass" label.abbr="Cb." lines="5" clef.line="4" clef.shape="F" key.sig="4s" key.mode="major" trans.semi="-12" trans.diat="0"/>
                                </staffGrp>
                            </staffGrp>
                        </scoreDef>
                        <section>
                            <measure n="42" xml:id="d1e36977" width="176">
                                <staff n="1">
                                    <layer n="1">
                                        <note xml:id="d1e36986" pname="a" oct="5" dur="2" dots="1" fermata="above" stem.dir="down"/>
                                        <rest xml:id="d1e37005" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="2">
                                    <layer n="1">
                                        <note xml:id="d1e37021" pname="a" oct="5" dur="2" dots="1" fermata="above" stem.dir="down"/>
                                        <rest xml:id="d1e37040" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="3">
                                    <layer n="1">
                                        <note xml:id="d1e37056" pname="f" oct="5" dur="2" dots="1" fermata="above" stem.dir="down" accid.ges="s"/>
                                        <rest xml:id="d1e37077" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="4">
                                    <layer n="1">
                                        <note xml:id="d1e37093" pname="e" oct="5" dur="2" dots="1" fermata="above" stem.dir="down" accid.ges="s"/>
                                        <rest xml:id="d1e37114" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="5">
                                    <layer n="1">
                                        <note xml:id="d1e37130" pname="c" oct="5" dur="2" dots="1" fermata="above" stem.dir="down" accid.ges="s"/>
                                        <rest xml:id="d1e37151" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="6">
                                    <layer n="1">
                                        <mRest xml:id="d1e37167"/>
                                    </layer>
                                </staff>
                                <staff n="7">
                                    <layer n="1">
                                        <mRest xml:id="d1e37181"/>
                                    </layer>
                                </staff>
                                <staff n="8">
                                    <layer n="1">
                                        <mRest xml:id="d1e37195"/>
                                    </layer>
                                </staff>
                                <staff n="9">
                                    <layer n="1">
                                        <note xml:id="d1e37209" pname="b" oct="2" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <rest xml:id="d1e37228" dur="4"/>
                                    </layer>
                                </staff>
                                <staff n="10">
                                    <layer n="1">
                                        <note xml:id="d1e37244" pname="b" oct="3" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <note xml:id="d1e37261" grace="unacc" stem.mod="1slash" pname="f" oct="4" dur="8" stem.dir="up" accid.ges="s"/>
                                        <beam>
                                            <note xml:id="d1e37278" pname="e" oct="4" dur="8" dots="1" stem.dir="up"/>
                                            <note xml:id="d1e37295" pname="d" oct="4" dur="16" stem.dir="up" accid.ges="s"/>
                                        </beam>
                                    </layer>
                                </staff>
                                <staff n="11">
                                    <layer n="1">
                                        <note xml:id="d1e37325" pname="b" oct="3" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <note xml:id="d1e37342" grace="unacc" stem.mod="1slash" pname="f" oct="4" dur="8" stem.dir="up" accid.ges="s"/>
                                        <beam>
                                            <note xml:id="d1e37359" pname="e" oct="4" dur="8" dots="1" stem.dir="up"/>
                                            <note xml:id="d1e37376" pname="d" oct="4" dur="16" stem.dir="up" accid.ges="s"/>
                                        </beam>
                                    </layer>
                                </staff>
                                <staff n="12">
                                    <layer n="1">
                                        <note xml:id="d1e37407" pname="b" oct="3" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <beam>
                                            <note xml:id="d1e37424" pname="b" oct="3" dur="8" dots="1" stem.dir="up"/>
                                            <note xml:id="d1e37443" pname="c" accid="n" oct="4" dur="16" stem.dir="up"/>
                                        </beam>
                                    </layer>
                                </staff>
                                <staff n="13">
                                    <layer n="1">
                                        <note xml:id="d1e37473" pname="b" oct="2" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <beam>
                                            <note xml:id="d1e37490" pname="g" oct="3" dur="8" dots="1" stem.dir="down" accid.ges="s"/>
                                            <note xml:id="d1e37511" pname="a" oct="3" dur="16" stem.dir="down"/>
                                        </beam>
                                    </layer>
                                </staff>
                                <staff n="14">
                                    <layer n="1">
                                        <note xml:id="d1e37539" pname="b" oct="2" dur="2" dots="1" fermata="above" stem.dir="up"/>
                                        <rest xml:id="d1e37556" dur="4"/>
                                    </layer>
                                </staff>
                                <dynam tstamp="3" place="below" startto="48" staff="1">pp</dynam>
                                <fermata staff="1" startid="#d1e36986" form="norm" place="above"/>
                                <dynam tstamp="3" place="below" startto="48" staff="2">pp</dynam>
                                <fermata staff="2" startid="#d1e37021" form="norm" place="above"/>
                                <dynam tstamp="3" place="below" startto="48" staff="3">pp</dynam>
                                <fermata staff="3" startid="#d1e37056" form="norm" place="above"/>
                                <dynam tstamp="3" place="below" startto="48" staff="4">pp</dynam>
                                <fermata staff="4" startid="#d1e37093" form="norm" place="above"/>
                                <dynam tstamp="3" place="below" startto="48" staff="5">pp</dynam>
                                <fermata staff="5" startid="#d1e37130" form="norm" place="above"/>
                                <dynam tstamp="3" place="below" startto="48" staff="6">pp</dynam>
                                <dynam tstamp="3" place="below" startto="48" staff="7">pp</dynam>
                                <dynam tstamp="3" place="below" startto="48" staff="8">pp</dynam>
                                <dynam tstamp="3" place="below" startto="16" staff="9">pp</dynam>
                                <fermata staff="9" startid="#d1e37209" form="norm" place="above"/>
                                <trill tstamp="1" place="above" staff="9" startid="#d1e37209"/>
                                <dynam tstamp="3" place="below" startto="96" staff="10">pp</dynam>
                                <fermata staff="10" startid="#d1e37244" form="norm" place="above"/>
                                <slur curvedir="below" startid="#d1e37261" endid="#d1e37295"/>
                                <dynam tstamp="3" place="below" startto="96" staff="11">pp</dynam>
                                <fermata staff="11" startid="#d1e37325" form="norm" place="above"/>
                                <slur curvedir="below" startid="#d1e37342" endid="#d1e37376"/>
                                <dynam tstamp="3" place="below" startto="96" staff="12">pp</dynam>
                                <fermata staff="12" startid="#d1e37407" form="norm" place="above"/>
                                <slur curvedir="below" startid="#d1e37424" endid="#d1e37443"/>
                                <dynam tstamp="3" place="below" startto="96" staff="13">pp</dynam>
                                <fermata staff="13" startid="#d1e37473" form="norm" place="above"/>
                                <slur curvedir="above" startid="#d1e37490" endid="#d1e37511"/>
                                <dynam tstamp="3" place="below" startto="96" staff="14">pp</dynam>
                                <fermata staff="14" startid="#d1e37539" form="norm" place="above"/>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>
    

    Also, the dynamic markings in this measure are encoded a bit unusually. Ideally they would have a @tstamp="4" with a horizontal offset to the left. And I doubt that the parts with rests would show dynamics on the rests in an urtext edition (probably a system-level dynamic originally in Finale which then became multiple staff-level dynamics in the exported MusicXML).

    enhancement low priority 
    opened by craigsapp 34
  • n on scoreDef

    n on scoreDef

    In the develop branch the @n on scoreDef is no longer available. Is this done on purpose?

    opened by rettinghaus 34
  • Add support for num.place on multiRest

    Add support for num.place on multiRest

    This PR adds support for the rendering of numbers of multi-measure rests below the staff.

    rest-012

    <?xml version="1.0" encoding="UTF-8"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
       <meiHead>
          <fileDesc>
             <titleStmt>
                <title>Positioning of numbers on multi-measure rests</title>
             </titleStmt>
             <pubStmt>
                <respStmt>
                   <persName role="encoder">Klaus Rettinghaus</persName>
                   <corpName role="funder">Enote GmbH</corpName>
                </respStmt>
                <date isodate="2021-09-22">2021-09-22</date>
             </pubStmt>
          </fileDesc>
       </meiHead>
       <music>
          <body>
             <mdiv>
                <score>
                   <scoreDef meter.count="4" meter.unit="4" meter.sym="cut">
                      <staffGrp>
                         <staffDef n="1" lines="5" clef.shape="G" clef.line="2" />
                      </staffGrp>
                   </scoreDef>
                   <section>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="0" num="2" width="4" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="2" num="4" width="6" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="4" num="6" width="8" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="6" num="8" width="10" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="8" num="10" width="12" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <multiRest num.place="below" block="true" loc="10" num="12" width="14" />
                            </layer>
                         </staff>
                      </measure>
                   </section>
                </score>
             </mdiv>
          </body>
       </music>
    </mei>
    
    opened by rettinghaus 0
  • Wrong bounding boxes on Firefox since Release 82

    Wrong bounding boxes on Firefox since Release 82

    Describe the problem Interacting with the Verovio rendered SVG causes problems, since the bounding boxes (Element.getBoundingClientRect() and SVGGraficsElement.getBBox()) are sized up to the respective right and bottom bound of the current SVG. This problem only occurs with Firefox since Release 82 (Current Release: 93)

    To Reproduce Steps to reproduce the behavior:

    1. Load an arbitrary MEI with Verovio (e.g. the tutorial)
    2. Use a Firefox Release >= 83 && <= 93
    3. Check SVG Element in browser inspector (e.g. document.querySelector(".measure"), or document.querySelector(".layer)

    Expected behavior The example statements should only display the bounding box visually displayed for the element (measure, staff, etc.)

    Verovio information

    • 3.6.
    • Javascript

    Environment information (as appropriate)

    • MacOS 11.5.2, Windows10
    • Firefox (Release >= 83 && <= 93)

    Screenshots Displayed Bounding Box in Firefox 93 after executing document.querySelector(".staff") (first staff) in browser console staff bbox firefox 93

    Additional context This problem was already reported to mozilla 10 Months ago. It is not yet clear if it is a problem with Verovio or with Firefox

    opened by mnowakow 0
  • Do not ignore system scoreDef clefs

    Do not ignore system scoreDef clefs

    closes #1960

    Fix for the issue that BB of scoreDef clefs is being ignored which, with options like --adjust-page-height might lead to clef truncation: Before: image After fix: image

    However, given that BB is not ignored anymore leads placing first staff that has G-clef a bit lower (since upper part of the clef is now counted towards overlaps of the system): image After: image

    opened by Monceber 1
  • New slur adjustment algorithm

    New slur adjustment algorithm

    This PR implements a new slur adjustment algorithm that mainly adjusts the control points of the slur bezier curve.

    Slurs now more accurately curve around obstacles while preserving the position of the slur endpoints as much as possible.

    | Before | After | | ------ | ----- | | Before1 | After1 |

    Before Before2 After After2

    This particularly improves long slurs where endpoints before appeared lifted off.

    Before Before3 Before4

    After After3 After4

    The new algorithm consists of three steps:

    1. Vertical end point adjustment. This shifts the slur vertically. Only collisions near the endpoints are taken into account.
    2. Horizontal control point adjustment. The idea is to shift control points to the outside if there is an obstacle in the vicinity of the corresponding endpoint.
    3. Vertical control point adjustment. For each colliding bounding box we formulate a constraint ax + by >= c where x, y denote the vertical adjustments of the control points and c is the size of the collision. The coefficients a, b are calculated from the Bezier curve equation. After collecting all constraints we calculate a solution.
    AlgoSteps

    Moreover:

    • We fix an error in the calculation of t in BoundingBox::CalcBezierAtPosition. This error means that previously the slur was evaluated at the wrong horizontal position in order to calculate intersections with bounding boxes. To accurately calculate t one has to solve a cubic equation. For now we determine an approximate solution by interval bisection, this might be refined in a later PR.
    • We adjust cross staff slurs after vertical justification. This fixes part of #2309 .
    opened by DavidBauer1984 1
  • Using override instead of virtual

    Using override instead of virtual

    C++11 introduced the keyword override to specify that a virtual function overrides another virtual function defined in a base class. Using this instead of virtual for overriding functions has two advantages:

    • The compiler can check that we are indeed overriding some virtual function in a base class and throw an error if we accidentally define a new virtual function.
    • It tells the human who is reading the code immediately whether we define or override a virtual function.

    It is really impossible to break something by adding it. But if we use it, then it should be used consistently. Xcode throws warnings if it is used just here and there within a class.

    What do you think about introducing it into Verovio's codebase? (Technically I've sneaked it in already into the class OptionJson. I didn't know at this point that it is not used anywhere else 😬 )

    feature request 
    opened by DavidBauer1984 1
  • Improve grace slur rendering

    Improve grace slur rendering

    closes #2012

    1. Refactored DrawSlurInitial, moving parts of the code to separate functions to decrease its complexity.
    2. Adjusted code for the slurs that start on the grace notes to improve rendering - depending on the position of the grace note and direction of the slur, rendering now should be improved.

    Before: image

    After: image

    There is still an issue left that is not addressed here - slurs on grace notes when multiple layers present. Layer::GetDrawingStemDir()) does not work properly with grace notes, since they don't have correct alignment time and duration.

    opened by Monceber 3
  • Cancel layout

    Cancel layout

    This PR adds functionality to the toolkit to abort the layout in a thread-safe way. One use case is that a helper thread renders a score and meanwhile the user resizes the window. Then the current rendering must be aborted and restarted with new (page size) parameters.

    opened by DavidBauer1984 2
  • `--breaks encoded` not working without sb elements in Verovio 3.6

    `--breaks encoded` not working without sb elements in Verovio 3.6

    With the current release 3.6, the --breaks option seems to have changed its behavior.

    This dummy encoding containing three <pb> elements, but no <sb> elements appears incorrectly on one page, when called on the command line verovio --breaks encoded -a pagebreaks.mei. It should (and it has in previous versions) appear on three pages. (Similarly, --breaks line results in the same single-page output.)

    grafik
    pagebreaks.mei with three page break elements
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
       <meiHead>
          <fileDesc>
             <titleStmt>
                <title>Three page breaks</title>
                <respStmt />
             </titleStmt>
             <pubStmt />
          </fileDesc>
       </meiHead>
       <music>
          <body>
             <mdiv>
                <score>
                   <scoreDef key.sig="0" meter.count="3" meter.unit="4">
                      <staffGrp bar.thru="true" symbol="brace">
                         <staffDef n="1" lines="5" clef.shape="G" clef.line="2" />
                         <staffDef n="2" lines="5" clef.shape="F" clef.line="4" />
                      </staffGrp>
                   </scoreDef>
                   <section>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" />
                               <note dur="4" oct="4" pname="b" />
                               <note dur="4" oct="5" pname="c" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="5" pname="d" />
                               <note dur="4" oct="5" pname="c" />
                               <note dur="4" oct="4" pname="b" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" />
                               <note dur="4" oct="4" pname="g" />
                               <note dur="4" oct="4" pname="f" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="e" />
                               <note dur="4" oct="4" pname="d" />
                               <note dur="4" oct="4" pname="c" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="3" pname="b" />
                               <note dur="4" oct="4" pname="c" />
                               <note dur="4" oct="4" pname="d" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="e" />
                               <note dur="4" oct="4" pname="f" />
                               <note dur="4" oct="4" pname="g" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                   </section>
                </score>
             </mdiv>
          </body>
       </music>
    </mei>
    

    It works as expected on three pages when also <sb> elements are present in the encoding:

    grafikgrafikgrafik

    pagesystembreaks.mei with three page breaks and three system breaks
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
       <meiHead>
          <fileDesc>
             <titleStmt>
                <title>Three page and three system breaks</title>
                <respStmt />
             </titleStmt>
             <pubStmt />
          </fileDesc>
       </meiHead>
       <music>
          <body>
             <mdiv>
                <score>
                   <scoreDef key.sig="0" meter.count="3" meter.unit="4">
                      <staffGrp bar.thru="true" symbol="brace">
                         <staffDef n="1" lines="5" clef.shape="G" clef.line="2" />
                         <staffDef n="2" lines="5" clef.shape="F" clef.line="4" />
                      </staffGrp>
                   </scoreDef>
                   <section>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" />
                               <note dur="4" oct="4" pname="b" />
                               <note dur="4" oct="5" pname="c" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <sb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="5" pname="d" />
                               <note dur="4" oct="5" pname="c" />
                               <note dur="4" oct="4" pname="b" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" />
                               <note dur="4" oct="4" pname="g" />
                               <note dur="4" oct="4" pname="f" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <sb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="e" />
                               <note dur="4" oct="4" pname="d" />
                               <note dur="4" oct="4" pname="c" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <pb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="3" pname="b" />
                               <note dur="4" oct="4" pname="c" />
                               <note dur="4" oct="4" pname="d" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                      <sb />
                      <measure>
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="e" />
                               <note dur="4" oct="4" pname="f" />
                               <note dur="4" oct="4" pname="g" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                               <note dur="4" oct="3" pname="a" />
                            </layer>
                         </staff>
                      </measure>
                   </section>
                </score>
             </mdiv>
          </body>
       </music>
    </mei>
    

    I have not tracked down the commit where the behavior changed. Help highly appreciated.

    opened by wergo 3
  • Make resources non-static

    Make resources non-static

    Following the discussing in #2253 we should move all vrv-resources into a non-static container object which is owned by the toolkit or document. This would allow passing a toolkit instance between different threads without loosing resource path and loaded fonts.

    feature request 
    opened by DavidBauer1984 2
  • Editorial accidental refinements

    Editorial accidental refinements

    Related to issue https://github.com/rism-digital/verovio/issues/2322 which allowed small editorial accidentals to be enclosed in parentheses and brackets, there could be some enhancement in the visual placements of parentheses/brackets around small editorial accidentals. The current tight spacing makes it difficult to see the difference between editorial accidentals in an enclosure and not in an enclosure (particularly for parentheses).

    Screen Shot 2021-08-09 at 11 51 16 AM
    Click to view MEI data for above example.
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
     <meiHead>
      <fileDesc>
       <titleStmt>
        <title />
       </titleStmt>
       <pubStmt />
      </fileDesc>
      <encodingDesc>
       <appInfo>
        <application isodate="2021-08-09T11:52:56" version="3.6.0-dev-0abf482-dirty">
         <name>Verovio</name>
         <p>Transcoded from Humdrum</p>
        </application>
       </appInfo>
      </encodingDesc>
      <workList>
       <work>
        <title />
       </work>
      </workList>
     </meiHead>
     <music>
      <body>
       <mdiv xml:id="mdiv-0000000222374883">
        <score xml:id="score-0000002091737657">
         <scoreDef xml:id="scoredef-0000000210598957">
          <staffGrp xml:id="staffgrp-0000000978835965">
           <staffDef xml:id="staffdef-0000000169064387" n="1" lines="5">
            <clef xml:id="clef-0000002110967572" shape="G" line="2" />
            <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
           </staffDef>
          </staffGrp>
         </scoreDef>
         <section xml:id="section-L1F1">
          <measure xml:id="measure-L1" n="1">
           <staff xml:id="staff-0000001191213448" n="1">
            <layer xml:id="layer-L1F1N1" n="1">
             <note xml:id="note-L4F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L4F1" accid="s" func="edit" enclose="paren" />
             </note>
             <note xml:id="note-L5F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L5F1" accid="n" func="edit" enclose="paren" />
             </note>
             <note xml:id="note-L6F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L6F1" accid="f" func="edit" enclose="paren" />
             </note>
             <note xml:id="note-L7F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L7F1" accid="ff" func="edit" enclose="paren" />
             </note>
             <note xml:id="note-L8F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L8F1" accid="x" func="edit" enclose="paren" />
             </note>
            </layer>
           </staff>
          </measure>
          <measure xml:id="measure-L9">
           <staff xml:id="staff-L9F1N1" n="1">
            <layer xml:id="layer-L9F1N1" n="1">
             <note xml:id="note-L10F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L10F1" accid="s" func="edit" enclose="brack" />
             </note>
             <note xml:id="note-L11F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L11F1" accid="n" func="edit" enclose="brack" />
             </note>
             <note xml:id="note-L12F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L12F1" accid="f" func="edit" enclose="brack" />
             </note>
             <note xml:id="note-L13F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L13F1" accid="ff" func="edit" enclose="brack" />
             </note>
             <note xml:id="note-L14F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L14F1" accid="x" func="edit" enclose="brack" />
             </note>
            </layer>
           </staff>
          </measure>
          <measure xml:id="measure-L15">
           <staff xml:id="staff-L15F1N1" n="1">
            <layer xml:id="layer-L15F1N1" n="1">
             <note xml:id="note-L16F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L16F1" accid="s" enclose="paren" />
             </note>
             <note xml:id="note-L17F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L17F1" accid="n" enclose="paren" />
             </note>
             <note xml:id="note-L18F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L18F1" accid="f" enclose="paren" />
             </note>
             <note xml:id="note-L19F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L19F1" accid="ff" enclose="paren" />
             </note>
             <note xml:id="note-L20F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L20F1" accid="x" enclose="paren" />
             </note>
            </layer>
           </staff>
          </measure>
          <measure xml:id="measure-L21">
           <staff xml:id="staff-L21F1N1" n="1">
            <layer xml:id="layer-L21F1N1" n="1">
             <note xml:id="note-L22F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L22F1" accid="s" enclose="brack" />
             </note>
             <note xml:id="note-L23F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L23F1" accid="n" enclose="brack" />
             </note>
             <note xml:id="note-L24F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L24F1" accid="f" enclose="brack" />
             </note>
             <note xml:id="note-L25F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L25F1" accid="ff" enclose="brack" />
             </note>
             <note xml:id="note-L26F1" dur="4" oct="5" pname="c">
              <accid xml:id="accid-L26F1" accid="x" enclose="brack" />
             </note>
            </layer>
           </staff>
          </measure>
         </section>
        </score>
       </mdiv>
      </body>
     </music>
    </mei>
    

    Parentheses/brackets around regular-sized accidentals look fine (last two measures), but in many cases the parentheses/brackets are too close to the accidental when it is small and above the note. When the parentheses/brackets are on regular accidentals, the tight spacing is good because (1) the accidentals are larger, and (2) it is usually desirable to minimize the width of the accidentals to reduce stretching out the music.

    For smaller accidentals above the notes, keeping the enclosures compact is not as necessary, so it would be useful to add padding space between the enclosure and accidental:

    • The worst case are small naturals and flats above the notes enclosed in parentheses. It would good to add enough space so that the parentheses endpoints do not visually touch the accidentals. For flats, only the left side needs some padding, since the right side does not have problems with the parenthese endpoints. The double flat has the same property. The sharp is not too bad, but a tiny bit of space on both sides might be better. The double sharp looks good as it is.
    • When a bracket is used, there is less problem since there is a 90 degree angle at the junction between the parenthese endpoints and the accidental which it touches. But like with parentheses, a little more space between the enclosure and the accidental would increase readability.
    feature request low priority 
    opened by craigsapp 2
Releases(version-3.6.0)
Owner
RISM Digital Center
Répertoire International des Sources Musicales - Digital Center
RISM Digital Center
C++ library and Python bindings for the Music Encoding Initiative format

LibMEI LibMEI is a C++ library for reading and writing MEI files It is developed by the Distributed Digital Music Archives and Libraries Lab at the Sc

Distributed Digital Music Archives and Libraries Lab 49 Aug 30, 2021
OpenSheetMusicDisplay renders sheet music in MusicXML format in your web browser based on VexFlow. OSMD is brought to you by PhonicScore.com.

OpenSheetMusicDisplay (OSMD) A MusicXML renderer for the Browser opensheetmusicdisplay.org About OSMD • Demo • Key Features • Limitations • How to Use

Open Sheet Music Display 806 Sep 24, 2021
A language for music notation

Lydown is a language and compiler for creating music scores, parts and snippets. The lydown code is compiled to lilypond code and then compiled to PDF

Sharon Rosner 21 Apr 8, 2021
A beautiful cross platform Desktop Player for Google Play Music

Google Play Music™ Desktop Player Windows: MacOS / Linux: Run "Google Play Music" as a standalone desktop app. Never again will you have to hunt throu

Samuel Attard 8.5k Sep 12, 2021
A Music programming language. Translates source code into MIDI. Includes a player. Supports MIDI-Karaoke. Includes a MIDI analyzer.

Get Started | Features | Screenshots | Programming | CLI | Contribute | License Midica is an interpreter for a Music Programming Language. It translat

Jan Trukenmüller 47 Sep 17, 2021
Music typeset with the Lilypond system

Intro (from long ago) This repo contains sheet music typeset with the Lilypond typesetter. The music chosen is in favour of cello music (mostly chambe

Enthusiastic about  the Cello 95 Sep 24, 2021
网易云音乐第三方

ieaseMusic Elegant NeteaseMusic desktop app, Rock with NeteaseMusic ?? Built by Electron, React, MobX, JSS API 由 Binaryify/NeteaseCloudMusicApi 提供。 Pr

null 8.6k Sep 22, 2021
MuseScore is an open source and free music notation software. For support, contribution, bug reports, visit MuseScore.org. Fork and make pull requests!

Music notation and composition software MuseScore is an open source and free music notation software. For support, contribution, and bug reports visit

MuseScore 6.3k Sep 24, 2021
Frescobaldi LilyPond Editor

README for Frescobaldi Homepage: http://www.frescobaldi.org/ Main author: Wilbert Berendsen Frescobaldi is a LilyPond sheet music text editor. It aims

Frescobaldi 501 Sep 21, 2021
A music programming language for musicians. :notes:

Installation | Docs | Changelog | Contributing composers chatting Alda is a text-based programming language for music composition. It allows you to co

Alda 4.7k Sep 25, 2021
A JavaScript library for rendering music notation and guitar tablature.

VexFlow 3 A JavaScript library for rendering music notation. Copyright (c) 2010 Mohit Muthanna Cheppudira Sponsor this Project If you use VexFlow in y

Mohit Cheppudira 3.1k Sep 25, 2021
🎚️ Open Source Audio Matching and Mastering

Matching + Mastering = ❤️ Matchering 2.0 is a novel Containerized Web Application and Python Library for audio matching and mastering. It follows a si

Sergey Grishakov 490 Sep 24, 2021
Mopidy is an extensible music server written in Python

Mopidy Mopidy is an extensible music server written in Python. Mopidy plays music from local disk, Spotify, SoundCloud, Google Play Music, and more. Y

Mopidy 7.2k Sep 17, 2021
music library manager and MusicBrainz tagger

beets Beets is the media library management system for obsessive music geeks. The purpose of beets is to get your music collection right once and for

beetbox 10.4k Sep 15, 2021
Lilypond music preprocessor

Ripple - DRY for Lilypond Ripple is a small program that helps you generate scores and parts without repeating yourself, performing complex includes o

Sharon Rosner 21 Mar 24, 2020
Python CD-DA ripper preferring accuracy over speed

Whipper Whipper is a Python 3 (3.6+) CD-DA ripper based on the morituri project (CDDA ripper for *nix systems aiming for accuracy over speed). It star

null 554 Sep 19, 2021
LilyPond mini-score engraving and sharing service for musicians.

Tunefl LilyPond mini-score engraving and sharing service for musicians. The live Tunefl service is at tunefl.com. More sleep lost by tiredpixel. Insta

Nic Williams 22 Jun 22, 2020
Music player for deepin desktop environment.

deepin-music Deepin music is a local music player with beautiful design and simple functions developed by Deepin Technology. Dependencies Build depend

Wuhan Deepin Technology Co.,Ltd. 155 Sep 16, 2021
MusicXML parsing and layout library

mxml mxml is a C++ parser and layout generator for MusicXML files. Usage You will need: CMake >= 2.6 LibXML2 boost (for unit tests) To build a stand-a

Reinvent Inc. 19 Mar 29, 2021