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

MIDI playback does not include the trill effect #3754

Closed
dajun-TT opened this issue Sep 2, 2024 · 2 comments
Closed

MIDI playback does not include the trill effect #3754

dajun-TT opened this issue Sep 2, 2024 · 2 comments

Comments

@dajun-TT
Copy link

dajun-TT commented Sep 2, 2024

Describe the problem
When performance markings are added to the sheet music, they do not produce the intended effect during playback. For example, after a trill symbol is marked, the playback does not include the trill effect, and so on.

@craigsapp
Copy link
Contributor

craigsapp commented Sep 2, 2024

Currently verovio export to MIDI does not realize trills (and also mordents, turns, <ftrem>, <mRpt> and <halfmRpt> (and two-bar repeats, which I am not testing below)). Note that <bTrem> (repeating the same note with tremolo notation) has been implemented. These ornamentations and notation abbreviations would be good to add to the MEI-to-MIDI conversion.

Ideally you should provide input data as mentioned previously, but in this case I will provide it:

Screenshot 2024-09-01 at 8 53 54 PM
Click to view MEI data for above example.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2024-09-01T20:53:59" version="4.3.0-dev-6e49bf7-dirty">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
 </meiHead>
 <music decls="#work1_encoded">
  <body>
   <mdiv xml:id="m1bkhba6">
    <score xml:id="sq5rkgg">
     <scoreDef xml:id="s1p85auf" tempo.dist="3.0000vu">
      <staffGrp xml:id="s6yyqgd">
       <staffDef xml:id="staffdef-L1F1" n="1" lines="5">
        <clef xml:id="clef-L2F1" shape="G" line="2" />
        <meterSig xml:id="metersig-L3F1" count="4" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1" n="1">
       <staff xml:id="staff-L1F1" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <note xml:id="note-L6F1" dur="4" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L7F1" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L8F1" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L9F1" dur="4" oct="4" pname="f" accid.ges="n" />
        </layer>
       </staff>
       <trill xml:id="trill-L6F1" staff="1" startid="#note-L6F1" />
       <dir xml:id="dir-L5F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="r2cayus" color="dodgerblue" fontstyle="normal">trills</rend>
       </dir>
       <trill xml:id="trill-L7F1" staff="1" startid="#note-L7F1" />
       <trill xml:id="trill-L8F1" staff="1" startid="#note-L8F1" />
       <trill xml:id="trill-L9F1" staff="1" startid="#note-L9F1" />
      </measure>
      <scoreDef xml:id="s4bm2cg">
       <staffGrp xml:id="sots1a0">
        <staffDef xml:id="s12qtl7a" n="1">
         <meterSig xml:id="m1mj5znb" count="4" unit="2" />
        </staffDef>
       </staffGrp>
      </scoreDef>
      <measure xml:id="measure-L10" n="2">
       <staff xml:id="staff-L10F1N1" n="1">
        <layer xml:id="layer-L10F1N1" n="1">
         <note xml:id="note-L12F1" dur="2" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L13F1" dur="2" oct="4" pname="d">
          <accid xml:id="accid-L13F1" type="caution" accid="n" func="caution" />
         </note>
         <note xml:id="note-L14F1" dur="2" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L15F1" dur="2" oct="4" pname="f">
          <accid xml:id="accid-L15F1" type="caution" accid="n" func="caution" />
         </note>
        </layer>
       </staff>
       <trill xml:id="trill-L12F1" staff="1" startid="#note-L12F1" accidupper="f" />
       <trill xml:id="trill-L13F1" staff="1" startid="#note-L13F1" />
       <trill xml:id="trill-L14F1" staff="1" startid="#note-L14F1" accidupper="s" />
       <trill xml:id="trill-L15F1" staff="1" startid="#note-L15F1" accidupper="f" />
      </measure>
      <scoreDef xml:id="s16cufm8">
       <staffGrp xml:id="s1sa7z6f">
        <staffDef xml:id="sriy7cl" n="1">
         <meterSig xml:id="m2a8ki4" count="4" unit="4" />
        </staffDef>
       </staffGrp>
      </scoreDef>
      <measure xml:id="measure-L16" n="3">
       <staff xml:id="staff-L16F1N1" n="1">
        <layer xml:id="layer-L16F1N1" n="1">
         <note xml:id="note-L19F1" dur="2" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L20F1" dur="2" oct="4" pname="d" accid.ges="n" />
        </layer>
       </staff>
       <turn xml:id="t1szxvuf" staff="1" startid="#note-L19F1" delayed="true" form="upper" />
       <dir xml:id="dir-L18F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="r18087gz" color="dodgerblue" fontstyle="normal">turns</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L21" n="4">
       <staff xml:id="staff-L21F1N1" n="1">
        <layer xml:id="layer-L21F1N1" n="1">
         <note xml:id="note-L22F1" dur="2" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L23F1" dur="2" oct="4" pname="d" accid.ges="n" />
        </layer>
       </staff>
       <turn xml:id="tsf3g7b" staff="1" startid="#note-L22F1" form="upper" />
      </measure>
      <measure xml:id="measure-L24" right="dbl" n="5">
       <staff xml:id="staff-L24F1N1" n="1">
        <layer xml:id="layer-L24F1N1" n="1">
         <note xml:id="note-L25F1" dur="2" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L26F1" dur="2" oct="4" pname="d">
          <accid xml:id="accid-L26F1" type="caution" accid="n" func="caution" />
         </note>
        </layer>
       </staff>
       <turn xml:id="t9c5u4y" staff="1" startid="#note-L25F1" accidupper="f" accidlower="f" delayed="true" form="upper" />
      </measure>
      <measure xml:id="measure-L27" right="dbl" n="6">
       <staff xml:id="staff-L27F1N1" n="1">
        <layer xml:id="layer-L27F1N1" n="1">
         <note xml:id="note-L29F1" dur="4" oct="4" pname="f" accid="s" />
         <note xml:id="note-L30F1" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L31F1" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L32F1" dur="4" oct="4" pname="f" accid.ges="s" />
        </layer>
       </staff>
       <mordent xml:id="mordent-L29F1" staff="1" startid="#note-L29F1" place="above" form="upper" />
       <dir xml:id="dir-L28F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="r1st0z6e" color="dodgerblue" fontstyle="normal">mordents</rend>
       </dir>
       <mordent xml:id="mordent-L30F1" staff="1" startid="#note-L30F1" place="above" form="upper" long="true" />
       <mordent xml:id="mordent-L31F1" staff="1" startid="#note-L31F1" place="above" form="lower" />
       <mordent xml:id="mordent-L32F1" staff="1" startid="#note-L32F1" place="above" form="upper" />
      </measure>
      <measure xml:id="measure-L33" n="7">
       <staff xml:id="staff-L33F1N1" n="1">
        <layer xml:id="layer-L33F1N1" n="1">
         <bTrem xml:id="btrem-L36F1-L43F1" unitdur="16">
          <note xml:id="note-L36F1" dur="2" oct="4" pname="c" accid.ges="n" />
         </bTrem>
         <fTrem xml:id="ftrem-L44F1-L51F1" beams="2" unitdur="16">
          <note xml:id="note-L44F1" dur="2" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L51F1" dur="2" oct="5" pname="c" accid.ges="n" />
         </fTrem>
        </layer>
       </staff>
       <dir xml:id="dir-L35F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="r9vuqz0" color="dodgerblue" fontstyle="normal">tremolos</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L53" n="8">
       <staff xml:id="staff-L53F1N1" n="1">
        <layer xml:id="layer-L53F1N1" n="1">
         <mRpt xml:id="mrpt-L54F1" num.visible="false" />
        </layer>
       </staff>
       <dir xml:id="dir-L56F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="rddys4w" color="dodgerblue" fontstyle="normal">repeat bar</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L75" n="9">
       <staff xml:id="staff-L75F1N1" n="1">
        <layer xml:id="layer-L75F1N1" n="1">
         <bTrem xml:id="btrem-L78F1-L85F1" unitdur="16">
          <note xml:id="note-L78F1" dur="2" oct="4" pname="c" accid.ges="n" />
         </bTrem>
         <halfmRpt xml:id="halfmrpt-L86F1" />
        </layer>
       </staff>
       <dir xml:id="dir-L77F1" place="below" staff="1" tstamp="1.000000" vgrp="2">
        <rend xml:id="r1ff7fa1" color="dodgerblue" fontstyle="normal">half-bar repeat</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L96" right="end" n="10">
       <staff xml:id="staff-L96F1N1" n="1">
        <layer xml:id="layer-L96F1N1" n="1">
         <fTrem xml:id="ftrem-L97F1-L104F1" beams="2" unitdur="16">
          <note xml:id="note-L97F1" dur="2" oct="4" pname="c" accid.ges="n" />
          <note xml:id="note-L104F1" dur="2" oct="5" pname="c" accid.ges="n" />
         </fTrem>
         <halfmRpt xml:id="halfmrpt-L105F1" />
        </layer>
       </staff>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

For proper rendering of ornamental notes, the tempo will need to be considered, as well as the rhythms of the notes.

A complication is that the chromatic alterations of ornamental notes will need to be inferred during the conversion process to MIDI, or some realization hint attributes will need to be added (created?) for the ornaments in order to create the correct intervals of the ornamentation notes (which is why they have not been implemented yet). This is beyond @accidupper/@accidlower since these will force an accidental to display on the ornament, but this accidental is typically not displayed when the performer is assumed to infer the ornamental pitch from the accidental states of that pitch in the key signature/measure.

So one possibility is to add new attributes to hide either or both of the @accidupper/@accidlower; otherwise, the chromatic alteration of the ornamental note(s) will have to be inferred from the key signature and previous chromatic alterations of the diatonic ornamental note previously in the measure.

As a side note: MusescoreXML (I think) and Humdrum encode the ornamental interval rather than the chromatic alteration of the ornamental note (and Dorico does this in its internal format). But then you still have complications in that you have to calculate the visual accidental(s) to display on the ornaments.

PlayScore is a good model of automatically rendering ornaments.


Here is an evil case:

Screenshot 2024-09-01 at 9 14 43 PM
Click to view MEI data for above example.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt>
    <unpub>This MEI file was created by Verovio's Humdrum converter. When published, this unpub element should be removed, and the enclosing pubStmt element should be properly filled out.</unpub>
   </pubStmt>
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2024-09-01T21:09:28" version="4.3.0-dev-6e49bf7-dirty">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <extMeta>
   <frames xmlns="http://www.humdrum.org/ns/humxml">
    <metaFrame n="9" token="!!!RDF**kern: > = above" xml:id="L10">
     <frameInfo>
      <startTime float="3" />
      <frameType>reference</frameType>
      <referenceKey>RDF**kern</referenceKey>
      <referenceValue>&gt; = above</referenceValue>
     </frameInfo>
    </metaFrame>
   </frames>
  </extMeta>
 </meiHead>
 <music decls="#work1_encoded">
  <body>
   <mdiv xml:id="m11heeh7">
    <score xml:id="s1f9vtq">
     <scoreDef xml:id="se1ziwc" tempo.dist="3.0000vu">
      <staffGrp xml:id="sgivrho" bar.thru="true" symbol="brace">
       <staffDef xml:id="staffdef-L1F2" n="1" lines="5">
        <clef xml:id="clef-L2F2" shape="G" line="2" />
        <meterSig xml:id="metersig-L3F2" count="3" unit="4" />
       </staffDef>
       <staffDef xml:id="staffdef-L1F1" n="2" lines="5">
        <clef xml:id="clef-L2F1" shape="F" line="4" />
        <meterSig xml:id="metersig-L3F1" count="3" unit="4" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1">
       <staff xml:id="staff-L1F2" n="1">
        <layer xml:id="layer-L1F2N1" n="1">
         <note xml:id="note-L4F2" dur="4" oct="4" pname="f" accid="s" />
         <note xml:id="note-L5F2" dur="4" oct="5" pname="c" accid="s" />
         <note xml:id="note-L7F2" dur="4" oct="5" pname="d" accid.ges="n" />
        </layer>
       </staff>
       <staff xml:id="staff-L1F1" n="2">
        <layer xml:id="layer-L1F1N1" n="1">
         <note xml:id="note-L4F1" dur="4" oct="4" pname="c" accid.ges="n" />
         <beam xml:id="beam-L5F1-L6F1" beam.with="below">
          <note xml:id="note-L5F1" type="placed" dur="8" oct="4" pname="c" stem.dir="up" accid.ges="n" />
          <note xml:id="note-L6F1" dur="8" staff="1" oct="4" pname="f" stem.dir="down" />
         </beam>
         <note xml:id="note-L7F1" dur="4" oct="4" pname="f" accid.ges="n" />
        </layer>
       </staff>
       <mordent xml:id="mordent-L6F1" staff="1" startid="#note-L6F1" place="within" form="upper" />
       <mordent xml:id="mordent-L7F1" staff="2" startid="#note-L7F1" place="above" form="upper" />
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

The ornamental notes for both mordents is G4.

For the first modent on the 8th note, that note should have @accid.ges="s" and the inferred ornamental note should be G4 (a minor second above the F#4) based on the key signature and any chromatic alterations of G4 given previously in the measure.

For the second mordent on the quarter note, the note is F4 natural, and the ornamental note is G4 (a major second above F4). Likewise the G4 is inferred from key signature and previous chromatic alterations of G4 in the measure (ignoring any alterations when the G4 diatonic pitch in the staff 4 layers (any layer for keyboard music as can be safely inferred since monophic instrument that share a staff will never be cross-staff) that are not placed on staff 1).

@lpugin
Copy link
Contributor

lpugin commented Sep 2, 2024

Thanks @craigsapp for the examples and points to take into account. Closing this issue since more broadly covered here.

@lpugin lpugin closed this as completed Sep 2, 2024
@craigsapp craigsapp changed the title the playback does not include the trill effect MIDI playback does not include the trill effect Sep 2, 2024
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