rism-digital / verovio

🎵 Music notation engraving library for MEI with MusicXML and Humdrum support and various toolkits (JavaScript, Python)
https://www.verovio.org
GNU Lesser General Public License v3.0
678 stars 185 forks source link

Fingering stacking order is incorrect even with positioning information #2562

Closed ameamenoame closed 2 years ago

ameamenoame commented 2 years ago

Describe the problem Using the MEI file, the rendered fingering differs from the fingering in the MusicXML file used to create the MEI file.

Fingering in the MusicXML file

The chord's fingering is 1 5 Screenshot from 2022-01-07 17-18-52

Fingering in the rendered MEI file

The chord's fingering is now 5 1 Screenshot from 2022-01-07 17-25-45

To Reproduce MusicXML file: https://files.catbox.moe/snhj4k.musicxml

  1. Convert the MusicXML file to MEI using the Verovio Python library
  2. View the MEI file (I'm using https://www.verovio.org/mei-viewer.xhtml)

Example MEI file: https://files.catbox.moe/s9bg7m.mei

Expected behavior The fingering rendered by the MEI file should be the same as the MusicXML file.

Verovio information Verovio 3.5.0, Python bindings

Environment information (as appropriate) OS: Fedora 35

samuelbradshaw commented 2 years ago

Related: https://github.com/w3c/musicxml/issues/439

ameamenoame commented 2 years ago

Related: w3c/musicxml#439

That issue seems to be about fingering without positioning information, but in this case -fingering for a chord with positioning information- shouldn't we be able to fix it?

Fingering info in the MusicXML file

The fingering 5 is bound to the note C, 1 is bound to G. Screenshot from 2022-01-11 14-46-26

Fingering info in the MEI file

The fing tags seem to be bound to the correct notes also using startid, yet it still renders as 5 1 instead of 1 5. Screenshot from 2022-01-11 14-53-40

rettinghaus commented 2 years ago

I think MEI is not sufficient to describe all properties when it comes to fingering. Maybe you could open a discussion over at https://github.com/music-encoding/music-encoding ?

ahankinson commented 2 years ago

These should be wrapped in a fingGrp element, no?

https://music-encoding.org/guidelines/dev/elements/fingGrp.html

The order would be the order that they are listed as children in that element.

craigsapp commented 2 years ago

Here is what I am doing in the Humdrum-to-MEI converter (which was implemented before <fing> was available):

Screen Shot 2022-01-11 at 6 24 36 AM
Click to view MEI data for above example ```xml </titleStmt> <pubStmt /> </fileDesc> <encodingDesc> <appInfo> <application isodate="2022-01-11T06:23:25" version="3.9.0-dev-5935d76-dirty"> <name>Verovio</name> <p>Transcoded from Humdrum</p> </application> </appInfo> </encodingDesc> <workList> <work> <title /> </work> </workList> </meiHead> <music> <body> <mdiv xml:id="m5jk3jn"> <score xml:id="so976nj"> <scoreDef xml:id="suz912r" midi.bpm="400.000000"> <staffGrp xml:id="sjpr6v7"> <staffDef xml:id="s2ye70c" n="1" lines="5"> <clef xml:id="c2asc4w" shape="F" line="4" /> <meterSig xml:id="metersig-L2F1" count="4" unit="4" /> </staffDef> </staffGrp> </scoreDef> <section xml:id="section-L1F1"> <measure xml:id="measure-L1" n="1"> <staff xml:id="sbfgfd7" n="1"> <layer xml:id="layer-L1F1N1" n="1"> <chord xml:id="chord-L5F1" dur="1"> <note xml:id="note-L5F1S1" oct="3" pname="c" accid.ges="n" /> <note xml:id="note-L5F1S2" oct="3" pname="g" accid.ges="n" /> </chord> </layer> </staff> <dir xml:id="dir-L5F2" type="fingering" place="below" staff="1" startid="#chord-L5F1"> <rend xml:id="rrswx6t" fontsize="x-small" fontstyle="normal">5</rend> </dir> <dir xml:id="dir-L5F2" type="fingering" place="below" staff="1" startid="#chord-L5F1"> <rend xml:id="r74tmxe" fontsize="x-small" fontstyle="normal">1</rend> </dir> </measure> <measure xml:id="measure-L6" n="2"> <staff xml:id="staff-L6F1N1" n="1"> <layer xml:id="layer-L6F1N1" n="1"> <chord xml:id="chord-L7F1" dur="1"> <note xml:id="note-L7F1S1" oct="3" pname="c" accid.ges="n" /> <note xml:id="note-L7F1S2" oct="3" pname="g" accid.ges="n" /> </chord> </layer> </staff> <dir xml:id="dir-L7F2" type="fingering" place="below" staff="1" startid="#chord-L7F1"> <rend xml:id="rw53f91" fontsize="x-small" fontstyle="normal">1</rend> </dir> <dir xml:id="dir-L7F2" type="fingering" place="below" staff="1" startid="#chord-L7F1"> <rend xml:id="ruokh9s" fontsize="x-small" fontstyle="normal">5</rend> </dir> </measure> </section> </score> </mdiv> </body> </music> </mei> ``` </details> <p>Ordering of the <code><dir></code> (or <code><fing></code>) is the method I use to select the stacking order of the fingering numbers. Note that the stacking order is from near to far from the staff, so if you move the fingerings to the other side of the staff, then they will flip their order (so you would have to reverse their order when moving to the other side of the staff if you want to keep the same order of the numbers from top-down).</p> <p>So it is possible to get the correct order in the MusicXML importer by considering the pitches related to the fingerings, but it would be a lot of work, and perhaps better would be to improve the system in verovio.</p> <p>In the MusicXML example, the fingering number is attached to the note, with the stacking order left up to the renderer (which should match the pitch order for the fingerings, of course). A possible enhancement in the fingering positions would be to use the <code>@startid</code> of the <code><fing></code> to calculate an order for the fingering that matches the order of the note pitches which they are attached to (when <code>@startid</code> is available; otherwise, use the current stacking behavior).</p> <p><code>fingGrp</code> would be good to implement, but in that case the MusicXML importer would still have to do work to calculate the order that matches the pitches. In other words, <code>fingGrp</code> should assumed to be in a fixed vertical order, such as top-down as in <code><fb></code>).</p> <p>Perhaps utilizing the code for figured bass which has a similar visual syntax to <code><fingGrp></code> (which I do not think is implemented in verovio yet)?</p> <img width="198" alt="Screen Shot 2022-01-11 at 6 38 21 AM" src="https://user-images.githubusercontent.com/3487289/148963347-e7fb4107-122b-4eaa-bccc-e04fc8221a49.png"> <details> <summary> Click to view MEI data for above example </summary> ```xml <?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 /> </titleStmt> <pubStmt /> </fileDesc> <encodingDesc> <appInfo> <application isodate="2022-01-11T06:38:04" version="3.9.0-dev-5935d76-dirty"> <name>Verovio</name> <p>Transcoded from Humdrum</p> </application> </appInfo> </encodingDesc> <workList> <work> <title /> </work> </workList> </meiHead> <music> <body> <mdiv xml:id="mv2qyyv"> <score xml:id="slofrvx"> <scoreDef xml:id="ssekofk" midi.bpm="400.000000"> <staffGrp xml:id="s9y9mj8"> <staffDef xml:id="sd87m8d" n="1" lines="5"> <clef xml:id="c2gwe1v" shape="F" line="4" /> </staffDef> </staffGrp> </scoreDef> <section xml:id="section-L1F1"> <measure xml:id="measure-L1"> <harm xml:id="harm-L2F2" staff="1" tstamp="1.000000"> <fb xml:id="fb-L2F2"> <f xml:id="f-L2F2N1"></f> <f xml:id="f-L2F2N2"></f> </fb> </harm> <staff xml:id="sy655if" n="1"> <layer xml:id="layer-L1F1N1" n="1"> <chord xml:id="chord-L2F1" dur="1"> <note xml:id="note-L2F1S1" oct="3" pname="c" accid.ges="n" /> <note xml:id="note-L2F1S2" oct="3" pname="g" accid.ges="n" /> </chord> </layer> </staff> </measure> </section> </score> </mdiv> </body> </music> </mei> ``` </details> </div> </div> <div class="page-bar-simple"> </div> <div class="footer"> <ul class="body"> <li>© <script> document.write(new Date().getFullYear()) </script> Githubissues.</li> <li>Githubissues is a development platform for aggregating issues.</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script> <script src="/githubissues/assets/js.js"></script> <script src="/githubissues/assets/markdown.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/languages/go.min.js"></script> <script> hljs.highlightAll(); </script> </body> </html>