Open earboxer opened 4 years ago
The problem here is that a <type>quarter</type>
is missing in the musicXML (which is correct I guess) and even though the <duration>
is correctly given as 4 units (thus a quarter note), an mRest
is inserted.
`// we assume /note without /type or with duration of an entire bar to be mRest
else if (typeStr.empty() || duration == (m_ppq * 4 * m_meterCount / m_meterUnit)
|| HasAttributeWithValue(rest.node(), "measure", "yes")) {`
It should be: (typeStr.empty() && duration == (m_ppq * 4 * m_meterCount / m_meterUnit)) ...
shouldn't it, @rettinghaus?
@wergo the condition is correct. If you reimport the file into MuseScore (where it came from), it shows a whole measure rest too.
Should we really base an argument on the MusicXML import capabilities of MuseScore, that often that it is faulty?
The xml pertinent snipped is this (with <division>
defined as 4 earlier):
<measure number="4" width="171.46">
<print new-system="yes"/>
<note>
<rest/>
<duration>4</duration>
<voice>1</voice>
</note>
</measure>
So, the <duration>
element correctly specifies a quarter note, even though <type>quarter</type>
is missing. Shouldn't that import correctly as a quarter-note rest?
The musicxml specifies a whole measure rest (because type is undefined), and the whole measure is 1 quarter-note long.
So I think we should create an mRest with dur and dur.ppq set appropriately...
Putting @dur.ppq
on mRest
wouldn't resolve the issue (as it is not implemented for mRest).
And even then the same error would prevail on MEI files (that don't have a @dur.ppq
on mRest
).
The calculation of mRest
duration has to be improved.
@lpugin this is not an MusicXML issue, but one about mRest duration calculation.
(The MEI posted in #1481 does not contain any mRest
.)
The result of the MusicXML conversion of the example above leaves me doubtful:
<measure xml:id="measure-0000000347293321" right="invis" n="3">
<staff xml:id="staff-0000000269333995" n="1">
<layer xml:id="layer-0000000010344056" n="1">
<note xml:id="note-0000001551771701" dur.ppq="8" dur="2" oct="4" pname="g" stem.dir="up">
<verse xml:id="verse-0000000177835352" n="1">
<syl xml:id="syl-0000000247952080" con="d" wordpos="i">heav</syl>
</verse>
</note>
<note xml:id="note-0000000232489823" dur.ppq="4" dur="4" oct="4" pname="e" stem.dir="up">
<verse xml:id="verse-0000000941134656" n="1">
<syl xml:id="syl-0000001224484950" con="s" wordpos="t">en,</syl>
</verse>
</note>
</layer>
<layer xml:id="layer-0000000452441359" n="2">
<note xml:id="note-0000001851782662" dur.ppq="8" dur="2" oct="4" pname="e" stem.dir="down" />
<note xml:id="note-0000001886512702" dur.ppq="4" dur="4" oct="4" pname="c" stem.dir="down" />
</layer>
</staff>
<staff xml:id="staff-0000000494954418" n="2">
<layer xml:id="layer-0000000075432589" n="1">
<note xml:id="note-0000000324438461" dur.ppq="8" dur="2" oct="4" pname="c" stem.dir="up" />
<note xml:id="note-0000001459657811" dur.ppq="4" dur="4" oct="3" pname="g" stem.dir="up" />
</layer>
<layer xml:id="layer-0000000430161242" n="2">
<note xml:id="note-0000000937456504" dur.ppq="8" dur="2" oct="3" pname="c" stem.dir="down" />
<note xml:id="note-0000001052792774" dur.ppq="4" dur="4" oct="3" pname="c" stem.dir="down" />
</layer>
</staff>
</measure>
<sb xml:id="sb-0000000828106355" />
<measure xml:id="measure-0000001298228642" n="4">
<staff xml:id="staff-0000000890427094" n="1">
<layer xml:id="layer-0000000777033468" n="1">
<beam xml:id="beam-0000000906894824">
<note xml:id="note-0000001327870263" dots="1" dur.ppq="3" dur="8" oct="4" pname="g" stem.dir="up">
<verse xml:id="verse-0000000829096040" n="1">
<syl xml:id="syl-0000000336840856" con="s">what</syl>
</verse>
</note>
<note xml:id="note-0000000744896718" dur.ppq="1" dur="16" oct="4" pname="g" stem.dir="up">
<verse xml:id="verse-0000000803708960" n="1">
<syl xml:id="syl-0000001374662137" con="s">a</syl>
</verse>
</note>
</beam>
</layer>
</staff>
<staff xml:id="staff-0000001747086282" n="2">
<layer xml:id="layer-0000001383504811" n="1">
<mRest xml:id="mrest-0000000479382709" />
</layer>
</staff>
</measure>
So, yes, the mRest calcutation in the MIDI output is wrong, but before we tweak it we need to make sure that this is an appropriate MEI encoding. I am not.
Consider the following example. The length of each measure changes. Adding notes works fine, but removing them adds an extra pause from the mRest in the second line. (Note, that no meter is given!) The problem in #1481 basically is the same: We have something that looks like a whole measure, while the @dur.ppq
value tells something different, but is getting ignored.
<?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"?>
<?xml-model href="https://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 />
<respStmt />
</titleStmt>
<pubStmt />
</fileDesc>
</meiHead>
<music>
<body>
<mdiv>
<score>
<scoreDef>
<staffGrp>
<staffDef n="1" lines="5" ppq="1" clef.shape="G" clef.line="2" key.sig="2s">
<label>Violin</label>
</staffDef>
<staffDef n="2" lines="5" ppq="1" clef.shape="G" clef.line="2" key.sig="2s">
<label>Violin</label>
</staffDef>
</staffGrp>
</scoreDef>
<section>
<pb />
<measure>
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="4" pname="c" accid.ges="s" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<rest dur.ppq="1" dur="4" />
</layer>
</staff>
<tempo place="above" staff="1" tstamp="1.000000" mm="92" mm.unit="4" />
</measure>
<measure n="1">
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="4" pname="d" />
<note dur.ppq="1" dur="4" oct="4" pname="f" accid.ges="s" />
<note dur.ppq="1" dur="4" oct="4" pname="a" />
<note dur.ppq="1" dur="4" oct="4" pname="b" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<mRest />
</layer>
</staff>
</measure>
<measure n="2">
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="4" pname="a" />
<note dur.ppq="1" dur="4" oct="4" pname="f" accid.ges="s" />
<note dur.ppq="1" dur="4" oct="4" pname="d" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<mRest />
</layer>
</staff>
</measure>
<measure n="3">
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="4" pname="e" />
<note dur.ppq="1" dur="4" oct="4" pname="g" />
<note dur.ppq="1" dur="4" oct="4" pname="b" />
<note dur.ppq="1" dur="4" oct="5" pname="d" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<mRest />
</layer>
</staff>
</measure>
<measure n="4">
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="5" pname="f" accid.ges="s" />
<note dur.ppq="1" dur="4" oct="5" pname="a" />
<note dur.ppq="1" dur="4" oct="5" pname="f" accid.ges="s" />
<note dur.ppq="1" dur="4" oct="5" pname="d" />
<note dur.ppq="1" dur="4" oct="4" pname="b" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<mRest />
</layer>
</staff>
</measure>
<measure n="5" metcon="false">
<staff n="1">
<layer n="1">
<note dur.ppq="1" dur="4" oct="4" pname="a" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<rest dur.ppq="1" dur="4" />
</layer>
</staff>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
NB: A general break however would have to rely on a given meter.
Yes, to make your example complete, I would expect to have
<scoreDef meter.unit="4" meter.count="3" meter.form="invis"/>
with appropriate values and whenever necessary, wouldn't you?
(PS there are no @dur.ppq
on mRest in your example)
(To help understanding)
To me it looks more like a <scoreDef meter.unit="4" meter.count="4" meter.form="invis"/>
. You could make these changes in meter explicit, but the meaning of mRest
in this example is unquestionable.
(PS there are @dur.ppq
on rest
in #1481)
As I said, "with appropriate values", so I gave the example for measure 2 (the measure with @n=2
) for which you complained that a gap was added. Sorry, I thought this was obvious.
(PS there are
@dur.ppq
on rest in #1481)
I am confused: are you talking about rest
or mRest
? For rest
, you can simply use @dur.ges
. This is the way to encode it - both MIDI and visual rendering are what I would expect:
<?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"?>
<?xml-model href="https://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 />
<respStmt />
</titleStmt>
<pubStmt />
</fileDesc>
</meiHead>
<music>
<body>
<mdiv>
<score>
<scoreDef>
<staffGrp>
<staffDef n="1" lines="5" ppq="1" clef.shape="G" clef.line="2" key.sig="2s">
<label>Violin</label>
</staffDef>
<staffDef n="2" lines="5" ppq="1" clef.shape="G" clef.line="2" key.sig="2s">
<label>Violin</label>
</staffDef>
</staffGrp>
</scoreDef>
<section>
<measure n="1">
<staff n="1">
<layer n="1">
<note dur="4" oct="4" pname="d" />
<note dur="4" oct="4" pname="f" accid.ges="s" />
<note dur="4" oct="4" pname="a" />
<note dur="4" oct="4" pname="b" />
</layer>
</staff>
<staff n="2">
<layer n="1">
<rest dur="1" dur.ges="4"/>
<note dur="2" dots="1" oct="4" pname="d" />
</layer>
</staff>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
Ok. I'm talking about mRests. And I see now, that #1481 is indeed a different problem, what I'll be thinking about.
Yes, to make your example complete, I would expect to have
<scoreDef meter.unit="4" meter.count="3" meter.form="invis"/>
You could make these changes in meter explicit, but the meaning of mRest in this example is unquestionable.
It might be unquestionable in that example, but what if the notes in measure n="1"
get removed. How could an improved mRest duration calculation handle this issue? Should it be 0 beats (probably not), 1 beat (likely), or 3 (the number of beats in the next measure)? It seems like either the mRest needs a duration or we need an invisible scoreDef to remove all possible ambiguity. (not that it means much, but for comparison, if you remove the duration from the rest in musicxml, and load it into MuseScore, they also have an unexpected pause in playback).
Since the MusicXML has the duration, I think we should try to use that. (Which would also make the conversion less lossy).
(This doesn't mean that we shouldn't try to improve mRest duration calculation, just know that doing so won't solve all potential issues.)
Next Steps:
In the following MEI file, there is an mRest in the bass clef of a shortened measure.
When the audio is played back, it pauses for three extra beats, so there is a gap of silence between "what a" and "day". Measure 4 should be only one beat long, so the mRest should only be 1 beats. (Though I don't know how it ought to know that).
This was converted from musicXML:
MusicXML
MEI