verovio icon indicating copy to clipboard operation
verovio copied to clipboard

dynam dir alignment

Open ndubo opened this issue 4 years ago • 9 comments

In the example from Brahms op. 116/6 the ‘p’ and the “dol. e ben legato’ are on the same line: dynam_dir_Brahms_116-06 Typically, one would encode the first as <dynam>, the second as <dir>.

The same is true for the this example from K. 581/02, where the dynamic mark and the performance mark are meant to be read as one single expression. ‘p con sordino‘ (Of course, the ‘con sordino’ refers to first note as well, just like the p): dynam-dir-K58102c

Vertical alignment of different elements such as <dynam> and <dir> with @vgrp would be desirable.

Here is the code for K. 581/02:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<mei meiversion="4.0.0" xmlns="http://www.music-encoding.org/ns/mei">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title>K.581/02</title>
    <respStmt/>
   </titleStmt>
   <pubStmt/>
  </fileDesc>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mdiv_543002">
    <score xml:id="score_480">
     <scoreDef key.mode="major" key.pname="d" key.sig="2s" meter.count="3" meter.unit="4" xml:id="scoreDef_01">
      <staffGrp bar.thru="true" symbol="bracket" xml:id="staffGrp_01">
       <staffDef clef.line="2" clef.shape="G" key.sig="1f" lines="5" n="1" trans.diat="-2" trans.semi="-3" xml:id="staffDef_P1">
        <label xml:id="label_P1">Clarinetto <lb xml:id="lb_P1"/>in La/A</label>
       </staffDef>
       <staffGrp symbol="brace" xml:id="staffGrp_02">
        <staffDef clef.line="2" clef.shape="G" lines="5" n="2" xml:id="staffDef_P2">
         <label xml:id="label_P2">Violino I</label>
        </staffDef>
        <staffDef clef.line="2" clef.shape="G" lines="5" n="3" xml:id="staffDef_P3">
         <label xml:id="label_P3">Violino II</label>
        </staffDef>
       </staffGrp>
       <staffDef clef.line="3" clef.shape="C" lines="5" n="4" xml:id="staffDef_P4">
        <label xml:id="label_P4">Viola</label>
       </staffDef>
       <staffDef clef.line="4" clef.shape="F" lines="5" n="5" xml:id="staffDef_P5">
        <label xml:id="label_P5">Violoncello</label>
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section_564">
      <measure facs="#zoneOf_measure1" n="1" xml:id="m1_k581_002">
       <tempo midi.bpm="55" place="above" staff="1" tstamp="1" xml:id="tempo01">Larghetto</tempo>
       <staff n="1" xml:id="staff_3876">
        <layer n="1" xml:id="layer_3882">
         <note dots="1" dur="4" oct="5" pname="c" tstamp="1" xml:id="note_3888"/>
         <beam xml:id="beam_3894">
          <note dur="8" oct="5" pname="f" tstamp="2.5" xml:id="note_3900"/>
          <note dur="8" oct="5" pname="a" tstamp="3" xml:id="note_3906"/>
          <note dur="8" oct="5" pname="f" tstamp="3.5" xml:id="note_3912"/>
         </beam>
        </layer>
       </staff>
       <staff n="2" xml:id="staff_3918">
        <layer n="1" xml:id="layer_3924">
         <beam xml:id="beam_3930">
          <note accid.ges="s" dur="8" oct="4" pname="f" tstamp="1" xml:id="note_3936"/>
          <note dur="8" oct="4" pname="d" tstamp="1.5" xml:id="note_3942"/>
          <note accid.ges="s" dur="8" oct="4" pname="f" tstamp="2" xml:id="note_3948"/>
          <note dur="8" oct="4" pname="d" tstamp="2.5" xml:id="note_3954"/>
          <note accid.ges="s" dur="8" oct="4" pname="f" tstamp="3" xml:id="note_3960"/>
          <note dur="8" oct="4" pname="d" tstamp="3.5" xml:id="note_3966"/>
         </beam>
        </layer>
       </staff>
       <staff n="3" xml:id="staff_3972">
        <layer n="1" xml:id="layer_3978">
         <beam xml:id="beam_3984">
          <note dur="8" oct="4" pname="d" tstamp="1" xml:id="note_3990"/>
          <note dur="8" oct="3" pname="a" tstamp="1.5" xml:id="note_3996"/>
          <note dur="8" oct="4" pname="d" tstamp="2" xml:id="note_4002"/>
          <note dur="8" oct="3" pname="a" tstamp="2.5" xml:id="note_4008"/>
          <note dur="8" oct="4" pname="d" tstamp="3" xml:id="note_4014"/>
          <note dur="8" oct="3" pname="a" tstamp="3.5" xml:id="note_4020"/>
         </beam>
        </layer>
       </staff>
       <staff n="4" xml:id="staff_4026">
        <layer n="1" xml:id="layer_4032">
         <beam xml:id="beam_4038">
          <note dur="8" oct="3" pname="a" tstamp="1" xml:id="note_4044"/>
          <note accid.ges="s" dur="8" oct="3" pname="f" tstamp="1.5" xml:id="note_4050"/>
          <note dur="8" oct="3" pname="a" tstamp="2" xml:id="note_4056"/>
          <note accid.ges="s" dur="8" oct="3" pname="f" tstamp="2.5" xml:id="note_4062"/>
          <note dur="8" oct="3" pname="a" tstamp="3" xml:id="note_4068"/>
          <note accid.ges="s" dur="8" oct="3" pname="f" tstamp="3.5" xml:id="note_4074"/>
         </beam>
        </layer>
       </staff>
       <staff n="5" xml:id="staff_4080">
        <layer n="1" xml:id="layer_4086">
         <note dots="1" dur="2" oct="3" pname="d" tstamp="1" xml:id="note_4092"/>
        </layer>
       </staff>
       <dynam staff="1" startid="#note_3888" xml:id="dynam_4098">p</dynam>
       <dynam staff="2" startid="#note_3936" xml:id="dynam_4110" vgrp="1">p</dynam>
       <dynam staff="3" startid="#note_3990" xml:id="dynam_4122" vgrp="1">p</dynam>
       <dynam staff="4" startid="#note_4044" xml:id="dynam_4134" vgrp="1">p</dynam>
       <dynam staff="5" startid="#note_4092" xml:id="dynam_4146">p</dynam>
       <dir place="below" staff="2" tstamp="1.2" xml:id="dir_4164" vgrp="1">
        <rend fontstyle="normal" xml:id="rend_4164">con sordino</rend>
       </dir>
       <dir place="below" staff="3" tstamp="1.2" xml:id="dir_4176" vgrp="1">
        <rend fontstyle="normal" xml:id="rend_4176">con sordino</rend>
       </dir>
       <supplied xml:id="supplied_4177">
        <dir place="below" staff="4" tstamp="1.2" xml:id="dir_4177" vgrp="1">
         <rend fontstyle="normal" xml:id="rend_4177">con sordino</rend>
        </dir>
       </supplied>
       <slur endid="#note_3912" staff="1" startid="#note_3888" xml:id="slur_4188"/>
       <slur endid="#note_3966" staff="2" startid="#note_3936" xml:id="slur_4194"/>
       <slur endid="#note_4020" staff="3" startid="#note_3990" xml:id="slur_4200"/>
       <slur endid="#note_4074" staff="4" startid="#note_4044" xml:id="slur_4206"/>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

ndubo avatar Oct 03 '19 09:10 ndubo

Slightly related to issue https://github.com/rism-ch/verovio/issues/1117.

One solution is to treat the combined text as a composite <dir>, embedding the dynamic within the <dir>. This would be an appropriate solution for cases such as this example from the first movement of Beethoven's moonlight sonata:

Screen Shot 2019-10-03 at 11 42 00 AM

So something like

<dir>
    sempre <dynam>pp</dynam> e senza sordini
</dir>

seems to be the best solution.

If there is no solution for this yet, it would be good to come up with one, as this sort of case is quite common. @vgrp solves the horizontal alignment, but there is also the question of precedence: when multiple <dir> and/or <dynam> occur on the same note or timestamp, which one gets to go first, and which one gets moved to the end of the previous one? The order should not be faked by giving a slightly different timestamp to each dir/dynam.

This is somewhat similar to the case where a dynamic and a hairpin are attached to the same note. This case has been implemented:

Screen Shot 2019-10-03 at 11 36 51 AM
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title />
            </titleStmt>
            <pubStmt />
        </fileDesc>
        <encodingDesc>
            <appInfo>
                <application isodate="2019-10-03T11:37:36" version="2.2.0-dev-33affbd-dirty">
                    <name>Verovio</name>
                    <p>Transcoded from Humdrum</p>
                </application>
            </appInfo>
        </encodingDesc>
        <workList>
            <work>
                <title />
            </work>
        </workList>
    </meiHead>
    <music>
        <body>
            <mdiv xml:id="mdiv-0000000937936252">
                <score xml:id="score-0000001067919542">
                    <scoreDef xml:id="scoredef-0000000018255301" midi.bpm="400">
                        <staffGrp xml:id="staffgrp-0000001378649291">
                            <staffDef xml:id="staffdef-0000000997717923" n="1" lines="5">
                                <clef xml:id="clef-0000000488214972" shape="G" line="2" />
                                <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
                            </staffDef>
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-L1F1">
                        <measure xml:id="measure-L1" n="0">
                            <staff xml:id="staff-0000000240671000" n="1">
                                <layer xml:id="layer-L1F1N1" n="1">
                                    <note xml:id="note-L4F1" dur="1" oct="4" pname="c" accid.ges="n" />
                                </layer>
                            </staff>
                            <dynam xml:id="dynam-L4F2" staff="1" tstamp="1.000000" vgrp="100">p</dynam>
                            <hairpin xml:id="hairpin-L4F2" staff="1" tstamp="1.000000" tstamp2="1m+1.0000" form="cres" vgrp="100" />
                        </measure>
                        <measure xml:id="measure-L5" n="2">
                            <staff xml:id="staff-L5F1N1" n="1">
                                <layer xml:id="layer-L5F1N1" n="1">
                                    <note xml:id="note-L6F1" dur="1" oct="4" pname="d" accid.ges="n" />
                                </layer>
                            </staff>
                            <dynam xml:id="dynam-L6F2" staff="1" tstamp="1.000000" vgrp="100">f</dynam>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>

Here is a similar case that has not yet been addressed, where there is a mixture of a dynamic and a text direction:

Screen Shot 2019-10-03 at 11 38 29 AM

In this case there is not enough information about whether the combined text should be p cresc. or cresc. p. Inferring the order is not good, since there are also reverse cases like subito p.

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title />
            </titleStmt>
            <pubStmt />
        </fileDesc>
        <encodingDesc>
            <appInfo>
                <application isodate="2019-10-03T11:39:17" version="2.2.0-dev-33affbd-dirty">
                    <name>Verovio</name>
                    <p>Transcoded from Humdrum</p>
                </application>
            </appInfo>
        </encodingDesc>
        <workList>
            <work>
                <title />
            </work>
        </workList>
    </meiHead>
    <music>
        <body>
            <mdiv xml:id="mdiv-0000001545811197">
                <score xml:id="score-0000001790224813">
                    <scoreDef xml:id="scoredef-0000002129172812" midi.bpm="400">
                        <staffGrp xml:id="staffgrp-0000000549950010">
                            <staffDef xml:id="staffdef-0000001813418073" n="1" lines="5">
                                <clef xml:id="clef-0000000249622694" shape="G" line="2" />
                                <meterSig xml:id="metersig-L2F1" count="4" unit="4" />
                            </staffDef>
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-L1F1">
                        <measure xml:id="measure-L1" n="0">
                            <staff xml:id="staff-0000000580227469" n="1">
                                <layer xml:id="layer-L1F1N1" n="1">
                                    <note xml:id="note-L4F1" dur="1" oct="4" pname="c" accid.ges="n" />
                                </layer>
                            </staff>
                            <dynam xml:id="dynam-L4F2" staff="1" tstamp="1.000000" vgrp="100">p</dynam>
                            <dir xml:id="dir-L4F2" staff="1" vgrp="100" tstamp="1.000000">cresc.</dir>
                        </measure>
                        <measure xml:id="measure-L5" n="2">
                            <staff xml:id="staff-L5F1N1" n="1">
                                <layer xml:id="layer-L5F1N1" n="1">
                                    <note xml:id="note-L6F1" dur="1" oct="4" pname="d" accid.ges="n" />
                                </layer>
                            </staff>
                            <dynam xml:id="dynam-L6F2" staff="1" tstamp="1.000000" vgrp="100">f</dynam>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>


craigsapp avatar Oct 03 '19 18:10 craigsapp

The order should not be faked by giving a slightly different timestamp to each dir/dynam.

This is an important point!

I like the <dynam> nested into the <dir> because it's simple, but something in my guts says, that this is not the solution. What about a horizontal sequence controlled by @next and @prev?

ndubo avatar Oct 04 '19 14:10 ndubo

What about a horizontal sequence controlled by @next and @prev?

That sounds good to me.

craigsapp avatar Oct 04 '19 14:10 craigsapp

Another way to look at this issue would be to make verovio render dynamic abbreviation, including within text, with the music font. Then you would simply have:

<dynam>
    sempre pp e senza sordini
</dynam>

(I think this is something Lilypond does.) Alternatively, we could require a <rend> to be added around the 'pp', but I am not sure this is actually necessary.

@ndubo support for @vgrp should be added anyway.

lpugin avatar Oct 06 '19 09:10 lpugin

A problem is that the pp in sempre pp e senza sordini needs to be identified as the dynamic to play the music. In other words when converting to MIDI, a converter needs to see the pp as a dynamic to perform the music in. Conversely, if the dynamic in some text does not refer to the current dynamic of the music, there should be a way of telling the MIDI renderer not to use that dynamic in the performance rendering.

There are a lot of dynamics: p pp ppp pppp pppp etc, same for f, mp, mf, mfp fp pf ffp and also accents sf sfz sffz fz ffz etc. so it would be difficult to automatically identify all of them with 100% accuracy in order to give them the correct font (so using a <rend> would probably be safer.

There are also case, particularly in 18th century music, where the printed dynamics are displayed in a roman-like font and the editorial dynamics are using the modern dynamic font, so some encoders would want to control the font of the dynamics.

craigsapp avatar Oct 06 '19 12:10 craigsapp

This is the list of supported dynamics : https://w3c.github.io/smufl/gitbook/tables/dynamics.html

I think we can support them within dynam strings. For other cases, then <rend> should be used, but this will yield other issues when letters are missing. The alignment of the letters will be another issue but let's not discuss it here. MIDI conversion should also be addressed in another issue when dynamics will be taken into account.

lpugin avatar Oct 06 '19 19:10 lpugin

<dynam>
    sempre pp e senza sordini
</dynam>

is now rendered as image

lpugin avatar Oct 07 '19 16:10 lpugin

@craigsapp : if you do not want to have this you can do

<dynam>
    <rend fontfam="Times">sempre pp e senza sordini</rend>
</dynam>

lpugin avatar Oct 09 '19 09:10 lpugin

@ndubo looking at the alignment of dir with dynam, I think we have a problem. Normally the order for laying out control event is:

  • mordent / turn / trill
  • dynam / hairpin
  • brackets
  • octave
  • breath
  • fermata
  • dir
  • tempo
  • pedal
  • harm
  • (ending)

Grouping dynam and dir causes a problem. We can change the order and align dir with dynam / hairpin, but then there will be other complains. Any ideas what the algorithm should be?

lpugin avatar Oct 09 '19 11:10 lpugin