Esempio n. 1
0
    def _parseEventsIn(self, m21Stream: Union[m21.stream.Voice, m21.stream.Measure],
                             voiceIndex: int,
                             emptyStartDuration: HumNum = HumNum(0),
                             emptyEndDuration: HumNum = HumNum(0)):
        if emptyStartDuration > 0:
            # make m21 hidden rests totalling this duration, and pretend they
            # were at the beginning of m21Stream
            durations: List[HumNum] = Convert.getPowerOfTwoDurationsWithDotsAddingTo(emptyStartDuration)
            startTime: HumNum = self.startTime
            for duration in durations:
                m21StartRest: m21.note.Rest = m21.note.Rest(duration=m21.duration.Duration(duration))
                m21StartRest.style.hideObjectOnPrint = True
                event: EventData = EventData(m21StartRest, -1, voiceIndex, self, offsetInScore=startTime)
                if event is not None:
                    self.events.append(event)
                startTime += duration

        m21FlatStream: Union[m21.stream.Voice, m21.stream.Measure] = m21Stream.flat
        for elementIndex, element in enumerate(m21FlatStream):
            event: EventData = EventData(element, elementIndex, voiceIndex, self)
            if event is not None:
                self.events.append(event)

        if emptyEndDuration > 0:
            # make m21 hidden rests totalling this duration, and pretend they
            # were at the end of m21Stream
            durations: List[HumNum] = Convert.getPowerOfTwoDurationsWithDotsAddingTo(emptyEndDuration)
            startTime: HumNum = self.startTime + self.duration - emptyEndDuration
            for duration in durations:
                m21EndRest: m21.note.Rest = m21.note.Rest(duration=m21.duration.Duration(duration))
                m21EndRest.style.hideObjectOnPrint = True
                event: EventData = EventData(m21EndRest, -1, voiceIndex, self, offsetInScore=startTime)
                if event is not None:
                    self.events.append(event)
                startTime += duration
Esempio n. 2
0
    def _parseEventsIn(
            self,
            m21Stream: t.Union[m21.stream.Voice, m21.stream.Measure],
            voiceIndex: int,
            emptyStartDuration: HumNumIn = 0,
            emptyEndDuration: HumNumIn = 0
    ) -> None:
        event: EventData
        durations: t.List[HumNum]
        startTime: HumNum
        if emptyStartDuration > 0:
            # make m21 hidden rests totalling this duration, and pretend they
            # were at the beginning of m21Stream
            durations = Convert.getPowerOfTwoDurationsWithDotsAddingTo(emptyStartDuration)
            startTime = self.startTime
            for duration in durations:
                m21StartRest: m21.note.Rest = m21.note.Rest(
                    duration=m21.duration.Duration(duration)
                )
                m21StartRest.style.hideObjectOnPrint = True
                event = EventData(m21StartRest, -1, voiceIndex, self, offsetInScore=startTime)
                if event is not None:
                    self.events.append(event)
                startTime = opFrac(startTime + duration)

        for elementIndex, element in enumerate(m21Stream.recurse()
                                                    .getElementsNotOfClass(m21.stream.Stream)):
            event = EventData(element, elementIndex, voiceIndex, self)
            if event is not None:
                self.events.append(event)
                # Make a separate event for any DynamicWedge (in score's
                #   spannerBundle) that starts with this element.
                #   Why?
                #       1. So we don't put the end of the wedge in the same slice as the
                #           endNote (wedges end at the end time of the endNote, not at
                #           the start time of the endNote).
                #       2. So wedge starts/ends will go in their own slice if necessary (e.g.
                #           if we choose not to export the voice-with-only-invisible-rests we
                #           may have made to position them correctly.
                extraEvents: t.List[EventData] = self._parseDynamicWedgesStartedOrStoppedAt(event)
                if extraEvents:
                    self.events += extraEvents

        if emptyEndDuration > 0:
            # make m21 hidden rests totalling this duration, and pretend they
            # were at the end of m21Stream
            durations = Convert.getPowerOfTwoDurationsWithDotsAddingTo(emptyEndDuration)
            startTime = opFrac(self.startTime + self.duration - opFrac(emptyEndDuration))
            for duration in durations:
                m21EndRest: m21.note.Rest = m21.note.Rest(duration=m21.duration.Duration(duration))
                m21EndRest.style.hideObjectOnPrint = True
                event = EventData(m21EndRest, -1, voiceIndex, self, offsetInScore=startTime)
                if event is not None:
                    self.events.append(event)
                startTime = opFrac(startTime + duration)
Esempio n. 3
0
    def _parseEventsAtTopLevelOf(self, m21Stream: m21.stream.Measure):
        for elementIndex, element in enumerate(m21Stream):
            if 'Stream' in element.classes:
                # skip substreams, just parse the top-level objects
                continue

            event: EventData = EventData(element, elementIndex, -1, self)
            if event is not None:
                self.events.append(event)
Esempio n. 4
0
    def _parseMeasure(self):
        self._setStartTimeOfMeasure()
        self._duration = HumNum(self.m21Measure.duration.quarterLength)

        # m21 tracks timesigdur for us in barDuration, which is always the latest timeSig duration
        # But it can be ridiculously slow if it has to search back in the score for a timesignature,
        # so we only call it if the measure has a timesignature. If it doesn't have one, we
        # just use the _timeSigDur of the previous measure.
        if self.m21Measure.timeSignature is None and self._prevMeasData is not None:
            self._timeSigDur = self._prevMeasData.timeSigDur
        else:
            self._timeSigDur = HumNum(self.m21Measure.barDuration.quarterLength)

        self._measureNumberString = self.m21Measure.measureNumberWithSuffix()
        if self._measureNumberString == '0':
            self._measureNumberString = ''

        # In humdrum, measure style is a combination of this measure's left barline and the
        # previous measure's right barline.  (For example, ':|!|:' in a humdrum barline comes
        # from the previous right barline being an end-repeat (light-heavy) and the current
        # left barline being a start repeat (heavy-light)).
        # The very last humdrum barline (last measure's right barline) is handled as a special
        # case at a higher level, not here.

        # Compute our left and right barline style
        self.leftBarlineStyle = M21Convert.measureStyleFromM21Barline(self.m21Measure.leftBarline)
        self.rightBarlineStyle = M21Convert.measureStyleFromM21Barline(self.m21Measure.rightBarline)

        # Grab the previous measure's right barline style (if there is one) and
        # combine it with our left barline style, giving our measureStyle.
        prevRightMeasureStyle: MeasureStyle = MeasureStyle.Regular
        if self._prevMeasData is not None:
            prevRightMeasureStyle = self._prevMeasData.rightBarlineStyle
        self.measureStyle = M21Convert.combineTwoMeasureStyles(self.leftBarlineStyle,
                                                               prevRightMeasureStyle)

        # measure index 0 only: add events for any Instruments found in ownerStaff.m21PartStaff
        if self.measureIndex == 0:
            for elementIndex, inst in enumerate(
                    self.ownerStaff.m21PartStaff.getElementsByClass(m21.instrument.Instrument)):
                event: EventData = EventData(inst, elementIndex, -1, self)
                if event is not None:
                    self.events.append(event)

        if len(list(self.m21Measure.voices)) == 0:
            # treat the measure itself as voice 0
            self._parseEventsIn(self.m21Measure, 0)
        else:
            # parse the 0-offset non-streams first...
            self._parseEventsAtTopLevelOf(self.m21Measure)
            # ... then parse the voices
            for voiceIndex, voice in enumerate(self.m21Measure.voices):
                emptyStartDuration: HumNum = HumNum(voice.offset)
                emptyEndDuration: HumNum = HumNum(self.duration - (HumNum(voice.offset) + HumNum(voice.duration.quarterLength)))
                self._parseEventsIn(voice, voiceIndex, emptyStartDuration, emptyEndDuration)

        self._sortEvents()
Esempio n. 5
0
    def _parseEventsAtTopLevelOf(self, m21Stream: m21.stream.Measure) -> None:
        for elementIndex, element in enumerate(m21Stream):
            if 'Stream' in element.classes:
                # skip substreams, just parse the top-level objects
                continue

            event: EventData = EventData(element, elementIndex, -1, self)
            if event is not None:
                self.events.append(event)

                extraEvents: t.List[EventData] = self._parseDynamicWedgesStartedOrStoppedAt(event)
                if extraEvents:
                    self.events += extraEvents
Esempio n. 6
0
    def _parseDynamicWedgesStartedOrStoppedAt(self, event: EventData) -> t.List[EventData]:
        if t.TYPE_CHECKING:
            assert isinstance(event.m21Object, m21.note.GeneralNote)
        output: t.List[EventData] = []
        wedges: t.List[m21.dynamics.DynamicWedge] = (
            M21Utilities.getDynamicWedgesStartedOrStoppedWithGeneralNote(
                event.m21Object,
                self.spannerBundle)
        )
        wedge: m21.dynamics.DynamicWedge
        for wedge in wedges:
            ownerScore = self.ownerStaff.ownerPart.ownerScore
            score: m21.stream.Score = ownerScore.m21Score
            startNote: m21.note.GeneralNote = wedge.getFirst()
            endNote: m21.note.GeneralNote = wedge.getLast()
            thisEventIsStart: bool = startNote is event.m21Object
            thisEventIsEnd: bool = endNote is event.m21Object
            wedgeStartTime: t.Optional[HumNum] = None
            wedgeDuration: t.Optional[HumNum] = None
            wedgeEndTime: HumNum = opFrac(
                endNote.getOffsetInHierarchy(score) + endNote.duration.quarterLength
            )
            if thisEventIsStart:
                wedgeStartTime = startNote.getOffsetInHierarchy(score)
                wedgeDuration = opFrac(wedgeEndTime - wedgeStartTime)

            if thisEventIsStart and thisEventIsEnd:
                # print(f'wedgeStartStopEvent: {event}', file=sys.stderr)
                # one note for the wedge? let's make one event, so it can become '>]' or whatever
                wedgeStartStopEvent: EventData = EventData(wedge, -1, event.voiceIndex, self,
                                                           offsetInScore=wedgeStartTime,
                                                           duration=wedgeDuration)
                output.append(wedgeStartStopEvent)
            elif thisEventIsStart:
                # add the start event, with duration
                # print(f'wedgeStartEvent: {event}', file=sys.stderr)
                wedgeStartEvent: EventData = EventData(wedge, -1, event.voiceIndex, self,
                                                       offsetInScore=wedgeStartTime,
                                                       duration=wedgeDuration)
                output.append(wedgeStartEvent)
            elif thisEventIsEnd:
                # add the end event (duration == 0)
                # but add it to the same measure/voice as the wedge start event
                # print(f'wedgeStopEvent: {event}', file=sys.stderr)
                matchingStartEvent: t.Optional[EventData] = (
                    ownerScore.eventFromM21Object.get(id(wedge), None)
                )
                endVoiceIndex: int
                if matchingStartEvent is None:
                    # print('wedgeStop with no wedgeStart, putting it in its own measure/voice',
                    #           file=sys.stderr)
                    endVoiceIndex = event.voiceIndex
                    endSelf = self
                else:
                    endVoiceIndex = matchingStartEvent.voiceIndex
                    endSelf = matchingStartEvent.ownerMeasure
                wedgeEndEvent: EventData = EventData(wedge, -1, endVoiceIndex, endSelf,
                                                     offsetInScore=wedgeEndTime,
                                                     duration=0)
                output.append(wedgeEndEvent)

        return output
Esempio n. 7
0
    def _parseMeasure(self) -> None:
        self._setStartTimeOfMeasure()
        self._duration = self.m21Measure.duration.quarterLength

        # m21 tracks timesigdur for us in barDuration, which is always the latest timeSig duration
        # But it can be ridiculously slow if it has to search back in the score for a timesignature,
        # so we only call it if the measure has a timesignature. If it doesn't have one, we
        # just use the _timeSigDur of the previous measure.
        if self.m21Measure.timeSignature is None and self._prevMeasData is not None:
            self._timeSigDur = self._prevMeasData.timeSigDur
        else:
            self._timeSigDur = self.m21Measure.barDuration.quarterLength

        self._measureNumberString = self.m21Measure.measureNumberWithSuffix()
        if self._measureNumberString == '0':
            self._measureNumberString = ''

        # In humdrum, measure style is a combination of this measure's left barline and the
        # previous measure's right barline.  (For example, ':|!|:' in a humdrum barline comes
        # from the previous right barline being an end-repeat (light-heavy) and the current
        # left barline being a start repeat (heavy-light)).
        # The very last humdrum barline (last measure's right barline) is handled as a special
        # case at a higher level, not here.

        # Compute our left and right barline style
        self.leftBarlineStyle = M21Convert.measureStyleFromM21Barline(self.m21Measure.leftBarline)
        self.rightBarlineStyle = M21Convert.measureStyleFromM21Barline(self.m21Measure.rightBarline)

        # Grab the previous measure's right barline style (if there is one) and
        # combine it with our left barline style, giving our measureStyle.
        prevRightMeasureStyle: MeasureStyle = MeasureStyle.Regular
        if self._prevMeasData is not None:
            prevRightMeasureStyle = self._prevMeasData.rightBarlineStyle
        self.measureStyle = M21Convert.combineTwoMeasureStyles(self.leftBarlineStyle,
                                                               prevRightMeasureStyle)
        # Extract left and right barline Fermata
        self.leftBarlineFermataStyle = M21Convert.fermataStyleFromM21Barline(
            self.m21Measure.leftBarline
        )
        self.rightBarlineFermataStyle = M21Convert.fermataStyleFromM21Barline(
            self.m21Measure.rightBarline
        )

        # Grab the previous measure's right barline fermata style (if there is one) and
        # combine it with our left barline fermata style, giving our fermataStyle.
        prevRightBarlineFermataStyle: FermataStyle = FermataStyle.NoFermata
        if self._prevMeasData is not None:
            prevRightBarlineFermataStyle = self._prevMeasData.rightBarlineFermataStyle
        self.fermataStyle = M21Convert.combineTwoFermataStyles(
            self.leftBarlineFermataStyle,
            prevRightBarlineFermataStyle
        )

        # measure index 0 only: add events for any Instruments found in ownerStaff.m21PartStaff
        if self.measureIndex == 0:
            for elementIndex, inst in enumerate(
                    self.ownerStaff.m21PartStaff.getElementsByClass(m21.instrument.Instrument)):
                event: EventData = EventData(inst, elementIndex, -1, self)
                if event is not None:
                    self.events.append(event)

        # parse any RepeatBracket this measure is in.
        for rb in self.m21Measure.getSpannerSites([m21.spanner.RepeatBracket]):
            # measure is in this RepeatBracket
            if t.TYPE_CHECKING:
                assert isinstance(rb, m21.spanner.RepeatBracket)
            self.inRepeatBracket = True
            if rb.overrideDisplay:
                self.repeatBracketName = rb.overrideDisplay
            else:
                self.repeatBracketName = rb.number

            if rb.getFirst() == self.m21Measure:
                # this measure starts the RepeatBracket (it may also stop it)
                self.startsRepeatBracket = True

            if rb.getLast() == self.m21Measure:
                # this measure stops the RepeatBracket (it may also start it)
                self.stopsRepeatBracket = True

            # a measure can only be in one RepeatBracket, so stop looking
            break

        if len(list(self.m21Measure.voices)) == 0:
            # treat the measure itself as voice 0
            self._parseEventsIn(self.m21Measure, 0)
        else:
            # first parse the voices...
            for voiceIndex, voice in enumerate(self.m21Measure.voices):
                emptyStartDuration: HumNum = voice.offset
                emptyEndDuration: HumNum = opFrac(
                    self.duration - (voice.offset + voice.duration.quarterLength)
                )
                self._parseEventsIn(voice, voiceIndex, emptyStartDuration, emptyEndDuration)

            # ... then parse the non-streams last, so that the ending barline lands after
            # any objects in the voices that are also at the last offset in the measure
            # (e.g. TextExpressions after the last note in the measure).
            self._parseEventsAtTopLevelOf(self.m21Measure)

        self._sortEvents()