Skip to content

Fix MEI importer silently dropping <bTrem> and shifting subsequent onsets (AI) - #2000

Open
youdie006 wants to merge 1 commit into
cuthbertLab:masterfrom
youdie006:fix/1994-mei-btrem-import
Open

Fix MEI importer silently dropping <bTrem> and shifting subsequent onsets (AI)#2000
youdie006 wants to merge 1 commit into
cuthbertLab:masterfrom
youdie006:fix/1994-mei-btrem-import

Conversation

@youdie006

Copy link
Copy Markdown

Fixes #1994

Problem

music21.mei.base._processEmbeddedElements dispatches each child element through a per-container tag->function mapping. A child whose tag is not in the mapping is silently dropped and never recursed into (only a debug message is emitted). <bTrem> (measured / bowed tremolo, which wraps the <note>/<chord> carrying the notated duration) was registered in none of the dispatch dicts, so the tremolo note/chord and its duration disappeared and every later onset in the layer shifted earlier -- data corruption, not a cosmetic loss. As @weselyj reported, one dropped tremolo chord shifted the remainder of a real piece by a quarter note.

Fix

  • Add bTremFromElement, mirroring beamFromElement/tupletFromElement: it imports the wrapped <note>/<chord> with its notated duration and returns it, so timing is preserved. When @unitdur is present it attaches an expressions.Tremolo with numberOfMarks derived from the unit duration (eighth->1 mark, sixteenth->2, ...).
  • Register <bTrem> in the layer, beam, and tuplet dispatch tables.
  • Scope limited to <bTrem>; the two-note <fTrem> is intentionally out of scope.
  • Docstring "Implemented"/"not Implemented" element lists updated to match.

Tests

Added focused tests in music21/mei/test_base.py using the reporter's snippet: the <bTrem> chord now imports on beat 2 with its correct duration, subsequent onsets no longer shift (3 notes at offsets 0.0/1.0/2.0, ql 1/1/2), and the Tremolo expression is attached with the right number of marks. Red-green verified (without the fix the layer imports only 2 notes); the full music21/mei/test_base.py module and the module doctests pass with no regressions; ruff, pylint, and mypy are clean.

Thanks to @weselyj for the precise repro and to @mscuthbert for inviting the PR.

AI disclosure

This contribution was prepared with AI assistance; I take responsibility for its correctness and have verified it against the project's test suite and style checks.

…sets

music21.mei.base._processEmbeddedElements dispatches each child element through a
per-container tag->function mapping. A child whose tag is not in the mapping is
silently dropped and never recursed into (only a debug message is emitted).
<bTrem> (measured/bowed tremolo, which wraps the <note>/<chord> carrying the
notated duration) was registered in none of the dispatch dicts, so the tremolo
note/chord and its duration disappeared and every later onset in the layer
shifted earlier - data corruption, not a cosmetic loss.

Add bTremFromElement, mirroring beamFromElement/tupletFromElement: it imports the
wrapped <note>/<chord> with its notated duration and returns it, so timing is
preserved. When @unitdur is present it attaches an expressions.Tremolo with
numberOfMarks derived from the unit duration. Register <bTrem> in the layer,
beam, and tuplet dispatch tables. Scope limited to <bTrem>; the two-note <fTrem>
is intentionally out of scope. Docstring implemented/not-implemented lists
updated to match.

Fixes cuthbertLab#1994.
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 93.329% (+0.003%) from 93.326% — youdie006:fix/1994-mei-btrem-import into cuthbertLab:master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants