Ejemplo n.º 1
0
    def __init__(
        self,
        element=None,
        beatStrength=None,
        parentOffset=None,
        parentEndTime=None,
        parentage=None,
        offset=None,
        endTime=None,
    ):
        super(ElementTimespan, self).__init__(offset=offset, endTime=endTime)

        self._element = element
        if parentage is not None:
            parentage = tuple(parentage)
        self._parentage = parentage
        if beatStrength is not None:
            beatStrength = float(beatStrength)
        self._beatStrength = beatStrength
        if parentOffset is not None:
            parentOffset = float(parentOffset)
        self._parentOffset = parentOffset
        if parentEndTime is not None:
            parentEndTime = float(parentEndTime)
        self._parentEndTime = parentEndTime
        if parentOffset is not None and parentEndTime is not None:
            if parentOffset > parentEndTime:
                raise TimespanException(
                    'offset %r must be after parentEndTime %r' %
                    (parentOffset, parentEndTime))
Ejemplo n.º 2
0
 def __init__(self, offset=float('-inf'), endTime=float('inf')):
     if offset is not None:
         offset = float(offset)
     self._offset = offset
     if endTime is not None:
         endTime = float(endTime)
     self._endTime = endTime
     if offset is not None and endTime is not None:
         if offset > endTime:
             raise TimespanException('offset %r must be after endTime %r' %
                                     (offset, endTime))
Ejemplo n.º 3
0
    def rebalance(self):
        r'''
        Rebalances the subtree rooted on this node.

        Returns the new central node.
        '''
        node = self
        if node.balance > 1:
            if 0 <= node.rightChild.balance:
                node = node.rotateRightRight()
            else:
                node = node.rotateRightLeft()
        elif node.balance < -1:
            if node.leftChild.balance <= 0:
                node = node.rotateLeftLeft()
            else:
                node = node.rotateLeftRight()
        if node.balance < -1 or node.balance > 1:
            raise TimespanException(
                'Somehow Nodes are still not balanced. node.balance %r must be between -1 and 1'
            )

        return node
Ejemplo n.º 4
0
    def mergeWith(self, elementTimespan):
        r'''
        Merges two consecutive like-pitched element timespans, keeping
        score-relevant information from the first of the two, such as its
        Music21 Element, and any beatstrength information.

        This is useful when using timespans to perform score reduction.

        Let's demonstrate merging some contiguous E's in the alto part of a Bach
        chorale:

        >>> score = corpus.parse('bwv66.6')
        >>> tree = score.asTimespans()
        >>> timespan_one = tree[12]
        >>> print(timespan_one)
        <ElementTimespan (2.0 to 3.0) <music21.note.Note E>>

        >>> print(timespan_one.part)
        <music21.stream.Part Alto>

        >>> timespan_two = tree.findNextElementTimespanInSameStreamByClass(
        ...     timespan_one)
        >>> print(timespan_two)
        <ElementTimespan (3.0 to 4.0) <music21.note.Note E>>
            
        >>> merged = timespan_one.mergeWith(timespan_two)
        >>> print(merged)
        <ElementTimespan (2.0 to 4.0) <music21.note.Note E>>

        >>> merged.part is timespan_one.part
        True

        >>> merged.beatStrength == timespan_one.beatStrength
        True

        Attempting to merge timespans which are not contiguous, or which do not
        have identical pitches will result in error:

        >>> tree[0].mergeWith(tree[50])
        Traceback (most recent call last):
        ...
        TimespanException: Cannot merge <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>> with <ElementTimespan (9.5 to 10.0) <music21.note.Note B>>: not contiguous

        This is probably not what you want to do: get the next element timespan in
        the same score:

        >>> timespan_twoWrong = tree.findNextElementTimespanInSameStreamByClass(
        ...     timespan_one, classList=(stream.Score,))
        >>> print(timespan_twoWrong)
        <ElementTimespan (3.0 to 4.0) <music21.note.Note C#>>
        >>> print(timespan_twoWrong.part)
        <music21.stream.Part Soprano>
        '''
        if not isinstance(elementTimespan, type(self)):
            message = 'Cannot merge {} with {}: wrong types'.format(
                self, elementTimespan)
            raise TimespanException(message)
        if not ((self.endTime == elementTimespan.offset) or
                (elementTimespan.endTime == self.offset)):
            message = 'Cannot merge {} with {}: not contiguous'.format(
                self, elementTimespan)
            raise TimespanException(message)
        if self.pitches != elementTimespan.pitches:
            message = 'Cannot merge {} with {}: different pitches'.format(
                self, elementTimespan)
            raise TimespanException(message)
        if self.offset < elementTimespan.offset:
            mergedElementTimespan = self.new(endTime=elementTimespan.endTime, )
        else:
            mergedElementTimespan = elementTimespan.new(endTime=self.endTime, )
        return mergedElementTimespan
Ejemplo n.º 5
0
    def mergeWith(self, other):
        r'''
        Merges two consecutive/contiguous timespans, keeping the
        information from the former of the two.
        
        >>> ts1 = timespans.spans.Timespan(0, 5)
        >>> ts2 = timespans.spans.Timespan(5, 7)
        >>> ts3 = ts1.mergeWith(ts2)
        >>> ts3
        <Timespan 0.0 7.0>

        Note that (for now), overlapping timespans cannot be merged:
        
        >>> ts4 = timespans.spans.Timespan(6, 10)
        >>> ts3.mergeWith(ts4)
        Traceback (most recent call last):
        TimespanException: Cannot merge <Timespan 0.0 7.0> with 
            <Timespan 6.0 10.0>: not contiguous        
        
        
        Merges two consecutive like-pitched element timespans, keeping
        score-relevant information from the first of the two, such as its
        Music21 Element, and any beatstrength information.

        This is useful when using timespans to perform score reduction.

        Let's demonstrate merging some contiguous E's in the alto part of a Bach
        chorale:

        >>> score = corpus.parse('bwv66.6')
        >>> tree = score.asTimespans()
        >>> timespan_one = tree[12]
        >>> print(timespan_one)
        <ElementTimespan (2.0 to 3.0) <music21.note.Note E>>

        >>> print(timespan_one.part)
        <music21.stream.Part Alto>

        >>> timespan_two = tree.findNextElementTimespanInSameStreamByClass(
        ...     timespan_one)
        >>> print(timespan_two)
        <ElementTimespan (3.0 to 4.0) <music21.note.Note E>>
            
        >>> merged = timespan_one.mergeWith(timespan_two)
        >>> print(merged)
        <ElementTimespan (2.0 to 4.0) <music21.note.Note E>>

        >>> merged.part is timespan_one.part
        True

        >>> merged.beatStrength == timespan_one.beatStrength
        True

        Attempting to merge timespans which are not contiguous, or which do not
        have identical pitches will result in error:

        >>> tree[0].mergeWith(tree[50])
        Traceback (most recent call last):
        TimespanException: Cannot merge <ElementTimespan (0.0 to 0.5) <music21.note.Note C#>> 
                with <ElementTimespan (9.5 to 10.0) <music21.note.Note B>>: not contiguous

        This is probably not what you want to do: get the next element timespan in
        the same score:

        >>> timespan_twoWrong = tree.findNextElementTimespanInSameStreamByClass(
        ...     timespan_one, classList=(stream.Score,))
        >>> print(timespan_twoWrong)
        <ElementTimespan (3.0 to 4.0) <music21.note.Note C#>>
        >>> print(timespan_twoWrong.part)
        <music21.stream.Part Soprano>
        '''
        can, message = self.canMerge(other)
        if can is False:
            raise TimespanException(message)

        if self.offset < other.offset:
            mergedTimespan = self.new(endTime=other.endTime)
        else:
            mergedTimespan = other.new(endTime=self.endTime)
        return mergedTimespan
Ejemplo n.º 6
0
def timespansToChordifiedStream(timespans, templateStream=None):
    r'''
    Creates a score from the ElementTimespan objects stored in this
    offset-tree.

    A "template" score may be used to provide measure and time-signature
    information.

    >>> score = corpus.parse('bwv66.6')
    >>> tree = score.asTimespans()
    >>> chordifiedScore = timespans.timespansToChordifiedStream(
    ...     tree, templateStream=score)
    >>> chordifiedScore.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.key.KeySignature of 3 sharps, mode minor>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.chord.Chord A3 E4 C#5>
        {0.5} <music21.chord.Chord G#3 B3 E4 B4>
    {1.0} <music21.stream.Measure 1 offset=1.0>
        {0.0} <music21.chord.Chord F#3 C#4 F#4 A4>
        {1.0} <music21.chord.Chord G#3 B3 E4 B4>
        {2.0} <music21.chord.Chord A3 E4 C#5>
        {3.0} <music21.chord.Chord G#3 B3 E4 E5>
    {5.0} <music21.stream.Measure 2 offset=5.0>
        {0.0} <music21.chord.Chord A3 E4 C#5>
        {0.5} <music21.chord.Chord C#3 E4 A4 C#5>
        {1.0} <music21.chord.Chord E3 E4 G#4 B4>
        {1.5} <music21.chord.Chord E3 D4 G#4 B4>
        {2.0} <music21.chord.Chord A2 C#4 E4 A4>
        {3.0} <music21.chord.Chord E#3 C#4 G#4 C#5>
    {9.0} <music21.stream.Measure 3 offset=9.0>
        {0.0} <music21.layout.SystemLayout>
        {0.0} <music21.chord.Chord F#3 C#4 F#4 A4>
        {0.5} <music21.chord.Chord B2 D4 G#4 B4>
        {1.0} <music21.chord.Chord C#3 C#4 E#4 G#4>
        {1.5} <music21.chord.Chord C#3 B3 E#4 G#4>
        {2.0} <music21.chord.Chord F#2 A3 C#4 F#4>
        {3.0} <music21.chord.Chord F#3 C#4 F#4 A4>
    ...
    '''
    from music21 import stream
    if not isinstance(timespans, trees.TimespanTree):
        raise trees.TimespanTreeException('Needs a TimespanTree to run')
    if isinstance(templateStream, stream.Stream):
        templateOffsets = sorted(templateStream.measureOffsetMap())
        templateOffsets.append(templateStream.duration.quarterLength)
        if hasattr(templateStream, 'parts') and templateStream.iter.parts:
            outputStream = templateStream.iter.parts[0].measureTemplate(
                fillWithRests=False)
        else:
            outputStream = templateStream.measureTemplate(fillWithRests=False)
        timespans = timespans.copy()
        timespans.splitAt(templateOffsets)
        measureIndex = 0
        allTimePoints = timespans.allTimePoints + tuple(templateOffsets)
        allTimePoints = sorted(set(allTimePoints))
        for offset, endTime in zip(allTimePoints, allTimePoints[1:]):
            while templateOffsets[1] <= offset:
                templateOffsets.pop(0)
                measureIndex += 1
            vert = timespans.getVerticalityAt(offset)
            quarterLength = endTime - offset
            if (quarterLength < 0):
                raise TimespanException(
                    "Something is wrong with the verticality %r its endTime %f is less than its offset %f"
                    % (vert, endTime, offset))
            element = vert.makeElement(quarterLength)
            outputStream[measureIndex].append(element)
        return outputStream
    else:
        allTimePoints = timespans.allTimePoints
        elements = []
        for offset, endTime in zip(allTimePoints, allTimePoints[1:]):
            vert = timespans.getVerticalityAt(offset)
            quarterLength = endTime - offset
            if (quarterLength < 0):
                raise TimespanException(
                    "Something is wrong with the verticality %r, its endTime %f is less than its offset %f"
                    % (vert, endTime, offset))
            element = vert.makeElement(quarterLength)
            elements.append(element)
        outputStream = stream.Score()
        for element in elements:
            outputStream.append(element)
        return outputStream