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

Hidden rests import into both PartStaffs #991

Closed
jacobtylerwalls opened this issue Apr 29, 2021 · 0 comments · Fixed by #1008
Closed

Hidden rests import into both PartStaffs #991

jacobtylerwalls opened this issue Apr 29, 2021 · 0 comments · Fixed by #1008

Comments

@jacobtylerwalls
Copy link
Member

jacobtylerwalls commented Apr 29, 2021

music21 version

dev (and reproduced on 3.1.0)

Problem summary
Voices that don't fill the measure are represented in MusicXML with <forward> tags, from which m21 creates hidden rests. The hidden rests are made late enough that they never get a staffReference, and so they are not excluded during PartStaff separation, and so we get hidden rests in both parts.

Steps to reproduce

>>> from music21 import corpus, stream
>>> sch = corpus.parse('schoenberg/opus19', 2, forceSource=True)
>>> sch.parts[0][stream.Measure][-1].show('t')
{0.0} <music21.expressions.TextExpression 'poco rit.'>
{0.0} <music21.stream.Voice 1>
    {0.0} <music21.note.Rest quarter>
    {1.0} <music21.note.Rest eighth>
    {1.5} <music21.chord.Chord G4 B4>
    {2.0} <music21.chord.Chord G4 B4>
{0.0} <music21.stream.Voice 2>
    {0.0} <music21.note.Rest half>
    {2.0} <music21.chord.Chord E-5 F#5 B-5 D6>
{4.0} <music21.bar.Barline type=final>
>>> sch.parts[1][stream.Measure][-1].show('t')
{0.0} <music21.stream.Voice 2>
    {0.0} <music21.note.Rest half>    <------------------------incorrect
{0.0} <music21.stream.Voice 3>
    {0.0} <music21.note.Rest eighth>
    {0.5} <music21.chord.Chord C3 E3>
    {1.0} <music21.note.Rest quarter>
    {2.0} <music21.note.Rest half>
{4.0} <music21.bar.Barline type=final>

More information
This was the existing bug I was referring to in #986 (comment), discovered while working on #986.

Suggested fix
This diff fixes it, but I'm not convinced it's the best place to do this checking. (And it needs refactoring to pass the Pylint check for nested blocks.) Perhaps we should just create hidden rests in xmlForward() instead of relying on makeRests() after the fact? The problem with that is that <forward> tags don't have staff numbers. AH -- they do!

diff --git a/music21/musicxml/xmlToM21.py b/music21/musicxml/xmlToM21.py
index 35faa2ea5..3b6034ba6 100644
--- a/music21/musicxml/xmlToM21.py
+++ b/music21/musicxml/xmlToM21.py
@@ -2385,12 +2385,36 @@ class MeasureParser(XMLParserBase):
                     # the musicDataMethods use insertCore, thus the voices need to run
                     # coreElementsChanged
                     v.coreElementsChanged()
+                    elementsBefore = v.elements
                     # Fill mid-measure gaps, and find end of measure gaps by ref to measure stream
                     # https://github.com/cuthbertlab/music21/issues/444
                     v.makeRests(refStreamOrTimeRange=self.stream,
                                 fillGaps=True,
                                 inPlace=True,
                                 hideRests=True)
+                    elementsAdded = [e for e in v.elements if e not in elementsBefore]
+                    if not elementsAdded:
+                        continue
+
+                    for e in elementsAdded:
+                        next_element = e.next()
+                        staffKey = None
+                        for k, listOfEls in self.staffReference.items():
+                            if next_element in listOfEls:
+                                staffKey = k
+                                break
+                        if staffKey is None:
+                            # use max of keys in self.staffReference?
+                            continue
+                        if next_element.offset < e.offset:
+                            staffKey -= 1
+                        if staffKey < 0:
+                            continue
+                        if staffKey not in self.staffReference:
+                            self.staffReference[staffKey] = []
+                        self.staffReference[staffKey].append(e)
+
         self.stream.coreElementsChanged()
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 a pull request may close this issue.

1 participant