Closed peterkorgaard closed 5 years ago
Strange. When I encode it, the placement is correct:
I am getting the same problem as you when trying to render your encoding.
My encoding is below, which looks similar to yours (and changing things do not break it so far, such as moving meter.units to scoreDef, or removing the rend on the harm data):
<?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-01-30T11:51:00" version="2.1.0-dev-56b5535-dirty">
<name>Verovio</name>
<p>Transcoded from Humdrum</p>
</application>
</appInfo>
</encodingDesc>
<workList>
<work>
<title />
</work>
</workList>
</meiHead>
<music>
<body>
<mdiv xml:id="mdiv-0000000518650985">
<score xml:id="score-0000000375403176">
<scoreDef xml:id="scoredef-0000000310725454">
<staffGrp xml:id="staffgrp-0000000941074021">
<staffDef xml:id="staffdef-0000000677658184" clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5">
<label xml:id="label-0000001077812367" />
</staffDef>
</staffGrp>
</scoreDef>
<section xml:id="section-L1F1">
<measure xml:id="measure-L4">
<staff xml:id="staff-L4F1N1" n="1">
<layer xml:id="layer-L4F1N1" n="1">
<note xml:id="note-L5F1" dur="4" oct="4" pname="b" accid.ges="n" />
<beam xml:id="beam-L6F1-L9F1">
<note xml:id="note-L6F1" dur="16" oct="4" pname="b" accid.ges="n" />
<note xml:id="note-L7F1" dur="16" oct="4" pname="b" accid.ges="n" />
<note xml:id="note-L8F1" dur="16" oct="4" pname="b" accid.ges="n" />
<note xml:id="note-L9F1" dur="16" oct="4" pname="b" accid.ges="n" />
</beam>
<beam xml:id="beam-L10F1-L11F1">
<note xml:id="note-L10F1" dots="1" dur="8" oct="4" pname="b" accid.ges="n" />
<note xml:id="note-L11F1" dur="16" oct="4" pname="b" accid.ges="n" />
</beam>
<note xml:id="note-L12F1" dur="4" oct="4" pname="b" accid.ges="n" />
</layer>
</staff>
<harm xml:id="harm-L5F2" staff="1" tstamp="1.000000">1</harm>
<harm xml:id="harm-L6F2" staff="1" tstamp="2.000000">2</harm>
<harm xml:id="harm-L10F2" staff="1" tstamp="3.000000">3</harm>
<harm xml:id="harm-L12F2" staff="1" tstamp="4.000000">4</harm>
</measure>
<measure xml:id="measure-L13" right="dbl">
<staff xml:id="staff-L13F1N1" n="1">
<layer xml:id="layer-L13F1N1" n="1">
<beam xml:id="beam-L14F1-L15F1">
<note xml:id="note-L14F1" dots="1" dur="8" oct="4" pname="b" accid.ges="n" />
<note xml:id="note-L15F1" dur="16" oct="4" pname="b" accid.ges="n" />
</beam>
<rest xml:id="rest-L16F1" dur="4" />
<note xml:id="note-L17F1" dur="2" oct="4" pname="b" accid.ges="n" />
</layer>
</staff>
<harm xml:id="harm-L14F2" staff="1" tstamp="1.000000">1</harm>
<harm xml:id="harm-L16F2" staff="1" tstamp="2.000000">2</harm>
<harm xml:id="harm-L17F2" staff="1" tstamp="3.000000">3</harm>
<harm xml:id="harm-L18F2" staff="1" tstamp="4.000000">4</harm>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
I rendered your code and everything looks fine for me too. So, it looks like I need to find the key difference between the two encodings. It is a little peculiar, though. I have never experienced this before.
Thanks. I'll give an update when I'm wiser.
@peterkorgaard The duration of your first note in the second measure is "4"
instead of "8".
<note xml:id="dfc13a7e-bdf1-4fd0-b6ed-427ef562c52b" dots="1" dur="4" oct="4" pname="b"></note>
Changing it to "8"
should do the trick.
You're absolutely right. It's an obvious mistake, but I didn't see it because all the notes somehow rendered correctly. Thanks a lot. I'm very grateful.
No worries, such things can happen a lot.
@lpugin Is there any mechanism to detect metrical incongruency automatically and then display, e.g., a warning?
Is there any mechanism to detect metrical incongruency automatically
That would be a useful feature, but is not yet available in verovio.
In verovio it should be implemented as some sort of warning that all <staff>
elements of a <measure>
do not have the same duration (and in addition, maybe check that all <layer>
in a staff have the same duration). Here is an example of a measure that has an unequal duration between the staves (because I deleted one note in the bottom staff):
Verovio will not print a warning message in such cases, but it would probably be useful to report that the measure is either under or over full (and it should be something that verovio is already aware of). If someone wanted the above rendering, then they should add a <space>
(invisible rest) to indicate that is what they really want (and not a data error).
The problem is that there will be pickup measures and repeats that split full measures of music, so reporting an inconsistency with the prevailing meter would be beyond the scope of verovio. So in the case of a single staff (as in this case), it would be harder to detect the error, and beyond the scope of typesetting the music.
This would be more of a schematron feature for comparing the duration of the measure to the one expected by the time signature.
This can also be done currently by converting the MEI data into Humdrum and then summing the durations of each measure:
mei2hum file.mei | beat -s
which produces this output:
**beatsum
*M4/4
4.75
=1
4.75
=
*-
or to see along with the original data:
mei2hum file.mei | beat -as
**kern **beatsum
*part1 *
*staff1 *
*clefG2 *
*M4/4 *M4/4
4b 4.75
16bL .
16b .
16b .
16bJ .
4.b .
16b .
4b .
=1 =1
4.b 4.75
16b .
4r .
2b .
= =
*- *-
In this case both measures are 4.75 beats long instead of the expected 4.
Test data for the above rendering:
<?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-01-30T19:27:57" version="2.0.0-dev-bd2039c">
<name>Verovio</name>
<p>Transcoded from Humdrum</p>
</application>
</appInfo>
</encodingDesc>
<workDesc>
<work>
<titleStmt>
<title />
</titleStmt>
</work>
</workDesc>
</meiHead>
<music>
<body>
<mdiv xml:id="mdiv-0000001190257153">
<score xml:id="score-0000000841798666">
<scoreDef xml:id="scoredef-0000000454304434">
<staffGrp xml:id="staffgrp-0000001122750840" symbol="brace" bar.thru="true">
<label xml:id="label-0000001045322484" />
<staffDef xml:id="staffdef-0000001261663736" clef.shape="G" clef.line="2" meter.count="4" meter.unit="4" n="1" lines="5" />
<staffDef xml:id="staffdef-0000000540853942" clef.shape="F" clef.line="4" meter.count="4" meter.unit="4" n="2" lines="5" />
</staffGrp>
</scoreDef>
<section xml:id="section-L1F1">
<measure xml:id="measure-L3" n="1">
<staff xml:id="staff-L3F2N1" n="1">
<layer xml:id="layer-L3F2N1" n="1">
<note xml:id="note-L4F2" dur="4" oct="4" pname="c" accid.ges="n" />
<note xml:id="note-L5F2" dur="4" oct="4" pname="c" accid.ges="n" />
<note xml:id="note-L6F2" dur="4" oct="4" pname="c" accid.ges="n" />
<note xml:id="note-L7F2" dur="4" oct="4" pname="c" accid.ges="n" />
</layer>
</staff>
<staff xml:id="staff-L3F1N1" n="2">
<layer xml:id="layer-L3F1N1" n="1">
<note xml:id="note-L4F1" dur="4" oct="3" pname="c" accid.ges="n" />
<note xml:id="note-L5F1" dur="4" oct="3" pname="c" accid.ges="n" />
<note xml:id="note-L6F1" dur="4" oct="3" pname="c" accid.ges="n" />
</layer>
</staff>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
@musicEnfanthen not in Verovio. But maybe it can be done with Schematron as @craigsapp is suggesting it?
And/or you can write an XSLT to do it 😄
The basic algorithm is:
(1) use xpath to extra list of scoreDefs and measures (presuming measured music)
(2) use xpath to extract layers from the measures
(3) iterate through the layers accumulating durations from children elements
(4) compare the duration of all layers to each other and issue a warning if they do not all match. A variation would be to find the max duration for each staff and then compare them, if you want to allow underfull layers on a staff that is otherwise complete.
number 3 is the most complicated, having these complications:
(1) use @dur.ges
when present instead of @dur
. Use @dots.ges
when present instead of @dots
.
(2) when in a tuplet, apply the tuplet@num
and tuplet@numbase
to scale the visual duration of the durational element inside the tuplet. Tuplets can be nested, so if you use xpath to select durational items in a layer (notes, rests, mRests, multiRests, spaces), you would need to trace back in the ancestors of the durational element until you hit the layer level to apply all tuplet modications to the duration.
(3) mRest and multiRest take their duration from the prevailing time signature (so you can ignore them if you are searching for over/under filled measures).
(4) the biggest complication for a generalized tool would be tupletSpan. These function like tuplets but behave like slurs, in that they are outside of the layer/staff and are floating elements at the measure level. In theory these should be rare, but they are still quite common in the sample encoding dataset (16 out of 86 files):
https://github.com/music-encoding/sample-encodings/tree/master/MEI_4.0/Music/Complete_examples
Beethoven_op.18.mei
Borodin_StringTrio_g.mei
Brahms_StringQuartet_Op51_No1.mei
Chopin_Etude_op.10_no.9.mei
Chopin_Mazurka.mei
Debussy_Golliwogg'sCakewalk.mei
Hummel_Concerto_for_trumpet.mei
Hummel_op.67_No.11.mei
Liszt_Four_little_pieces.mei
Mahler_Song.mei
Mozart_Quintett.mei
Mozart_Quintett_2013.mei
Schubert_Lindenbaum.mei
Schumann_Op.41.mei
Telemann_Concert.mei
Weber_Arie.mei
tupletSpan should only be needed (like beamSpan) when a tuplet group crosses the element hierarchy (such as across measures), so most (probably all) uses of the tupletSpan in the above files is not necessary. There are also numerical errors related to tupletspans in the above data caused by the musicxml2mei converting XSLT program. Having such a tool would help identify the locations of those errors for hand-correcting. (ideally the musicxml2mei converter would be fixed, and then re-run on the source encoding, but the source encodings are not part of the repository).
This issue is identified using version 2.0.0.
The example below has added harm on each beat in both measures - tstamp 1, 2, 3 and 4. When harm follows a dotted note it displays on an incorrect location.