Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single note underline extender problem and word hyphens #292

Closed
craigsapp opened this issue Sep 15, 2016 · 12 comments
Closed

Single note underline extender problem and word hyphens #292

craigsapp opened this issue Sep 15, 2016 · 12 comments

Comments

@craigsapp
Copy link
Contributor

Related to the example Bona condit from issue #291 , I notice that verovio has problems rendering underline extenders which are attached to single-note syllables:

        <note xml:id="m-53" dur="brevis" dur.ges="3072p" oct="4" oct.ges="3" pname="e" plica="desc">
         <verse xml:id="m-55" n="1">            
          <syl xml:id="m-56" wordpos="i">Bo</syl>       
         </verse>                                               
        </note>
        <note xml:id="m-54" dur="brevis" dur.ges="3072p" oct="3" oct.ges="2" pname="a" plica="asc">
         <verse xml:id="m-57" n="1">                                            
          <syl xml:id="m-58" con="u" wordpos="t">na</syl>               
         </verse>                                               
        </note>                                                 
        <barLine xml:id="m-952cc0ef-a6b4-487b-b8a6-327570e767bf" />
       <note xml:id="m-83" dur="brevis" dur.ges="3072p" oct="4" oct.ges="3" pname="e">
         <verse xml:id="m-88" n="1">                                            
          <syl xml:id="m-89" wordpos="i">con</syl>
         </verse>                                                       
        </note>                                                 
        <note xml:id="m-84" dur="semibrevis" dur.ges="1024p" oct="4" oct.ges="3" pname="c" quality="i" num="3" numbase="2">
         <verse xml:id="m-90" n="1">                            
          <syl xml:id="m-91" con="u" wordpos="t">dit</syl>
         </verse>                                                       
        </note>                                                                 
        <note xml:id="m-85" dur="minima" dur.ges="512p" oct="3" oct.ges="2" pname="b" />
        <note xml:id="m-86" dur="semibrevis" dur.ges="1024p" oct="4" oct.ges="3" pname="c" quality="i" num="3" numbase="2" />                                                               
        <note xml:id="m-87" dur="minima" dur.ges="512p" oct="4" oct.ges="3" pname="d" />
        <barLine xml:id="m-9a6a69cd-e71e-43a2-8384-9a063768c8ce" />     

In the rendering below, The underline is placed overlapping with the syllable (and perhaps is not aware of the syllable), and it goes for a short distance, perhaps related to the unlayed-out spacing of the notes.

verovio bona_output.mei  --no-layout

screen shot 2016-09-15 at 5 33 23 am

Also notice the C's (do's) ledger lines are not centered on the notehead, but for B/si with a stem, it is.

Here are other example elsewhere in the work:

screen shot 2016-09-15 at 5 38 35 am

screen shot 2016-09-15 at 5 38 48 am

Verovio should obviously not overlap the underline with the syllable. Then there are three possibilities for how to render it: (1) omit the underline since there is only a single note, (2) put a small fixed-length underscore after the syllable, or (3) have the underline fully extend to the next syllable.

In the next measure, the word cetera is placed on three notes:

     <barLine xml:id="m-9a6a69cd-e71e-43a2-8384-9a063768c8ce" />     
        <note xml:id="m-101" dur="brevis" dur.ges="3072p" oct="3" oct.ges="2" pname="b">
         <verse xml:id="m-104" n="1">
          <syl xml:id="m-105" wordpos="i">ce</syl>
         </verse>
        </note>
        <note xml:id="m-102" dur="semibrevis" dur.ges="1536p" oct="3" oct.ges="2" pname="b">
         <verse xml:id="m-106" n="1">
          <syl xml:id="m-107" wordpos="m">te</syl>
         </verse>
        </note>
        <note xml:id="m-103" dur="semibrevis" dur.ges="1536p" oct="3" oct.ges="2" pname="b">
         <verse xml:id="m-108" n="1">
          <syl xml:id="m-109" wordpos="t">ra</syl>
         </verse>
        </note>
        <barLine xml:id="m-71f03001-0f9e-4404-acab-0468a8123379" />

The syllables have wordpos="i", "m", an "t", but there are no dashes between the syllables, and they look like independent words:

screen shot 2016-09-15 at 5 37 44 am

@lpugin
Copy link
Contributor

lpugin commented Sep 15, 2016

I think they are mostly encoding issues.

        <note xml:id="m-54" dur="brevis" dur.ges="3072p" oct="3" oct.ges="2" pname="a" plica="asc">
         <verse xml:id="m-57" n="1">                                            
          <syl xml:id="m-58" con="u" wordpos="t">na</syl>               
         </verse>                                               
        </note> 

It does not really make sense to have a @con="u" because the syllable is sung on only one note. (Because the next note has a new syllable, Verovio is confused an messes up the dash.)

Missing dashes between syllables: a @con="d" is missing

@craigsapp
Copy link
Contributor Author

There may be reasons to have an underline after a syllable, although standard modern editing style does not allow it. For example for a very long not with multiple verse, perhaps an underline may be needed to avoid confusion for the singer as to which syllable follows in the verse.

Your viewpoint is Andrew-like, and perhaps the underline should be automatically suppressed as it is an encoding error. If the schematron were to check and flag this error, then you would be allowed to blame the encoder and leave the behavior as it is.

A Johannesburg-like argument would say yhat the underline is valid and should be shown through the end of the single note. Suppose that a manuscript has an underline for a single note. Are you going to forbid it from being encoded. This would probably result in the encoder violating the intent of the MEI by making them add an underline as a text direction.

@craigsapp
Copy link
Contributor Author

For @cond="d", the is an interesting case. It is similar to the @accid problem for notes. In both cases there should be a "sic" state which indicates that nothing should be shown. This case has a stronger argument for that as xampared to the @accid case. Ideally initial or medial syllables should automatically include a following dash unless another style or the blank style is given. The is particularly true for hand encoding where having to type redundant information is a pain. Alternatively the MEI header would specify the connecting style for word syllables, with the default being to use dashes.

@craigsapp
Copy link
Contributor Author

Typos due to typing on an iPhone in the airport....

@lpugin
Copy link
Contributor

lpugin commented Sep 15, 2016

I am not blaming anybody, but this particular case is not a good example where we would need to draw something with an extender with a single note. It is only a question of priorities an until we have a better view of what should happen in such cases I am suggesting to change the encoding.

For default values, the best approach would be better documentation for Verovio. Suggestions and help on what to provide and where to put it are welcome.

@craigsapp
Copy link
Contributor Author

For the single-note underline, the best case is to have verovio print a warning message which gives the encoder or downstream user feedback on problematic encodings.

@lpugin
Copy link
Contributor

lpugin commented Sep 15, 2016

Done here 9f83aa9. The best would be to write a Schematron rule for this.

@lpugin lpugin closed this as completed Sep 15, 2016
@pe-ro
Copy link

pe-ro commented Sep 15, 2016

Is there an MEI feature request is this somewhere?

@lpugin
Copy link
Contributor

lpugin commented Sep 15, 2016

No. Do you think it is possible to have Schematron rule for this? If yes I'll create the issue.

@pe-ro
Copy link

pe-ro commented Sep 15, 2016

Perhaps, but what exactly is the problem. Forgive me, but I seem to be listening too slow. :-)

@lpugin
Copy link
Contributor

lpugin commented Sep 16, 2016

The problem is that a @con="u" represents the beginning of an extender that goes from the current syllable/note to the note before the next syllable. If the note after the current note has already a new syllable (or if the note is the last note of the piece), then we end up with an extender under a single note, which does not really makes sense, at least in modern practice.

@pe-ro
Copy link

pe-ro commented Nov 29, 2016

Raising a warning for the simultaneous use of @con="u" and @wordpos="i" or "m" is relatively easy, but preventing the next note after one with @con="u" from having a syllable is not, given the fact that staves, layers, and verses may or may not be numbered. The following works well enough, but it can be subverted by wily encoders. 😄

If someone can figure out a way to make this shorter/more efficient, please speak up.

I've attached an RNG with these rules baked in. Let me know about any issues with it. Unless I hear otherwise, I'll add these rules in MEI development.

LyricConnectorTest.zip

<!-- Match syl[@con] with numbered verses, layers, and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_1">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0"
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
    context="mei:syl[@con and ancestor::mei:verse[@n] and 
ancestor::mei:layer[@n] and ancestor::mei:staff[@n]]">
    <sch:let name="staff" value="ancestor::mei:staff/@n"/>
    <sch:let name="layer" value="ancestor::mei:layer/@n"/>
    <sch:assert role="warning" test="not(@wordpos ne 't')">An underline is normally 
used only for a monosyllabic word or the final syllable of a multi-syllabic 
word.</sch:assert>
    <sch:assert test="following::mei:note[ancestor::mei:layer[@n=$layer] and
ancestor::mei:staff[@n=$staff]]">The last note of the piece in staff 
<sch:value-of select="$staff + 1"/>, layer <sch:value-of select="$layer + 1"/> 
can't have a syllable with a @con attribute.</sch:assert>
  </sch:rule>
</pattern>

<!-- Match syl[@con] with unnumbered verses, layers, and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_2">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0" 
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
    context="mei:syl[@con and not(ancestor::mei:verse[@n] and 
ancestor::mei:layer[@n] and ancestor::mei:staff[@n])]">
    <sch:let name="staff" value="count(ancestor::mei:staff/preceding-sibling::mei:staff)"/>
    <sch:let name="layer" value="count(ancestor::mei:layer/preceding-sibling::mei:layer)"/>
    <sch:let name="verse" value="count(ancestor::mei:verse/preceding-sibling::mei:verse)"/>
    <sch:assert role="warning" test="not(@wordpos ne 't')">An underline is normally 
used only for a monosyllabic word or the final syllable of a multi-syllabic 
word.</sch:assert>
    <sch:assert test="following::mei:note[ancestor::mei:layer[count(preceding-sibling::mei:layer) 
= $layer] and ancestor::mei:staff[count(preceding-sibling::mei:staff) = $staff]]"
>The last note of the piece in staff <sch:value-of select="$staff + 1"/>, layer 
<sch:value-of select="$layer + 1"/> can't have a syllable with a @con attribute.</sch:assert>
  </sch:rule>
</pattern>

<!-- Match syl[@con='u'] with numbered verses, layers, and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_3">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0"
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
    context="mei:syl[@con='u' and ancestor::mei:verse[@n] and 
ancestor::mei:layer[@n] and ancestor::mei:staff[@n]]">
    <sch:let name="staff" value="ancestor::mei:staff/@n"/>
    <sch:let name="layer" value="ancestor::mei:layer/@n"/>
    <sch:let name="verse" value="ancestor::mei:verse/@n"/>
    <sch:assert role="warning" test="not(following::mei:note[ancestor::mei:staff/@n=$staff 
and ancestor::mei:layer/@n=$layer][1]//mei:verse[@n=$verse]/mei:syl)">Next note in 
the same staff, same layer, and same verse can't have a new syllable when this note has 
a syllable with @con='u'.</sch:assert>
  </sch:rule>
</pattern>

<!-- Match syl[@con='u'] with unnumbered verses, layers, and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_4">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0"
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
    context="mei:syl[@con='u' and not(ancestor::mei:verse[@n] and 
ancestor::mei:layer[@n] and ancestor::mei:staff[@n])]">
    <sch:let name="staff" value="count(ancestor::mei:staff/preceding-sibling::mei:staff)"/>
    <sch:let name="layer" value="count(ancestor::mei:layer/preceding-sibling::mei:layer)"/>
    <sch:let name="verse" value="count(ancestor::mei:verse/preceding-sibling::mei:verse)"/>
    <sch:assert role="warning" test="not(following::mei:note[ancestor::mei:staff[
count(preceding-sibling::mei:staff)=$staff] 
and ancestor::mei:layer[count(preceding-sibling::mei:layer)=$layer]][1]//
mei:verse[count(preceding-sibling::mei:verse)=$verse]/mei:syl)">Next note in the same 
staff, same layer, and same verse can't have a new syllable when this note has a syllable 
with @con='u'.</sch:assert>
  </sch:rule>
</pattern>

<!-- Match syl[@con='u'] with numbered verses, but unnumbered layers and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_5">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0"
  xmlns:sch="http://purl.oclc.org/dsdl/schematron"
  xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
  xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
  context="mei:syl[@con='u' and ancestor::mei:verse[@n] and 
not(ancestor::mei:layer[@n] and ancestor::mei:staff[@n])]">
    <sch:let name="staff" value="count(ancestor::mei:staff/preceding-sibling::mei:staff)"/>
    <sch:let name="layer" value="count(ancestor::mei:layer/preceding-sibling::mei:layer)"/>
    <sch:let name="verse" value="ancestor::mei:verse/@n"/>
    <sch:assert role="warning" test="not(following::mei:note[ancestor::mei:staff[
count(preceding-sibling::mei:staff)=$staff] and 
ancestor::mei:layer[count(preceding-sibling::mei:layer)=$layer]][1]//
mei:verse[@n=$verse]/mei:syl)">Next note in the same staff, same layer, and same verse 
can't have a new syllable when this note has a syllable with @con='u'.</sch:assert>
  </sch:rule>
</pattern>

<!-- Match syl[@con='u'] with unnumbered verses, but numbered layers and staves -->
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="syl_connector_test_6">
  <sch:rule xmlns:rng="http://relaxng.org/ns/structure/1.0"
    xmlns:sch="http://purl.oclc.org/dsdl/schematron"
    xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
    xmlns="http://www.tei-c.org/ns/1.0" xmlns:math="http://exslt.org/math"
    context="mei:syl[@con='u' and ancestor::mei:layer[@n] and 
ancestor::mei:staff[@n] and not(ancestor::mei:verse[@n])]">
    <sch:let name="staff" value="ancestor::mei:staff/@n"/>
    <sch:let name="layer" value="ancestor::mei:layer/@n"/>
    <sch:let name="verse" value="count(ancestor::mei:verse/preceding-sibling::mei:verse)"/>
    <sch:assert role="warning" test="not(following::mei:note[ancestor::mei:staff/@n=$staff and 
ancestor::mei:layer/@n=$layer][1]//mei:verse[count(preceding-sibling::mei:verse)=$verse]/mei:syl)"
>Next note in the same staff, same layer, and same verse can't have a new syllable when this note 
has a syllable with @con='u'.</sch:assert>
  </sch:rule>
</pattern>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants