Skip to content

Beaming corrections for stripTies() #994

@jacobtylerwalls

Description

@jacobtylerwalls

music21 version

7.0.5

Problem summary
stripTies(inPlace=True) leaves behind broken beams when it deletes notes, such as a stop beam lacking a start. These broken beams are then written out to musicxml, since .streamStatus.beams is already True, and makeNotation during musicXML export uses that flag to skip making beams. makeNotation during musicXML export queries a temporary stream of measures and gets its streamStatus .beams value by doing a fresh scan through all elements for the presence of any beam, and uses that result to skip making beams.

stripTies(inPlace=False) starts fresh with a new stream, no beams. Good—it doesn’t have the above problem. makeNotation during musicxml export makes beams for the first time.

But BOTH flavors of stripTies have this downstream problem:

  • In musicxml export, makeNotation() runs before splitAtDurations(), so we make some of the beams that need to be made, but too early to catch needed beams involving split durations (e.g. the 0.5 on a 2.5 QL note).

Either way, if you're using stripTies/chordify to annotate a score (add lyrics, etc), the beams will need some manual corrections.

Steps to reproduce

p = converter.parse('tinyNotation: c2~ c8 c8 c8 c8')
p.makeNotation(inPlace=True)  # makeBeams and set streamStatus.beams = True
p.stripTies(inPlace=True)
for n in p.recurse().notes:
    print(n.offset, n.beams)

Actual behavior

0.0 <music21.beam.Beams>
2.5 <music21.beam.Beams <music21.beam.Beam 1/stop>>  # broken
3.0 <music21.beam.Beams <music21.beam.Beam 1/start>>
3.5 <music21.beam.Beams <music21.beam.Beam 1/stop>>

MuseScore display (Finale does some automagic fixing, but the beam tags we are writing suggest this output):
Screen Shot 2021-04-13 at 8 58 57 PM

Workarounds

Deliberately calling makeBeams() afterward, but before musicxml export, will remove the broken beam, and should allow the deepcopy/makenotation musicxml export pipeline to start fresh with new beams. Calling Stream.splitAtDurations() should handle the other issue too, but this is too involved -- no reason we can't just incorporate these steps, it seems to me.

Suggested approach

  • stripTies(inPlace=False)could just set streamStatus.beams = False so that they can get remade during the makeNotation/musicxml export pipeline, and so we don’t have to document calling makeBeams() after stripTies(). This avoids imposing making beams when users are still doing transformations inside music21.
  • musicxml export should split durations using our newfangled Stream.splitAtDurations() somewhere early like fixupNotationMeasured() rather than note by note in parseOneElement().

Metadata

Metadata

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