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
657 stars 181 forks source link

MusicXML to MIDI: Full measure rest duration is ignored in partial measures #3146

Open bryantgeorge opened 1 year ago

bryantgeorge commented 1 year ago

Describe the problem Rests with the measure="yes" attribute have their duration ignored during MIDI conversion.

To Reproduce Convert the attached musicxml data to MIDI

Expected behavior The converted MIDI should play the music in the top staff (two quarters, then a whole note without any rest between)

Input data

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="3.1">
  <identification>
    <encoding>
      <software>MuseScore 3.6.2</software>
      <encoding-date>2022-12-01</encoding-date>
      <supports element="accidental" type="yes"/>
      <supports element="beam" type="yes"/>
      <supports element="print" attribute="new-page" type="yes" value="yes"/>
      <supports element="print" attribute="new-system" type="yes" value="yes"/>
      <supports element="stem" type="yes"/>
      </encoding>
    </identification>
  <defaults>
    <scaling>
      <millimeters>6.99912</millimeters>
      <tenths>40</tenths>
      </scaling>
    <page-layout>
      <page-height>1697.36</page-height>
      <page-width>1200.15</page-width>
      <page-margins type="even">
        <left-margin>85.7251</left-margin>
        <right-margin>85.7251</right-margin>
        <top-margin>85.7251</top-margin>
        <bottom-margin>85.7251</bottom-margin>
        </page-margins>
      <page-margins type="odd">
        <left-margin>85.7251</left-margin>
        <right-margin>85.7251</right-margin>
        <top-margin>85.7251</top-margin>
        <bottom-margin>85.7251</bottom-margin>
        </page-margins>
      </page-layout>
    <word-font font-family="Edwin" font-size="10"/>
    <lyric-font font-family="Edwin" font-size="10"/>
    </defaults>
  <part-list>
    <score-part id="P1">
      <part-name>Piano</part-name>
      <score-instrument id="P1-I1">
        <instrument-name></instrument-name>
        </score-instrument>
      <midi-device id="P1-I1" port="1"></midi-device>
      <midi-instrument id="P1-I1">
        <midi-channel>1</midi-channel>
        <midi-program>1</midi-program>
        <volume>78.7402</volume>
        <pan>0</pan>
        </midi-instrument>
      </score-part>
    <score-part id="P2">
      <part-name>Piano</part-name>
      <score-instrument id="P2-I1">
        <instrument-name></instrument-name>
        </score-instrument>
      <midi-device id="P2-I1" port="1"></midi-device>
      <midi-instrument id="P2-I1">
        <midi-channel>2</midi-channel>
        <midi-program>1</midi-program>
        <volume>78.7402</volume>
        <pan>0</pan>
        </midi-instrument>
      </score-part>
    </part-list>
  <part id="P1">
    <measure number="0" implicit="yes" width="216.37">
      <print>
        <system-layout>
          <system-margins>
            <left-margin>62.15</left-margin>
            <right-margin>520.15</right-margin>
            </system-margins>
          <top-system-distance>70.00</top-system-distance>
          </system-layout>
        </print>
      <attributes>
        <divisions>1</divisions>
        <key>
          <fifths>0</fifths>
          </key>
        <time>
          <beats>4</beats>
          <beat-type>4</beat-type>
          </time>
        <clef>
          <sign>G</sign>
          <line>2</line>
          </clef>
        </attributes>
      <note default-x="82.52" default-y="-20.00">
        <pitch>
          <step>B</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <stem>up</stem>
        </note>
      <note default-x="148.55" default-y="-20.00">
        <pitch>
          <step>B</step>
          <octave>4</octave>
          </pitch>
        <duration>1</duration>
        <voice>1</voice>
        <type>quarter</type>
        <stem>up</stem>
        </note>
      </measure>
    <measure number="1" width="230.03">
      <note default-x="13.00" default-y="-20.00">
        <pitch>
          <step>B</step>
          <octave>4</octave>
          </pitch>
        <duration>4</duration>
        <voice>1</voice>
        <type>whole</type>
        </note>
      <barline location="right">
        <bar-style>light-heavy</bar-style>
        </barline>
      </measure>
    </part>
  <part id="P2">
    <measure number="0" implicit="yes" width="216.37">
      <print>
        <staff-layout number="1">
          <staff-distance>65.00</staff-distance>
          </staff-layout>
        </print>
      <attributes>
        <divisions>1</divisions>
        <key>
          <fifths>0</fifths>
          </key>
        <time>
          <beats>4</beats>
          <beat-type>4</beat-type>
          </time>
        <clef>
          <sign>G</sign>
          <line>2</line>
          </clef>
        </attributes>
      <note>
        <rest measure="yes"/>
        <duration>2</duration>
        <voice>1</voice>
        </note>
      </measure>
    <measure number="1" width="230.03">
      <note>
        <rest measure="yes"/>
        <duration>4</duration>
        <voice>1</voice>
        </note>
      <barline location="right">
        <bar-style>light-heavy</bar-style>
        </barline>
      </measure>
    </part>
  </score-partwise>

Screenshots Currently, the exported MIDI plays like the following (ie. adds 2 beats of rest):

image
craigsapp commented 1 year ago

Here is your example converted into MEI then SVG with verovio:

Screen Shot 2022-12-01 at 2 50 02 PM
Click to view MEI conversion ```xml <respStmt /> </titleStmt> <pubStmt><date isodate="2022-12-01" type="encoding-date">2022-12-01</date> </pubStmt> </fileDesc> <encodingDesc xml:id="encodingdesc-x7t5mr"> <appInfo xml:id="appinfo-omp0tt"> <application xml:id="application-1ahux2k" isodate="2022-12-01T14:46:29" version="3.13.0-dev-9c1b56b"> <name xml:id="name-hgezmu">Verovio</name> <p xml:id="p-1gks1vn">Transcoded from MusicXML</p> </application> </appInfo> </encodingDesc> </meiHead> <music> <body> <mdiv xml:id="m1n9iv8y"> <score xml:id="s1citmu2"> <scoreDef xml:id="s1gfkeol"> <staffGrp xml:id="s17qgkof"> <staffDef xml:id="P1" n="1" lines="5" ppq="1"> <label xml:id="l1cua5ul">Piano</label> <instrDef xml:id="isoec87" midi.channel="0" midi.instrnum="0" midi.volume="78.00%" /> <clef xml:id="c1yacit0" shape="G" line="2" /> <keySig xml:id="k8pwptm" sig="0" /> <meterSig xml:id="m12neotm" count="4" unit="4" /> </staffDef> <staffDef xml:id="P2" n="2" lines="5" ppq="1"> <label xml:id="ltqypia">Piano</label> <instrDef xml:id="ia8nndo" midi.channel="1" midi.instrnum="0" midi.volume="78.00%" /> <clef xml:id="c1gzgt7" shape="G" line="2" /> <keySig xml:id="ke5vzki" sig="0" /> <meterSig xml:id="m1r87p6y" count="4" unit="4" /> </staffDef> </staffGrp> </scoreDef> <section xml:id="sndx7vb"> <measure xml:id="m1cd4v1h" n="0"> <mNum xml:id="m1eowpzd" /> <staff xml:id="s10338t9" n="1"> <layer xml:id="ldiee0n" n="1"> <note xml:id="nadpvp4" dur.ppq="1" dur="4" oct="4" pname="b" stem.dir="up" /> <note xml:id="n1o9db60" dur.ppq="1" dur="4" oct="4" pname="b" stem.dir="up" /> </layer> </staff> <staff xml:id="ssm4x82" n="2"> <layer xml:id="l13g1irb" n="1"> <mRest xml:id="m8wcxrb" /> </layer> </staff> </measure> <measure xml:id="m13580fs" right="end" n="1"> <staff xml:id="sa0nqn" n="1"> <layer xml:id="llmdhxj" n="1"> <note xml:id="n1ny9zhc" dur.ppq="4" dur="1" oct="4" pname="b" /> </layer> </staff> <staff xml:id="sbs292s" n="2"> <layer xml:id="l1jv7tw7" n="1"> <mRest xml:id="mhs5ul" /> </layer> </staff> </measure> </section> </score> </mdiv> </body> </music> </mei> ``` </details> <p>And here is the MIDI rendering from MEI with verovio, which is playing as you describe: <a href="https://github.com/rism-digital/verovio/files/10136739/example.zip">example.zip</a></p> <p>This is a correct rendering once converted to MEI. The problem is that the first rest in the bottom staff:</p> <pre><code class="language-xml"> <note> <rest measure="yes"/> <duration>2</duration> <voice>1</voice> </note></code></pre> <p>is given a duration of 2 quarter notes, while the full measure is in 4/4 (4 quarter notes).</p> <p>The <code>measure@implicit="yes"</code> indicates a pickup measure:</p> <p><a href="https://www.w3.org/2021/06/musicxml40/musicxml-reference/elements/measure-partwise">https://www.w3.org/2021/06/musicxml40/musicxml-reference/elements/measure-partwise</a></p> <blockquote> <p>Set to "yes" for measures where the measure number should never appear, such as pickup measures and the last half of mid-measure repeats. The value is "no" if not specified.</p> </blockquote> <p>This rest must be displayed as a half-note rest, so such rests cannot be converted to <code><mRest></code> in MEI and must instead be converted as <code>note@dur="2"</code>. This must be identified by observing that <code>measure@implicit</code> is set to <code>yes</code>, and that the <code><meterSig></code> does not match the given duration of the rest.</p> <p>In theory the <code><mRest></code> could be given a half-note duration, but this would still result in an incorrect rendering to SVG as a whole-note rest (but the MIDI rendering would be correct).</p> <hr /> <p>Alternatively, the <code><mRest></code> can be given a duration of "2" (half note), but the problem is that such a rest should be displayed as whole rests, which is incorrect since it must be displayed as a half-rest. Encoding as <code>mRest@dur="2"</code> is legal MEI but is currently ignored by verovio (it only checks the <code><meterSig></code>).</p> </div> </div> <div class="page-bar-simple"> </div> <div class="footer"> <ul class="body"> <li>© <script> document.write(new Date().getFullYear()) </script> Githubissues.</li> <li>Githubissues is a development platform for aggregating issues.</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script> <script src="/githubissues/assets/js.js"></script> <script src="/githubissues/assets/markdown.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/languages/go.min.js"></script> <script> hljs.highlightAll(); </script> </body> </html>