Skip to content

MEI importer silently drops <bTrem> (bowed tremolo) and its child note/chord, shifting all subsequent onsets #1994

Description

@weselyj

music21 version: 9.1.0 (also verified against the current MEI dispatch table)

Problem summary: music21.mei.base has no handler for <bTrem> (absent from the layer dispatch table), and an unhandled element's children are not imported. The result is not a cosmetic loss: the tremolo's note/chord contributes zero duration, so every onset after it in that voice shifts earlier by the tremolo's duration.

In the piece where I hit this (a Humdrum score rendered to MEI by verovio, which correctly emits <bTrem unitdur="8"> for a beamed tremolo), one dropped chord shifted the entire remainder of the piece by a quarter note — 169 spurious / 171 missing onsets out of ~1,900 when compared event-wise against the source.

Minimal repro (self-contained, 4/4 bar with notes on beats 1, 2, 3):

import music21

mei = '''<?xml version="1.0" encoding="UTF-8"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.1">
 <music><body><mdiv><score>
  <scoreDef meter.count="4" meter.unit="4">
   <staffGrp><staffDef n="1" lines="5" clef.shape="G" clef.line="2"/></staffGrp>
  </scoreDef>
  <section>
   <measure n="1">
    <staff n="1">
     <layer n="1">
      <note xml:id="n1" dur="4" oct="4" pname="c"/>
      <bTrem xml:id="bt1" form="meas" unitdur="8">
       <chord xml:id="ch1" dur="4">
        <note xml:id="n2" oct="4" pname="e"/>
        <note xml:id="n3" oct="5" pname="e"/>
       </chord>
      </bTrem>
      <note xml:id="n4" dur="2" oct="4" pname="g"/>
     </layer>
    </staff>
   </measure>
  </section>
 </score></mdiv></body></music>
</mei>'''

s = music21.converter.parse(mei, format="mei")
for n in s.flatten().notes:
    print(n.offset, [p.nameWithOctave for p in n.pitches], n.duration.quarterLength)

Actual output:

0.0 ['C4'] 1.0
1.0 ['G4'] 2.0

The <bTrem> chord (E4+E5 on beat 2) is gone, and G4 lands on beat 2 instead of beat 3.

Expected: the chord imported with its notated duration (offset 1.0, quarterLength 1.0) and G4 at offset 2.0 — ideally with a Tremolo expression attached, but timing correctness is the important part.

Suggested minimal fix short of full tremolo support: treat <bTrem> (and <fTrem>) transparently in the layer dispatch — import child <note>/<chord> elements as ordinary notes so durations survive, optionally attaching a Tremolo/TremoloSpanner expression when unitdur/@measperf is present. Silent deletion is the one behaviour that corrupts everything downstream of the tremolo.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions