🎵 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 http://www.verovio.org. Verovio is available under the LGPL license (see COPYING and COPYING.LESSER).

Building and use instructions by environment

See the wiki, with instructions for:

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

Contributing

If you are interested in contributing to Verovio, please read the contribution and coding style guidelines.

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
Comments
  • 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
  • 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
  • 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
  • Duplicate IDs in SVG file

    Duplicate IDs in SVG file

    Verovio generates duplicate IDs in the SVG output for MEI files, for ex.: <g class="barLineAttr" id="bline-000000000000767">

    The W3C Validator fails on most of my SVG files.

    Example MEI file

    enhancement 
    opened by sonovice 33
  • Not able to compile python version under Windows

    Not able to compile python version under Windows

    I am not able to compile the python version under Windows. The error is pretty short: ../src/iopae.cpp:36:19: fatal error: regex.h: No such file or directory

    The regular regex libs are usually heavily POSIX related and thus not available for Windows. Is there any way to make verovio compilable under Windows?

    I am using MinGW32.

    opened by sonovice 33
  • Functor classes - getting started

    Functor classes - getting started

    This PR implements the basic framework for functor classes (see #3005 ) and moves the first functors, namely most of the search functors and CalcDots as well as CalcLedgerLines.

    • We have const functors (class ConstFunctor) and mutable functors (class MutableFunctor). The latter are allowed to make changes on elements that they visit. Both are derived from FunctorBase which stores basic properties such as traversal direction, the current functor code or filters. They are derived from different interfaces (ConstFunctorInterface and FunctorInterface) which contain the virtual methods for element visitation. For convenience, we have the classes DocFunctor and DocConstFunctor which additionally store a Doc pointer.
    • For now we implement visitation for Object, Doc, all layer elements and all container elements. This will be further extended in the future.
    • The search functors demonstrate the implementation and usage of simple functor classes.
    • CalcDots demonstrates the implementation of an advanced functor with private helper function.
    • CalcLedgerLines demonstrates the implementation of an advanced functor that also uses the end interface (formerly end functor). The call of functors now becomes quite neat:
    CalcLedgerLines calcLedgerLines(doc);
    this->Process(calcLedgerLines);
    
    • Changing the code structure already becomes apparent in note.cpp which is reduced by ~100 LOC.

    This PR should not trigger any changes in performance or rendering.

    opened by DavidBauer1984 1
  • Verovio MEI Viewer MIDI playback ignores @midi.volume attribute

    Verovio MEI Viewer MIDI playback ignores @midi.volume attribute

    Describe the problem The MIDI playback in the Verovio Viewer seems to completely ignore the @midi.volume attribute on the instrDef element.

    To Reproduce I've edited the Jesu, meines Herzens Freud .mei file to have a <instrDef midi.volume="0%"/> element inside of it's <staffGrp>.

    Expected behavior Playing the modified MEI file should have 0 volume midi playback. Instead it plays at full volume like normal.

    Input data Jesu, meines Herzens Freud .mei file

    feature request 
    opened by RGamberini 0
  • Proposal for Functor Classes

    Proposal for Functor Classes

    Motivation

    Verovio currently implements functors as virtual methods of the Object class and stores the functor state in struct-like parameter objects (consisting only of public data members plus constructor for initialization). This approach has the following drawbacks:

    1. The functor implementation is spread over several element classes. In order to understand what a certain functor does, one must search and inspect the code in several classes. Reversely, element classes are not self-contained and are crowded with functor code. An extreme example is the Measure class which consists of 1700 LOC with 1000 LOC functor implementation.

    2. There exists no mechanism for functors to share common functionality. For example, it would make sense to split the current transpose functor into three functors Transpose, TransposeMdiv and TransposeToSoundingPitch which share the core transposition functionality on KeySig, Note and Rest. Similarly, it would make sense to split the MEI export into several functors for page based, score based, filtered score based and MEI basic.

    3. The functor state is currently not properly encapsulated. Usually parameters serve as input, output or intermediate values. However, there is no restriction for setting and getting parameter values.

    4. The functor state must be passed as argument into the functor implementation and casted afterwards. Even though this does not have a negative impact on runtime (the casts are static), it adds a certain amount of boilerplate code.

    5. There is no natural place to implement functor specific helper functions. This either leads to very long functor implementations (i.e. LayerElement::CalcAlignmentPitchPos with 260 LOC) or helper methods within an element class which are very functor specific (i.e. Note::GenerateGraceNoteMIDI).

    Proposal

    These drawbacks could be overcome by implementing functors as classes and using a Visitor Pattern to call them. The basic idea is to merge the functor implementation and state into one class for each functor. There would be an interface class defining virtual methods for each element (i.e. VisitorInterface::VisitMeasure(Measure *measure), VisitorInterface::VisitNote(Note *note), VisitorInterface::VisitRest(Rest *rest), … ) from which all functors are derived. To transform a functor into a class, the following steps must be done:

    1. Create a new class for the functor (say CastOffPagesFunctor)
    2. Use the content of the param object (CastOffPagesParams) to define the member variables (m_contentPage, m_doc, m_currentPage, …)
    3. Move the code of the functor implementation into the corresponding overridden interface methods (i.e. System::CastOffPages into CastOffPagesFunctor::VisitPage, Score::CastOffPages into CastOffPagesFunctor::VisitScore, etc.)
    4. Clean up by removing the previous param object and functor implementation.

    The visitor pattern consists of a virtual method Object::Call(Functor *functor) which is implemented by calling the corresponding visitor method in the object interface. For example, in the Measure class the call would be implemented as:

    Measure::Call(Functor *functor) override {
    	functor->VisitMeasure(this);
    }
    

    This is called a dispatch method. Effectively, we create a second class hierarchy (one for elements and one for functors) and use the dispatch method to call virtual methods in one hierarchy from the other.

    In my view, the biggest advantage of functor classes is that we would restructure the code in Verovio and create smaller classes which are more self-contained. Minor advantages include:

    • We could merge functors and corresponding end functors into one class.
    • Redirection of functors (i.e. to traverse the ScoreDef) would be simplified since functor classes naturally know the functor (via the this pointer) An interesting application would be parallelisation of the layout.

    A glimpse towards parallelisation

    Parallelising the layout is not straightforward, since most of the layout functors must be run in a fixed order. However, we have a lot of functors which could be evaluated in parallel on measures or systems. Examples are the search functors and all functors that only perform local changes like CalcDotsor AdjustSlurs. That is, the calculation of dots can be done in parallel for measure 1, 2, 3, … and the slur adjustment can be done in parallel for system 1, 2, 3, … . To do this, the current functor object must be copied for each measure/system and passed into helper tasks (threads) which evaluate the functor. After all tasks have finished, the results must be combined (i.e. for search). The details are not important here, but the point is that the best place to implement this would be a base class Functor from which all functors derive. Something that only makes sense after switching to functor classes.

    Discussion

    Switching to functor classes is a huge refactoring project that would take many months to complete. However, it could be done step by step turning functor by functor into classes. The question is whether this would be fine for everybody, since it would mean that for quite some time we would have to deal with a mixture of functors partially as classes and partially as virtual methods.

    feature request 
    opened by DavidBauer1984 2
  • 3.11: When condense

    3.11: When condense "auto", last system not rendered when pause(s) only

    The problem arises when

    • condense option is set to auto (default)
    • the last bar(s) are pause(s) only
    • the last system contains one or more of those pause-only bars

    If the last system should happen to require an additional extra page, that page is not created.

    condense: "none"

    condensing-none

    condense: "auto"

    As seen in the screenshot below, there is a "system break" symbol added, but the system itself is not.

    condensing-auto

    The problem can be reproduced using 3.10 and 3.11 - both using js toolkit and native - using the following musicXml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
    <score-partwise version="3.1">
      <work>
        <work-title>satb</work-title>
      </work>
      <identification>
        <encoding>
          <software>MuseScore 3.5.0</software>
          <encoding-date>2022-07-05</encoding-date>
          <supports element="accidental" type="yes"/>
          <supports element="beam" type="yes"/>
          <supports element="print" attribute="new-page" type="yes" value="yes"/>
          <supports element="print" attribute="new-system" type="yes" value="yes"/>
          <supports element="stem" type="yes"/>
        </encoding>
      </identification>
      <defaults>
        <scaling>
          <millimeters>7.05556</millimeters>
          <tenths>40</tenths>
        </scaling>
        <page-layout>
          <page-height>1683.36</page-height>
          <page-width>1190.88</page-width>
          <page-margins type="even">
            <left-margin>56.6929</left-margin>
            <right-margin>56.6929</right-margin>
            <top-margin>56.6929</top-margin>
            <bottom-margin>113.386</bottom-margin>
          </page-margins>
          <page-margins type="odd">
            <left-margin>56.6929</left-margin>
            <right-margin>56.6929</right-margin>
            <top-margin>56.6929</top-margin>
            <bottom-margin>113.386</bottom-margin>
          </page-margins>
        </page-layout>
        <word-font font-family="FreeSerif" font-size="10"/>
        <lyric-font font-family="FreeSerif" font-size="11"/>
      </defaults>
      <credit page="1">
        <credit-words default-x="595.44" default-y="1626.67" justify="center" valign="top" font-size="24">satb</credit-words>
      </credit>
      <part-list>
        <part-group type="start" number="1">
          <group-symbol>bracket</group-symbol>
        </part-group>
        <part-group type="start" number="2">
          <group-symbol>bracket</group-symbol>
        </part-group>
        <score-part id="P1">
          <part-name>Soprano</part-name>
          <part-abbreviation>S.</part-abbreviation>
          <score-instrument id="P1-I1">
            <instrument-name>Soprano</instrument-name>
          </score-instrument>
          <midi-device id="P1-I1" port="1"></midi-device>
          <midi-instrument id="P1-I1">
            <midi-channel>1</midi-channel>
            <midi-program>53</midi-program>
            <volume>78.7402</volume>
            <pan>0</pan>
          </midi-instrument>
        </score-part>
        <score-part id="P2">
          <part-name>Alto</part-name>
          <part-abbreviation>A.</part-abbreviation>
          <score-instrument id="P2-I1">
            <instrument-name>Alto</instrument-name>
          </score-instrument>
          <midi-device id="P2-I1" port="1"></midi-device>
          <midi-instrument id="P2-I1">
            <midi-channel>2</midi-channel>
            <midi-program>53</midi-program>
            <volume>78.7402</volume>
            <pan>0</pan>
          </midi-instrument>
        </score-part>
        <score-part id="P3">
          <part-name>Tenor</part-name>
          <part-abbreviation>T.</part-abbreviation>
          <score-instrument id="P3-I1">
            <instrument-name>Tenor</instrument-name>
          </score-instrument>
          <midi-device id="P3-I1" port="1"></midi-device>
          <midi-instrument id="P3-I1">
            <midi-channel>3</midi-channel>
            <midi-program>53</midi-program>
            <volume>78.7402</volume>
            <pan>0</pan>
          </midi-instrument>
        </score-part>
        <score-part id="P4">
          <part-name>Bass</part-name>
          <part-abbreviation>B.</part-abbreviation>
          <score-instrument id="P4-I1">
            <instrument-name>Bass</instrument-name>
          </score-instrument>
          <midi-device id="P4-I1" port="1"></midi-device>
          <midi-instrument id="P4-I1">
            <midi-channel>4</midi-channel>
            <midi-program>53</midi-program>
            <volume>78.7402</volume>
            <pan>0</pan>
          </midi-instrument>
        </score-part>
        <part-group type="stop" number="2"/>
        <part-group type="stop" number="1"/>
      </part-list>
      <part id="P1">
        <measure number="1" width="158.94">
          <print>
            <system-layout>
              <system-margins>
                <left-margin>93.80</left-margin>
                <right-margin>-0.00</right-margin>
              </system-margins>
              <top-system-distance>170.00</top-system-distance>
            </system-layout>
          </print>
          <attributes>
            <divisions>1</divisions>
            <key>
              <fifths>0</fifths>
            </key>
            <time>
              <beats>4</beats>
              <beat-type>4</beat-type>
            </time>
            <clef>
              <sign>G</sign>
              <line>2</line>
            </clef>
          </attributes>
          <note default-x="82.47" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="2" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="3" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="4" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="5" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="6" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="7" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="8" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="9" width="91.75">
          <note default-x="10.00" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
            </pitch>
            <duration>4</duration>
            <voice>1</voice>
            <type>whole</type>
          </note>
        </measure>
        <measure number="10" width="90.79">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
          <barline location="right">
            <bar-style>light-heavy</bar-style>
          </barline>
        </measure>
      </part>
      <part id="P2">
        <measure number="1" width="158.94">
          <print>
            <staff-layout number="1">
              <staff-distance>65.00</staff-distance>
            </staff-layout>
          </print>
          <attributes>
            <divisions>1</divisions>
            <key>
              <fifths>0</fifths>
            </key>
            <time>
              <beats>4</beats>
              <beat-type>4</beat-type>
            </time>
            <clef>
              <sign>G</sign>
              <line>2</line>
            </clef>
          </attributes>
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="2" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="3" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="4" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="5" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="6" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="7" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="8" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="9" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="10" width="90.79">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
          <barline location="right">
            <bar-style>light-heavy</bar-style>
          </barline>
        </measure>
      </part>
      <part id="P3">
        <measure number="1" width="158.94">
          <print>
            <staff-layout number="1">
              <staff-distance>65.00</staff-distance>
            </staff-layout>
          </print>
          <attributes>
            <divisions>1</divisions>
            <key>
              <fifths>0</fifths>
            </key>
            <time>
              <beats>4</beats>
              <beat-type>4</beat-type>
            </time>
            <clef>
              <sign>G</sign>
              <line>2</line>
              <clef-octave-change>-1</clef-octave-change>
            </clef>
          </attributes>
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="2" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="3" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="4" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="5" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="6" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="7" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="8" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="9" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="10" width="90.79">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
          <barline location="right">
            <bar-style>light-heavy</bar-style>
          </barline>
        </measure>
      </part>
      <part id="P4">
        <measure number="1" width="158.94">
          <print>
            <staff-layout number="1">
              <staff-distance>65.00</staff-distance>
            </staff-layout>
          </print>
          <attributes>
            <divisions>1</divisions>
            <key>
              <fifths>0</fifths>
            </key>
            <time>
              <beats>4</beats>
              <beat-type>4</beat-type>
            </time>
            <clef>
              <sign>F</sign>
              <line>4</line>
            </clef>
          </attributes>
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="2" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="3" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="4" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="5" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="6" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="7" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="8" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="9" width="91.75">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
        </measure>
        <measure number="10" width="90.79">
          <note>
            <rest measure="yes"/>
            <duration>4</duration>
            <voice>1</voice>
          </note>
          <barline location="right">
            <bar-style>light-heavy</bar-style>
          </barline>
        </measure>
      </part>
    </score-partwise>
    
    
    
    opened by cambiata 3
  • key change with transposing instruments

    key change with transposing instruments

    A key change with transposing instruments does not result in the correct accidentals.

    Key change

    As seen here both the clarinet and the horn have the correct accidentals in the beggining but the key change does not consider the transposition of the instruments. Accidentals should be 1f for the horn and 5f for the clarinet. This did work before, I hope I'm not missung something obvious.

    Test MEI
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0.0-dev">
       <meiHead>
          <fileDesc>
             <titleStmt>
                <title>TestMEI KeyChange</title>
                <respStmt />
             </titleStmt>
             <pubStmt>
                <date isodate="2022-06-24" type="encoding-date">2022-06-24</date>
             </pubStmt>
          </fileDesc>
          <encodingDesc xml:id="encodingdesc-npqx0g">
             <appInfo xml:id="appinfo-6vugxl">
                <application xml:id="application-mnrexv" isodate="2022-06-24T10:09:29" version="3.11.0-dev-5334175">
                   <name xml:id="name-jdab7g">Verovio</name>
                   <p xml:id="p-retco9">Transcoded from MusicXML</p>
                </application>
             </appInfo>
          </encodingDesc>
       </meiHead>
       <music>
          <body>
             <mdiv>
                <score>
                   <scoreDef>
                      <staffGrp>
                         <staffDef n="1" lines="5" ppq="1" trans.diat="-2.000000" trans.semi="-3.000000">
                            <label>Clarinet in A</label>
                            <labelAbbr>Cl. in A</labelAbbr>
                            <clef shape="G" line="2" />
                            <keySig sig="1f" />
                            <meterSig count="4" unit="4" />
                         </staffDef>
                         <staffDef n="2" lines="5" ppq="1" trans.diat="-4.000000" trans.semi="-7.000000">
                            <label>Horn in F</label>
                            <labelAbbr>Hrn. in F</labelAbbr>
                            <clef shape="G" line="2" />
                            <keySig sig="3s" />
                            <meterSig count="4" unit="4" />
                         </staffDef>
                         <staffGrp>
                            <grpSym symbol="bracket" />
                            <staffDef n="3" lines="5" ppq="1">
                               <label>Violin</label>
                               <labelAbbr>Vln.</labelAbbr>
                               <clef shape="G" line="2" />
                               <keySig sig="2s" />
                               <meterSig count="4" unit="4" />
                            </staffDef>
                            <staffDef n="4" lines="5" ppq="1">
                               <label>Violoncello</label>
                               <labelAbbr>Vc.</labelAbbr>
                               <clef shape="F" line="4" />
                               <keySig sig="2s" />
                               <meterSig count="4" unit="4" />
                            </staffDef>
                         </staffGrp>
                      </staffGrp>
                   </scoreDef>
                   <section>
                      <measure n="1">
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="f" stem.dir="up" />
                               <note dur="4" oct="4" pname="g" stem.dir="up" />
                               <note dur="4" oct="4" pname="a" stem.dir="up" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" accid.ges="f" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" stem.dir="up" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" />
                               <note dur="4" oct="5" pname="c" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="5" pname="d" stem.dir="down" />
                            </layer>
                         </staff>
                         <staff n="3">
                            <layer n="1">
                               <note dur="4" oct="4" pname="d" stem.dir="up" />
                               <note dur="4" oct="4" pname="e" stem.dir="up" />
                               <note dur="4" oct="4" pname="f" stem.dir="up" accid.ges="s" />
                               <note dur="4" oct="4" pname="g" stem.dir="up" />
                            </layer>
                         </staff>
                         <staff n="4">
                            <layer n="1">
                               <note dur="4" oct="3" pname="d" stem.dir="down" />
                               <note dur="4" oct="3" pname="e" stem.dir="down" />
                               <note dur="4" oct="3" pname="f" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="3" pname="g" stem.dir="down" />
                            </layer>
                         </staff>
                      </measure>
                      <measure n="2">
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="5" pname="c" stem.dir="down" />
                               <note dur="4" oct="5" pname="d" stem.dir="down" />
                               <note dur="4" oct="5" pname="e" stem.dir="down" />
                               <note dur="4" oct="5" pname="f" stem.dir="down" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="5" pname="e" stem.dir="down" />
                               <note dur="4" oct="5" pname="f" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="5" pname="g" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="5" pname="a" stem.dir="down" />
                            </layer>
                         </staff>
                         <staff n="3">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" stem.dir="up" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" />
                               <note dur="4" oct="5" pname="c" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="5" pname="d" stem.dir="down" />
                            </layer>
                         </staff>
                         <staff n="4">
                            <layer n="1">
                               <note dur="4" oct="3" pname="a" stem.dir="down" />
                               <note dur="4" oct="3" pname="b" stem.dir="down" />
                               <note dur="4" oct="4" pname="c" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="4" pname="d" stem.dir="down" />
                            </layer>
                         </staff>
                      </measure>
                      <scoreDef>
                         <keySig sig="2f" />
                      </scoreDef>
                      <measure n="3">
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="5" pname="e" stem.dir="down" accid.ges="f" />
                               <note dur="4" oct="5" pname="d" stem.dir="down" />
                               <note dur="4" oct="5" pname="c" stem.dir="down" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" accid.ges="f" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="5" pname="g" stem.dir="down" />
                               <note dur="4" oct="5" pname="f" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="5" pname="e" stem.dir="down" />
                               <note dur="4" oct="5" pname="d" stem.dir="down" />
                            </layer>
                         </staff>
                         <staff n="3">
                            <layer n="1">
                               <note dur="4" oct="5" pname="c" stem.dir="down" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" />
                               <note dur="4" oct="4" pname="a" stem.dir="up" />
                               <note dur="4" oct="4" pname="g" stem.dir="up" />
                            </layer>
                         </staff>
                         <staff n="4">
                            <layer n="1">
                               <note dur="4" oct="4" pname="c" stem.dir="down" />
                               <note dur="4" oct="3" pname="b" stem.dir="down" />
                               <note dur="4" oct="3" pname="a" stem.dir="down" />
                               <note dur="4" oct="3" pname="g" stem.dir="down" />
                            </layer>
                         </staff>
                      </measure>
                      <measure right="end" n="4">
                         <staff n="1">
                            <layer n="1">
                               <note dur="4" oct="4" pname="a" stem.dir="up" />
                               <note dur="4" oct="4" pname="g" stem.dir="up" />
                               <note dur="2" oct="4" pname="f" stem.dir="up" />
                            </layer>
                         </staff>
                         <staff n="2">
                            <layer n="1">
                               <note dur="4" oct="5" pname="c" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="4" pname="b" stem.dir="down" />
                               <note dur="2" oct="4" pname="a" stem.dir="up" />
                            </layer>
                         </staff>
                         <staff n="3">
                            <layer n="1">
                               <note dur="4" oct="4" pname="f" stem.dir="up" accid.ges="s" />
                               <note dur="4" oct="4" pname="e" stem.dir="up" />
                               <note dur="2" oct="4" pname="d" stem.dir="up" />
                            </layer>
                         </staff>
                         <staff n="4">
                            <layer n="1">
                               <note dur="4" oct="3" pname="f" stem.dir="down" accid.ges="s" />
                               <note dur="4" oct="3" pname="e" stem.dir="down" />
                               <note dur="2" oct="3" pname="d" stem.dir="down" />
                            </layer>
                         </staff>
                      </measure>
                   </section>
                </score>
             </mdiv>
          </body>
       </music>
    </mei>
    
    
    waiting for MEI clarification 
    opened by mapscl 2
  • Extend tags are not ended by rests in MusicXML-to-MEI converter

    Extend tags are not ended by rests in MusicXML-to-MEI converter

    Describe the problem Extend tags in musicxml continue through rests if no lyrics follow

    To Reproduce Load the attached musicxml data at https://www.verovio.org/musicxml.html

    Expected behavior The second extend should end before the rest like it does when rendered in MuseScore

    Input data

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
    <score-partwise version="3.1">
      <identification>
        <encoding>
          <software>MuseScore 3.6.2</software>
          <encoding-date>2022-06-09</encoding-date>
          <supports element="accidental" type="yes"/>
          <supports element="beam" type="yes"/>
          <supports element="print" attribute="new-page" type="yes" value="yes"/>
          <supports element="print" attribute="new-system" type="yes" value="yes"/>
          <supports element="stem" type="yes"/>
          </encoding>
        </identification>
      <defaults>
        <scaling>
          <millimeters>5.84388</millimeters>
          <tenths>40</tenths>
          </scaling>
        <page-layout>
          <page-height>1913</page-height>
          <page-width>1217</page-width>
          <page-margins type="both">
            <left-margin>68</left-margin>
            <right-margin>68</right-margin>
            <top-margin>68</top-margin>
            <bottom-margin>68</bottom-margin>
            </page-margins>
          </page-layout>
        <word-font font-family="Edwin" font-size="9.9619"/>
        <lyric-font font-family="Edwin" font-size="9.5738"/>
        </defaults>
      <part-list>
        <score-part id="P1">
          <part-name> </part-name>
          <part-abbreviation> </part-abbreviation>
          <score-instrument id="P1-I1">
            <instrument-name> </instrument-name>
            </score-instrument>
          <midi-device id="P1-I1" port="1"></midi-device>
          <midi-instrument id="P1-I1">
            <midi-channel>1</midi-channel>
            <midi-program>1</midi-program>
            <volume>78.7402</volume>
            <pan>0</pan>
            </midi-instrument>
          </score-part>
        </part-list>
      <part id="P1">
        <measure number="1" width="410.15">
          <print>
            <system-layout>
              <system-margins>
                <left-margin>50.00</left-margin>
                <right-margin>620.85</right-margin>
                </system-margins>
              <top-system-distance>70.00</top-system-distance>
              </system-layout>
            </print>
          <attributes>
            <divisions>1</divisions>
            <key>
              <fifths>0</fifths>
              </key>
            <time>
              <beats>4</beats>
              <beat-type>4</beat-type>
              </time>
            <clef>
              <sign>G</sign>
              <line>2</line>
              </clef>
            </attributes>
          <note default-x="80.72" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
              </pitch>
            <duration>1</duration>
            <voice>1</voice>
            <type>quarter</type>
            <stem>up</stem>
            <lyric number="1" default-y="-40.00" relative-y="-30.00">
              <syllabic>single</syllabic>
              <text>A</text>
              <extend/>
              </lyric>
            <lyric number="2" default-y="-60.22" relative-y="-30.00">
              <syllabic>single</syllabic>
              <text>A</text>
              <extend/>
              </lyric>
            </note>
          <note default-x="160.42" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
              </pitch>
            <duration>1</duration>
            <voice>1</voice>
            <type>quarter</type>
            <stem>up</stem>
            </note>
          <note>
            <rest/>
            <duration>1</duration>
            <voice>1</voice>
            <type>quarter</type>
            </note>
          <note default-x="319.81" default-y="-30.00">
            <pitch>
              <step>G</step>
              <octave>4</octave>
              </pitch>
            <duration>1</duration>
            <voice>1</voice>
            <type>quarter</type>
            <stem>up</stem>
            <lyric number="1" default-x="6.50" default-y="-40.00" relative-y="-30.00">
              <syllabic>single</syllabic>
              <text>B</text>
              </lyric>
            </note>
          <barline location="right">
            <bar-style>light-heavy</bar-style>
            </barline>
          </measure>
        </part>
      </score-partwise>
    

    Current output data

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
    <?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
    <mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0.0-dev">
       <meiHead>
          <fileDesc>
             <titleStmt>
                <title />
                <respStmt />
             </titleStmt>
             <pubStmt><availability>
                   <distributor>words and music: Jonathan Gabhart and Jake Helder; © Pillar Music, 2019
    </distributor>
                </availability>
                <date isodate="2022-06-09" type="encoding-date">2022-06-09</date>
             </pubStmt>
          </fileDesc>
          <encodingDesc xml:id="encodingdesc-s55pm0">
             <appInfo xml:id="appinfo-62ttk6">
                <application xml:id="application-jym9tf" isodate="2022-06-09T11:34:44" version="3.11.0-dev-00d26d1">
                   <name xml:id="name-re40op">Verovio</name>
                   <p xml:id="p-lnzck6">Transcoded from MusicXML</p>
                </application>
             </appInfo>
          </encodingDesc>
       </meiHead>
       <music>
          <body>
             <mdiv xml:id="mc11zj8">
                <score xml:id="sfknuwj">
                   <scoreDef xml:id="sjfxd6p">
                      <pgFoot xml:id="pgcpuu0">
                         <rend xml:id="rvmsny0" halign="center" valign="bottom">words and music: Jonathan Gabhart and Jake Helder; © Pillar Music, 2019
    </rend>
                      </pgFoot>
                      <staffGrp xml:id="su6hg45">
                         <staffDef xml:id="P1" n="1" lines="5" ppq="1">
                            <instrDef xml:id="iokbvme" midi.channel="0" midi.instrnum="0" midi.volume="78.00%" />
                            <clef xml:id="caoghh1" shape="G" line="2" />
                            <keySig xml:id="knwh41o" sig="0" />
                            <meterSig xml:id="mprhiag" count="4" unit="4" />
                         </staffDef>
                      </staffGrp>
                   </scoreDef>
                   <section xml:id="syqnpnf">
                      <measure xml:id="mmt98so" right="end" n="1">
                         <staff xml:id="swl38tg" n="1">
                            <layer xml:id="luunzwz" n="1">
                               <note xml:id="n7fg8v5" dur.ppq="1" dur="4" oct="4" pname="g" stem.dir="up">
                                  <verse xml:id="vvwzez1" n="1">
                                     <syl xml:id="sbsc2vz" con="u" wordpos="s">A</syl>
                                  </verse>
                                  <verse xml:id="vyn2tbt" n="2">
                                     <syl xml:id="sy909vf" con="u" wordpos="s">A</syl>
                                  </verse>
                               </note>
                               <note xml:id="nrb581l" dur.ppq="1" dur="4" oct="4" pname="g" stem.dir="up" />
                               <rest xml:id="rph2c8n" dur.ppq="1" dur="4" />
                               <note xml:id="nso4ne4" dur.ppq="1" dur="4" oct="4" pname="g" stem.dir="up">
                                  <verse xml:id="vhnb10w" n="1">
                                     <syl xml:id="s4peli8" con="s" wordpos="s">B</syl>
                                  </verse>
                               </note>
                            </layer>
                         </staff>
                      </measure>
                   </section>
                </score>
             </mdiv>
          </body>
       </music>
    </mei>
    

    Screenshots When rendered in MuseScore, it looks like:

    musescore

    When rendered in the MusicXML-to-MEI converter, it looks like:

    verovio

    enhancement low priority musicxml 
    opened by bryantgeorge 0
Releases(version-3.11.0)
Owner
RISM Switzerland
Répertoire International des Sources Musicales - Swiss branch
RISM Switzerland
A tiny, header only, easy to use, cross-platform, portaudio wrapper, sound and notation manager, tailored for the demo scene.

TDAW A tiny, header only, easy to use, cross-platform, portaudio wrapper, sound and notation manager, tailored for the demo scene. This header enables

kbx 12 Sep 17, 2022
Xan's NFS Music Player - Custom music player replacement and a BASS library interface for NFS.

Xan's NFS Music Player This is a custom music player replacement and a BASS library interface for NFS. FEATURES Custom playlist generation - put any n

Lovro Pleše 11 Aug 27, 2022
Strawberry is a music player and music collection organizer.

Strawberry is a music player and music collection organizer. It is a fork of Clementine released in 2018 aimed at music collectors and audiophiles. It's written in C++ using the Qt toolkit.

Strawberry Music Player 1.7k Oct 1, 2022
Arduino Audio Tools (Music Player, Music Recorder supporting I2S, Microphones, DAC, ADC, A2DP, Url)

Arduino Audio Tools Some basic header-only C++ classes that can be used for Audio Processing provided as Arduino Library: a simple I2S class (to read

Phil Schatzmann 421 Oct 3, 2022
C++ library for audio and music analysis, description and synthesis, including Python bindings

Essentia Essentia is an open-source C++ library for audio analysis and audio-based music information retrieval released under the Affero GPL license.

Music Technology Group - Universitat Pompeu Fabra 2.2k Sep 29, 2022
C++ Audio and Music DSP Library

_____ _____ ___ __ _ _____ __ __ __ ____ ____ / \\_ \\ \/ / |/ \| | | | \_ \/ \ | Y Y \/ /_ \> <| | Y Y \ | |_|

Mick Grierson 1.3k Oct 6, 2022
a library for audio and music analysis

aubio is a library to label music and sounds. It listens to audio signals and attempts to detect events. For instance, when a drum is hit, at which frequency is a note, or at what tempo is a rhythmic melody.

aubio 2.8k Oct 1, 2022
A lightweight music DSP library.

Soundpipe Soundpipe is a lightweight music DSP library written in C. It aims to provide a set of high-quality DSP modules for composers, sound designe

Paul Batchelor 102 Dec 14, 2021
C/C++ library for converting a stream of OPL FM synth chip commands to the OPB music format

OPBinaryLib C/C++ library for converting a stream of OPL FM synth chip commands to the OPB music format Basic usage Store your OPL commands as a conti

Emma Maassen 10 Feb 2, 2022
PendulumSynth is an on-going and open-source project, running on Arduino platform with the goal of mixing real-world physics into music composition and musical performance.

PendulumSynth PendulumSynth is an on-going and open-source project, running on Arduino platform with the goal of mixing real-world physics into music

Mohammadreza Anvari 4 Jun 19, 2022
projectM - cross-platform music visualization. Open-source and Milkdrop-compatible

projectM - cross-platform music visualization. Open-source and Milkdrop-compatible

projectM Visualizer 2.4k Sep 27, 2022
A music player based on RT-thread and AB32VG1.

A music player based on RT-thread and AB32VG1.

杨澄 7 May 16, 2022
By controlling the frequency at which the output Pins of MSP430 are turned off and on, we can make music.

By controlling the frequency at which the output Pins of MSP430 are turned off and on, we can make music.

Premkumar Vincent 1 Nov 9, 2021
Standalone player of Monkey Island PC-Speaker music

Standalone player of Monkey Island PC-Speaker music

Thanassis Tsiodras 28 Jul 17, 2022
A simple CLI to extract & save artwork of a 🎵 music/audio file.

artwork-extractor A simple CLI to extract & save artwork of a ?? music/audio file. Usage Dependencies MediaInfoLib On Debian based distros, one may in

Hitesh Kumar Saini 5 Aug 4, 2021
Linux client for Archo Music written in C++, uses Qt Framework.

ArchoMusicLinux Linux client for Archo Music written in C++, uses Qt Framework. For the original client, visit Archo Music Compiling Setting up the li

GianXD 2 Nov 13, 2021
A light-weight music Discord bot using Orca.

What's the "Music Discord bot with C"? A light-weight music Discord bot using Orca for it's bot. It's easy to use and install. How to download and use

ThePedro 9 Jul 18, 2022
An experimental music sequencer using Uxn, designed to run inside of sndkit.

uxnseq An experimental music sequencer using Uxn, designed to run inside of sndkit. The core motivation of this project to test how easily the Uxn VM

Paul Batchelor 6 Feb 6, 2022
An audio mixer that supports various file formats for Simple Directmedia Layer.

An audio mixer that supports various file formats for Simple Directmedia Layer.

Simple Directmedia Layer 163 Sep 26, 2022