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
656 stars 180 forks source link

fermata and editorial accidentals overstrike each other #395

Closed craigsapp closed 7 years ago

craigsapp commented 7 years ago

Fermatas and editorial accidentals overstrike each other:

screen shot 2016-12-24 at 20 49 49

Probably the fermata should go above the accidental.

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-24 20:46:49</date>
            </pubStmt>
        </fileDesc>
        <encodingDesc>
            <projectDesc>
                <p>Transcoded from Humdrum with Verovio version 0.9.13-dev-8b82cb1-dirty</p>
            </projectDesc>
        </encodingDesc>
    </meiHead>
    <music>
        <body>
            <mdiv>
                <score>
                    <scoreDef xml:id="scoredef-000000116560764">
                        <staffGrp xml:id="m-000000042101571">
                            <staffDef xml:id="staffdef-000000001774439" clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5" />
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-000000012417903">
                        <measure xml:id="measure-L3" n="1" right="end">
                            <staff xml:id="staff-L3F1" n="1">
                                <layer xml:id="layer-L3F1" n="1">
                                    <note xml:id="note-L4F1" dur="1" fermata="above" oct="4" pname="f">
                                        <accid xml:id="accid-000000164244899" accid="s" func="edit" />
                                    </note>
                                </layer>
                            </staff>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>
lpugin commented 7 years ago

It should align properly with a <fermata startid="thenote">

craigsapp commented 7 years ago

OK, but are you going to fix the case where it is expressed as @fermata="above"?

screen shot 2016-12-26 at 06 13 01
<?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-24 20:46:49</date>
            </pubStmt>
        </fileDesc>
        <encodingDesc>
            <projectDesc>
                <p>Transcoded from Humdrum with Verovio version 0.9.13-dev-8b82cb1-dirty</p>
            </projectDesc>
        </encodingDesc>
    </meiHead>
    <music>
        <body>
            <mdiv>
                <score>
                    <scoreDef xml:id="scoredef-000000116560764">
                        <staffGrp xml:id="m-000000042101571">
                            <staffDef xml:id="staffdef-000000001774439" clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5" />
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-000000012417903">
                        <measure xml:id="measure-L3" n="1" right="end">
                            <staff xml:id="staff-L3F1" n="1">
                                <layer xml:id="layer-L3F1" n="1">
                                    <note xml:id="note-L4F1" dur="1" oct="4" pname="f">
                                        <accid xml:id="accid-000000164244899" accid="s" func="edit" />
                                    </note>
                                </layer>
                            </staff>
                            <fermata startid="#note-L4F1">
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>
lpugin commented 7 years ago

This will be a very low priority because one way to do it is already supported. Actually the only case where I think using @fermata instead of <fermata> is with <mRest> because you want it centred, which is not necessary the tstamp of the middle of the measure.

craigsapp commented 7 years ago

Yes, low priority. Somehow the placement functions for @accid and <accid> should be merged.

But how should this be encoded?:

screen shot 2016-12-26 at 13 30 43

The fermata on the bottom staff seems reasonable to encode as <fermata> since it affects two notes, but for the upper staff, @fermata seems more appropriate as each fermata affects a single note. This would be useful for MIDI rendering with a realization of the fermatas being handled correctly in this case (the pause occurs on the second/third beats, eventhough some fermatas start on the first beat).

Otherwise, why bother having note@fermata? There could just be mrest@fermata. [is it possible to put a fermata on a barline in verovio?]

I could always encode as<fermata> and use @plist to indicate which notes are affected by the fermata (as recommended by Klaus).

lpugin commented 7 years ago

Otherwise, why bother having note@fermata? There could just be mrest@fermata

This is a Verovio support decision. Maybe we can use @startid to point to mRest and then completely remove @fermata support.

is it possible to put a fermata on a barline in verovio?

This is actually a good question for MEI.

pe-ro commented 7 years ago

is it possible to put a fermata on a barline in verovio?

This is actually a good question for MEI.

Yes, fermatas over bar lines are possible. For example, in 4/4 --

<fermata tstamp="5"/>

indicates a fermata over the right bar line. While

<fermata tstamp="0"/>

says there's a fermata over the left bar line.

I think it would be best to avoid using @fermata for rendering purposes. My plan is to move it and several other attributes into the analytical domain where they would be "switched off" unless the MEI.analysis module is active. This is intended to help clarify the difference between these attributes and their element counterparts and to encourage the use of the elements.

pe-ro commented 7 years ago

Although I just realized it's more than a little out of whack, here's the chunk of my ODD file for the next revision that deals with moving attributes from the logical to the analytical domain. It's just for illustration and will probably change.

<!-- Move some attributes from the logical to the analytical domain -->
<classSpec ident="att.chord.anl" module="MEI.shared" type="atts" mode="replace">
  <desc>Analytical domain attributes.</desc>
  <classes>
    <memberOf key="att.chord.anl.cmn"/>
    <memberOf key="att.common.anl"/>
  </classes>
</classSpec>
<classSpec ident="att.chord.anl.cmn" module="MEI.analysis.cmn" type="atts" mode="add">
  <desc>Analytical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.fermatapresent"/>
    <memberOf key="att.lvpresent"/>
    <memberOf key="att.ornam"/>
    <memberOf key="att.slurpresent"/>
    <memberOf key="att.tiepresent"/>
    <memberOf key="att.tupletpresent"/>
  </classes>
</classSpec>
<classSpec ident="att.chord.log" module="MEI.shared" type="atts" mode="replace">
  <desc>Logical domain attributes for chord. The artic, dots, and dur attributes encode the
   written articulations, augmentation dots, and duration values.</desc>
  <classes>
    <memberOf key="att.articulation"/>
    <memberOf key="att.augmentdots"/>
    <memberOf key="att.chord.log.cmn"/>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
    <memberOf key="att.syltext"/>
  </classes>
</classSpec>
<classSpec ident="att.chord.log.cmn" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes in the CMN repertoire.</desc>
</classSpec>
<classSpec ident="att.mRest.anl" module="MEI.cmn" type="atts" mode="replace">
  <desc>Analytical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.common.anl"/>
    <memberOf key="att.fermatapresent"/>
  </classes>
</classSpec>
<classSpec ident="att.mRest.log" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
  </classes>
</classSpec>
<classSpec ident="att.mSpace.anl" module="MEI.cmn" type="atts" mode="replace">
  <desc>Analytical domain attributes in the CMN repertoire. Use the n attribute to
  explicitly encode this measure's position in a string of measures containing only
  &lt;mRest&gt; elements.</desc>
  <classes>
    <memberOf key="att.common.anl"/>
    <memberOf key="att.fermatapresent"/>
  </classes>
</classSpec>
<classSpec ident="att.mSpace.log" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.augmentdots"/>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
  </classes>
</classSpec>
<classSpec ident="att.note.anl" module="MEI.shared" type="atts" mode="replace">
  <desc>Analytical domain attributes.</desc>
  <classes>
    <memberOf key="att.common.anl"/>
    <memberOf key="att.harmonicfunction"/>
    <memberOf key="att.intervalmelodic"/>
    <memberOf key="att.melodicfunction"/>
    <memberOf key="att.note.anl.cmn"/>
    <memberOf key="att.note.anl.mensural"/>
    <memberOf key="att.pitchclass"/>
    <memberOf key="att.solfa"/>
  </classes>
</classSpec>
<classSpec ident="att.note.anl.cmn" module="MEI.analysis.cmn" type="atts" mode="add">
  <desc>Analytical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.beamed"/>
    <memberOf key="att.fermatapresent"/>
    <memberOf key="att.lvpresent"/>
    <memberOf key="att.ornam"/>
    <memberOf key="att.slurpresent"/>
    <memberOf key="att.syltext"/>
    <memberOf key="att.tiepresent"/>
    <memberOf key="att.tupletpresent"/>
  </classes>
</classSpec>
<classSpec ident="att.note.log" module="MEI.shared" type="atts" mode="replace">
  <desc>Logical domain attributes.</desc>
  <classes>
    <memberOf key="att.accidental"/>
    <memberOf key="att.articulation"/>
    <memberOf key="att.augmentdots"/>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
    <memberOf key="att.note.log.cmn"/>
    <memberOf key="att.note.log.mensural"/>
    <memberOf key="att.pitched"/>
  </classes>
</classSpec>
<classSpec ident="att.note.log.cmn" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes.</desc>
</classSpec>
<classSpec ident="att.note.log.mensural" module="MEI.mensural" type="atts" mode="replace">
  <desc>Logical domain attributes in the Mensural repertoire.</desc>
</classSpec>
<classSpec ident="att.note.anl.mensural" module="MEI.analysis.mensural" type="atts"
mode="add">
  <desc>Analytical domain attributes in the Mensural repertoire.</desc>
  <attList>
    <attDef ident="lig" usage="opt">
      <desc>Indicates this element's participation in a ligature.</desc>
      <valList type="closed">
        <valItem ident="recta"/>
        <valItem ident="obliqua"/>
      </valList>
    </attDef>
  </attList>
</classSpec>
<classSpec ident="att.rest.anl" module="MEI.shared" type="atts" mode="replace">
  <desc>Analytical domain attributes.</desc>
  <classes>
    <memberOf key="att.common.anl"/>
    <memberOf key="att.rest.anl.cmn"/>
  </classes>
</classSpec>
<classSpec ident="att.rest.anl.cmn" module="MEI.analysis.cmn" type="atts" mode="add">
  <desc>Analytical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.beamed"/>
    <memberOf key="att.fermatapresent"/>
    <memberOf key="att.tupletpresent"/>
  </classes>
</classSpec>
<classSpec ident="att.rest.log" module="MEI.shared" type="atts" mode="replace">
  <desc>Logical domain attributes.</desc>
  <classes>
    <memberOf key="att.augmentdots"/>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
    <memberOf key="att.rest.log.cmn"/>
  </classes>
</classSpec>
<classSpec ident="att.rest.log.cmn" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes in the CMN repertoire.</desc>
</classSpec>
<classSpec ident="att.space.anl" module="MEI.shared" type="atts" mode="replace">
  <desc>Analytical domain attributes.</desc>
  <classes>
    <memberOf key="att.common.anl"/>
    <memberOf key="att.space.anl.cmn"/>
  </classes>
</classSpec>
<classSpec ident="att.space.anl.cmn" module="MEI.analysis.cmn" type="atts" mode="add">
  <desc>Analytical domain attributes in the CMN repertoire.</desc>
  <classes>
    <memberOf key="att.beamed"/>
    <memberOf key="att.fermatapresent"/>
    <memberOf key="att.tupletpresent"/>
  </classes>
</classSpec>
<classSpec ident="att.space.log" module="MEI.shared" type="atts" mode="replace">
  <desc>Logical domain attributes.</desc>
  <classes>
    <memberOf key="att.augmentdots"/>
    <memberOf key="att.duration.musical"/>
    <memberOf key="att.event"/>
  </classes>
</classSpec>
<classSpec ident="att.space.log.cmn" module="MEI.cmn" type="atts" mode="replace">
  <desc>Logical domain attributes in the CMN repertoire.</desc>
</classSpec>

Doing this will

I haven't created an MEI issue for this yet, mostly because I wanted to float this idea here first. This is a huge shift, but it doesn't mean that any attributes will go away. They'll just be de-emphasized, in the sense that in order to use them, the MEI.analysis module will have to be intentionally turned on. I hope this will make it easier to steer users (and developers, too) toward, say, <accid> when they realize that @accid might not be present. This is not unlike the current situation with @accid.ges, which may or may not be present in all encodings.

Comments, please.

craigsapp commented 7 years ago

privilege the element versions of the attributes

Sounds like MusicXML :-)

Looks good to me. Anything which can be inferred from "logical" attributes/elements in the data would be good to place into an analytic group (other than @accid/@accid.ges :-). For basic notation representation the analytic features should not be needed, so would be useful for minimal versions of MEI.

pe-ro commented 7 years ago

Glad you approve. Not everyone will. ☹️

Sounds like MusicXML :-)

Definitely not. 😛

lpugin commented 7 years ago

This is now fixed

image