music21.repeat

This module provides the base class for all RepeatMark objects: entities that denote repeats.

Some RepeatMark objects are Expression objects; others are Bar objects. See for instance, the Repeat which represents a normal barline repeat.

RepeatExpression

class music21.repeat.RepeatExpression(**keywords)

This class models any mark added to a Score to mark repeat start and end points that are designated by text expressions or symbols, such as D.S. Al Coda, etc.

N.B. Repeat(Barline) objects are not RepeatExpression objects, but both are RepeatMark subclasses.

This class stores internally a TextExpression. This object is used for rendering text output in translation. A properly configured TextExpression object can also be used to create an instance of a RepeatExpressions.

RepeatExpression bases

RepeatExpression read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

RepeatExpression read/write properties

Read/write properties inherited from Music21Object:

RepeatExpression methods

RepeatExpression.applyTextFormatting(te=None)

Apply the default text formatting to the text expression version of this repeat

RepeatExpression.getText()

Get the text used for this expression.

RepeatExpression.getTextExpression()

Return a copy of the TextExpression stored in this object.

RepeatExpression.isValidText(value)

Return True or False if the supplied text could be used for this RepeatExpression.

RepeatExpression.setText(value)

Set the text of this repeat expression. This is also the primary way that the stored TextExpression object is created.

RepeatExpression.setTextExpression(value)

Directly set a TextExpression object.

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

RepeatExpression instance variables

Instance variables inherited from Music21Object:

RepeatExpressionMarker

class music21.repeat.RepeatExpressionMarker(**keywords)

Some repeat expressions are markers of positions in the score to jump to; these classes model those makers, such as Coda, Segno, and Fine, which are subclassed below.

RepeatExpressionMarker bases

RepeatExpressionMarker read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

RepeatExpressionMarker read/write properties

Read/write properties inherited from Music21Object:

RepeatExpressionMarker methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

RepeatExpressionMarker instance variables

Instance variables inherited from Music21Object:

Coda

class music21.repeat.Coda(text=None, **keywords)

The coda symbol, or the word coda, as placed in a score.

>>> rm = repeat.Coda()

Coda bases

Coda read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

Coda read/write properties

Read/write properties inherited from Music21Object:

Coda methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

Coda instance variables

Instance variables inherited from Music21Object:

Segno

class music21.repeat.Segno(**keywords)

The segno sign as placed in a score.

>>> rm = repeat.Segno()
>>> rm.useSymbol
True

Segno bases

Segno read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

Segno read/write properties

Read/write properties inherited from Music21Object:

Segno methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

Segno instance variables

Instance variables inherited from Music21Object:

Fine

class music21.repeat.Fine(**keywords)

The fine word as placed in a score.

>>> rm = repeat.Fine()

Fine bases

Fine read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

Fine read/write properties

Read/write properties inherited from Music21Object:

Fine methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

Fine instance variables

Instance variables inherited from Music21Object:

RepeatExpressionCommand

class music21.repeat.RepeatExpressionCommand(**keywords)

Some repeat expressions are commands, instructing the reader to go somewhere else. DaCapo and related are examples.

RepeatExpressionCommand bases

RepeatExpressionCommand read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

RepeatExpressionCommand read/write properties

Read/write properties inherited from Music21Object:

RepeatExpressionCommand methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

RepeatExpressionCommand instance variables

Instance variables inherited from Music21Object:

DaCapo

class music21.repeat.DaCapo(text=None, **keywords)

The Da Capo command, indicating a return to the beginning and a continuation to the end. By default, repeatAfterJump is False, indicating that any repeats encountered on the Da Capo repeat not be repeated.

DaCapo bases

DaCapo read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DaCapo read/write properties

Read/write properties inherited from Music21Object:

DaCapo methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DaCapo instance variables

Instance variables inherited from Music21Object:

DaCapoAlFine

class music21.repeat.DaCapoAlFine(text=None, **keywords)

The Da Capo al Fine command, indicating a return to the beginning and a continuation to the Fine object. By default, repeatAfterJump is False, indicating that any repeats encountered on the Da Capo repeat not be repeated.

>>> rm = repeat.DaCapoAlFine()

DaCapoAlFine bases

DaCapoAlFine read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DaCapoAlFine read/write properties

Read/write properties inherited from Music21Object:

DaCapoAlFine methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DaCapoAlFine instance variables

Instance variables inherited from Music21Object:

DaCapoAlCoda

class music21.repeat.DaCapoAlCoda(text=None, **keywords)

The Da Capo al Coda command, indicating a return to the beginning and a continuation to the Coda object. The music resumes at a second Coda object. By default, repeatAfterJump is False, indicating that any repeats encountered on the Da Capo repeat not be repeated.

>>> rm = repeat.DaCapoAlCoda()

DaCapoAlCoda bases

DaCapoAlCoda read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DaCapoAlCoda read/write properties

Read/write properties inherited from Music21Object:

DaCapoAlCoda methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DaCapoAlCoda instance variables

Instance variables inherited from Music21Object:

AlSegno

class music21.repeat.AlSegno(text=None, **keywords)

Jump to the sign. Presumably a forward jump, not a repeat.

>>> rm = repeat.AlSegno()

AlSegno bases

AlSegno read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

AlSegno read/write properties

Read/write properties inherited from Music21Object:

AlSegno methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

AlSegno instance variables

Instance variables inherited from Music21Object:

DalSegno

class music21.repeat.DalSegno(text=None, **keywords)

The Dal Segno command, indicating a return to the segno and a continuation to the end. By default, repeatAfterJump is False, indicating that any repeats encountered on the Da Capo repeat not be repeated.

>>> rm = repeat.DaCapoAlFine()

DalSegno bases

DalSegno read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DalSegno read/write properties

Read/write properties inherited from Music21Object:

DalSegno methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DalSegno instance variables

Instance variables inherited from Music21Object:

DalSegnoAlFine

class music21.repeat.DalSegnoAlFine(text=None, **keywords)

The Dal Segno al Fine command, indicating a return to the segno and a continuation to the Fine object. By default, repeatAfterJump is False, indicating that any repeats encountered on the Dal Segno repeat not be repeated.

>>> rm = repeat.DaCapoAlFine()

DalSegnoAlFine bases

DalSegnoAlFine read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DalSegnoAlFine read/write properties

Read/write properties inherited from Music21Object:

DalSegnoAlFine methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DalSegnoAlFine instance variables

Instance variables inherited from Music21Object:

DalSegnoAlCoda

class music21.repeat.DalSegnoAlCoda(text=None, **keywords)

The Dal Segno al Coda command, indicating a return to the beginning and a continuation to the Coda object. The music resumes at a second Coda object. By default, repeatAfterJump is False, indicating that any repeats encountered on the Da Segno repeat not be repeated.

>>> rm = repeat.DaCapoAlCoda()

DalSegnoAlCoda bases

DalSegnoAlCoda read-only properties

Read-only properties inherited from Expression:

Read-only properties inherited from Music21Object:

Read-only properties inherited from ProtoM21Object:

DalSegnoAlCoda read/write properties

Read/write properties inherited from Music21Object:

DalSegnoAlCoda methods

Methods inherited from RepeatExpression:

Methods inherited from Music21Object:

Methods inherited from ProtoM21Object:

DalSegnoAlCoda instance variables

Instance variables inherited from Music21Object:

RepeatFinder

class music21.repeat.RepeatFinder(inpStream=None, defaultMeasureHashFunction=None)

An object for finding and simplifying repeated sections of music. Must be passed a stream which contains either measures or parts containing measures.

To collapse a repeated section, call RepeatFinder.simplify() and to see which sections of a piece are repeated, call either RepeatFinder.getMeasureSimilarityList() or RepeatFinder.getSimilarMeasureGroups (see below for full documentation).

If the internal stream passed to RepeatFinder is altered in any way (e.g. if you call simplify() with inplace=True) then to ensure proper functionality, you should use a new RepeatFinder object.

Below is an example of calling simplify on a Bach chorale.

>>> chorale = corpus.parse('bwv117.4.mxl')
>>> chorale.show()

Only the first 8 bars are displayed below

../_images/repeat-SimplifyExample_Chorale.PNG
>>> repeat.RepeatFinder(chorale).simplify().show()

The same chorale as before, but simplified

../_images/repeat-SimplifyExample_ChoraleSimplified.PNG

RepeatFinder methods

RepeatFinder.getMeasureSimilarityList()

Returns a list mList = [ [2, 3], [3], … ] such that measures i and j are the same (with i < j) if and only if mList[i] contains j. NOTE: this function refers to the very first measure as measure 0 regardless of whether s starts with measure 0 or 1 (i.e. treats a pickup bar as an entire measure).

For instance, if getMeasureSimilarityList returned [[4], [5], [6], [7, 8], [], [], [], [8], []], we would know that the first four measures repeat and the 4th, 8th, and 9th measures are the same.

Measures are considered the same if the defaultHash maps them to two values which are equal under the ‘==’ operator.

>>> chorale = corpus.parse('bwv154.3.mxl')

Expand the repeats:

>>> chorale = repeat.Expander(chorale.parts[0]).process()

Search for similarity:

>>> repeat.RepeatFinder(chorale).getMeasureSimilarityList()
[[4, 12], [5, 13], [6], [7], [12], [13], [], [], [], [], [], [], [], [], [], []]
>>> chorale2 = corpus.parse('bwv153.5.mxl')
>>> chorale2 = repeat.Expander(chorale2.parts[0]).process()
>>> repeat.RepeatFinder(chorale2).getMeasureSimilarityList()  # bwv153.5 has a pickup
[[5], [6], [7], [8], [9], [], [], [], [], [], [15], [], [], [], [19], [], [], [], [], []]
>>> hashFunction = lambda m : str(len(m))
>>> repeat.RepeatFinder(chorale.measures(1, 8),
...                     defaultMeasureHashFunction=hashFunction).getMeasureSimilarityList()
[[1, 2, 4, 5, 6, 8, 10], [2, 4, 5, 6, 8, 10], [4, 5, 6, 8, 10],
 [7, 9, 11], [5, 6, 8, 10], [6, 8, 10], [8, 10], [9, 11], [10], [11], [], []]
RepeatFinder.getQuarterLengthOfPickupMeasure()

Looks at RepeatFinder’s internal stream and returns the duration of the pickup bar in quarterLengths. If there is no pickup, returns 0.0.

Raises an exception if RepeatFinder’s internal stream is too short (i.e. fewer than 3 measures long)

>>> noPickup = corpus.parse('bwv10.7.mxl')
>>> repeat.RepeatFinder(noPickup).getQuarterLengthOfPickupMeasure()
0.0
>>> noPickup.parts[0].measures(0, 5).show()
../_images/repeat-rf_noPickup.PNG
>>> hasPickup = corpus.parse('bwv101.7.mxl')
>>> repeat.RepeatFinder(hasPickup).getQuarterLengthOfPickupMeasure()
1.0
>>> hasPickup.parts[0].measures(0, 2).show()
../_images/repeat-rf_hasPickup.PNG
>>> tooShort = noPickup.parts[0].measures(1, 2)
>>> repeat.RepeatFinder(tooShort).getQuarterLengthOfPickupMeasure()
Traceback (most recent call last):
music21.repeat.InsufficientLengthException: Cannot determine length
    of pickup given fewer than 3 measures
RepeatFinder.getSimilarMeasureGroups(threshold=1)

Returns a list of tuples containing information on repeated groups of measures.

Specifically, returns a list of tuples of the form (l1, l2) where l1 and l2 are lists of measure numbers such that measure l1[i] is the same as measure l2[i].

>>> chorale = corpus.parse('bwv117.4.mxl')

Expand repeats

>>> chorale = repeat.Expander(chorale.parts[0]).process()
>>> chorale.show()

Measures 0-4 are the same as measures 5-9.

../_images/repeat-SimplifyExample_Chorale.PNG
>>> repeat.RepeatFinder(chorale).getSimilarMeasureGroups()
[([0, 1, 2, 3, 4], [5, 6, 7, 8, 9]), ([1, 2, 3, 4, 5], [6, 7, 8, 9, 10]), ([0], [10])]

Notice that although measures 2-3 are the same as measures 6-7, we don’t have ([2, 3], [6, 7]) in our result, since ([1, 2, 3], [5, 6, 7]) already contains that information.

RepeatFinder.hasPickup()

Returns True when the RepeatFinder’s internal stream has a pickup bar.

Raises an exception if the internal stream is too short (i.e. fewer than 3 bars long).

>>> noPickup = corpus.parse('bwv10.7.mxl')
>>> repeat.RepeatFinder(noPickup).hasPickup()
False
>>> noPickup.parts[0].measures(0, 5).show()
../_images/repeat-rf_noPickup.PNG
>>> hasPickup = corpus.parse('bwv101.7.mxl')
>>> repeat.RepeatFinder(hasPickup).hasPickup()
True
>>> hasPickup.parts[0].measures(0, 2).show()
../_images/repeat-rf_hasPickup.PNG
RepeatFinder.simplify(repeatThreshold=4, repeatEndingThreshold=3, *, inPlace=False)

Takes the piece stored in the RepeatFinder object and collapses repeated sections by replacing them with repeat signs. Includes first and second endings where appropriate.

Only detects repeated sections which are repeatThreshold bars long and only detects repeat endings where the repeated sections is more than repeatEndingThreshold bars long. If inPlace is True, does not return a new music21 object, but instead alters the stream passed to the RepeatFinder object.

In the below example, we have an 8-measure stream where the last four measures are identical to the first four.

>>> s = stream.Stream()
>>> notes = [note.Note('D'), note.Note('E-'), note.Note('C'), note.Note('B3'),
...           note.Note('D'), note.Note('E-'), note.Note('C'), note.Note('B3')]
>>> for i in range(8):
...    m = stream.Measure()
...    m.number = i + 1
...    myNote = notes[i]
...    myNote.duration.quarterLength = 4.0
...    m.append(myNote)
...    s.append(m)
>>> s.show()
../_images/repeat-RepeatFinderDSCH.PNG
>>> s2 = repeat.RepeatFinder(s).simplify()
>>> s2.show()
../_images/repeat-RepeatFinderDSCHsimplified.PNG

RepeatFinder instance variables

RepeatFinder.correctMeasureNumbers

boolean whether measure numbers should be corrected

RepeatFinder.defaultHash

A function that takes a stream of notes and rests and returns a string or an integer such that two measures are equal if their hashes are equal under the ‘==’ operator

RepeatFinder.s

The internal stream which is being analyzed for repeated sections

Expander

class music21.repeat.Expander(streamObj: StreamType)

The Expander object can expand a single Part or Part-like Stream with repeats. Nested repeats given with Repeat objects, or repeats and sections designated with RepeatExpression objects, are all expanded.

This class is a utility processor. Direct usage is more commonly from the expandRepeats() method.

To use this object directly, call process() on the score

>>> s = converter.parse('tinynotation: 3/4 A2. C4 D E F2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(2).leftBarline = bar.Repeat(direction='start')
>>> s.measure(2).rightBarline = bar.Repeat(direction='end', times=3)
>>> s.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note A>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.bar.Repeat direction=start>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Repeat direction=end times=3>
{6.0} <music21.stream.Measure 3 offset=6.0>
    {0.0} <music21.note.Note F>
    {3.0} <music21.bar.Barline type=final>
>>> e = repeat.Expander(s)
>>> e.repeatBarsAreCoherent()
True
>>> s2 = e.process()
>>> s2.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note A>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{6.0} <music21.stream.Measure 2a offset=6.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{9.0} <music21.stream.Measure 2b offset=9.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{12.0} <music21.stream.Measure 3 offset=12.0>
    {0.0} <music21.note.Note F>
    {3.0} <music21.bar.Barline type=final>

Changed in v9: Expander must be initialized with a Stream object.

Expander methods

Expander.findInnermostRepeatIndices(streamObj)

Find the innermost repeat bars. Return raw index values. For a single measure, this could be [2] For many contiguous measures, this might be [2, 3, 4, 5]

The provided Stream must be a Stream only of Measures.

>>> s = converter.parse('tinynotation: 3/4 A2.  C4 D E   F2.    G4 a b   c2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(2).leftBarline = bar.Repeat(direction='start')
>>> s.measure(2).rightBarline = bar.Repeat(direction='end', times=3)
>>> s.measure(4).leftBarline = bar.Repeat(direction='start')
>>> s.measure(4).rightBarline = bar.Repeat(direction='end', times=2)
>>> e = repeat.Expander(s)
>>> e.findInnermostRepeatIndices(s)
[1]
>>> s.measure(2).rightBarline = None
>>> s.measure(4).leftBarline = None
>>> e2 = repeat.Expander(s)
>>> e2.findInnermostRepeatIndices(s)
[1, 2, 3]
Expander.getRepeatExpressionIndex(streamObj, target)

Return a list of index positions of a Measure given a stream of measures. This requires the provided stream to only have measures.

>>> s = converter.parse('tinynotation: 3/4 A2. C4 D E F2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(3).append(repeat.Segno())
>>> e = repeat.Expander(s)

getRepeatExpressionIndex returns the measureIndex not measure number

>>> e.getRepeatExpressionIndex(s.getElementsByClass(stream.Measure), 'Segno')
[2]
Expander.isExpandable() bool | None

Return True or False if this Stream is expandable, that is, if it has balanced repeats or sensible Da Capo or Dal Segno indications.

Return None if there’s nothing to expand (a third case…)

Expander.measureMap(returnType='index')

returns a list where for each measure in the expanded stream, the index of the measure in the original stream is given. if returnType = ‘measureNumber’ then the str(measureNumber) of the original instead of the index of the original is used – suffixes are important here for endings etc..

Inefficient, because the entire stream is expanded before making this call, rather than just seeing what needs to be expanded and returning that.

>>> s = converter.parse('tinynotation: 3/4 A2.  C4 D E   F2.    G4 a b   c2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(2).leftBarline = bar.Repeat(direction='start')
>>> s.measure(2).rightBarline = bar.Repeat(direction='end', times=3)
>>> s.measure(4).leftBarline = bar.Repeat(direction='start')
>>> s.measure(4).rightBarline = bar.Repeat(direction='end', times=2)
>>> e = repeat.Expander(s)
>>> e.measureMap()
[0, 1, 1, 1, 2, 3, 3, 4]
>>> e.measureMap(returnType='measureNumber')
['1', '2', '2a', '2b', '3', '4', '4a', '5']
Expander.process(deepcopy: bool = True) StreamType

This is the main call for Expander

Processes all repeats. Note that this processing only happens for Measures contained in the given Stream. Other objects in that Stream are neither processed nor copied.

if deepcopy is False then it will leave the stream in an unusual state, but acceptable if the source stream has already been deep-copied and will be discarded later

Expander.processInnermostRepeatBars(streamObj, repeatIndices=None, repeatTimes=None, returnExpansionOnly=False)

Process and return a new Stream of Measures, likely a Part.

If repeatIndices are given, only these indices will be copied. All the included indices must be listed, not just the start and end.

If returnExpansionOnly is True, only the expanded portion is returned, the rest of the Stream is not retained.

>>> s = converter.parse('tinynotation: 3/4 A2.  C4 D E   F2.    G4 a b   c2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(2).leftBarline = bar.Repeat(direction='start')
>>> s.measure(2).rightBarline = bar.Repeat(direction='end', times=3)
>>> s.measure(4).leftBarline = bar.Repeat(direction='start')
>>> s.measure(4).rightBarline = bar.Repeat(direction='end', times=2)

processInnermostRepeatBars only will expand the first set of repeats.

>>> e = repeat.Expander(s)
>>> s2 = e.processInnermostRepeatBars(s)
>>> s2.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
    {0.0} <music21.clef.BassClef>
    {0.0} <music21.meter.TimeSignature 3/4>
    {0.0} <music21.note.Note A>
{3.0} <music21.stream.Measure 2 offset=3.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{6.0} <music21.stream.Measure 2a offset=6.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{9.0} <music21.stream.Measure 2b offset=9.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note C>
    {1.0} <music21.note.Note D>
    {2.0} <music21.note.Note E>
    {3.0} <music21.bar.Barline type=double>
{12.0} <music21.stream.Measure 3 offset=12.0>
    {0.0} <music21.note.Note F>
{15.0} <music21.stream.Measure 4 offset=15.0>
    {0.0} <music21.bar.Repeat direction=start>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note A>
    {2.0} <music21.note.Note B>
    {3.0} <music21.bar.Repeat direction=end times=2>
{18.0} <music21.stream.Measure 5 offset=18.0>
    {0.0} <music21.note.Note C>
    {3.0} <music21.bar.Barline type=final>

Calling it again will complete the job, as .process() does

>>> s3 = e.processInnermostRepeatBars(s2)
>>> s3.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
...
{3.0} <music21.stream.Measure 2 offset=3.0>
...
{6.0} <music21.stream.Measure 2a offset=6.0>
...
{9.0} <music21.stream.Measure 2b offset=9.0>
...
{12.0} <music21.stream.Measure 3 offset=12.0>
...
{15.0} <music21.stream.Measure 4 offset=15.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note A>
    {2.0} <music21.note.Note B>
    {3.0} <music21.bar.Barline type=double>
{18.0} <music21.stream.Measure 4a offset=18.0>
    {0.0} <music21.bar.Barline type=double>
    {0.0} <music21.note.Note G>
    {1.0} <music21.note.Note A>
    {2.0} <music21.note.Note B>
    {3.0} <music21.bar.Barline type=double>
{21.0} <music21.stream.Measure 5 offset=21.0>
...

Should work even if no start repeat is given:

>>> s = converter.parse('tinynotation: 3/4 A2.  C4 D E   F2.    G4 a b   c2.')
>>> s.makeMeasures(inPlace=True)
>>> s.measure(2).rightBarline = bar.Repeat(direction='end')
>>> e = repeat.Expander(s)
>>> s2 = e.processInnermostRepeatBars(s)
>>> s2.show('text')
{0.0} <music21.stream.Measure 1 offset=0.0>
...
{3.0} <music21.stream.Measure 2 offset=3.0>
...
{6.0} <music21.stream.Measure 1a offset=6.0>
...
{9.0} <music21.stream.Measure 2a offset=9.0>
...
    {3.0} <music21.bar.Barline type=double>
{12.0} <music21.stream.Measure 3 offset=12.0>
...
{15.0} <music21.stream.Measure 4 offset=15.0>
...
{18.0} <music21.stream.Measure 5 offset=18.0>
...
    {3.0} <music21.bar.Barline type=final>
Expander.repeatBarsAreCoherent()

Check that all repeat bars are paired properly. Returns True or False

RepeatMark

class music21.repeat.RepeatMark

Base class of all repeat objects, including RepeatExpression objects and Repeat (Barline) objects.

This object is used for multiple-inheritance of such objects and to filter by class in order to get all things that mark repeats.

The RepeatMark is not itself a Music21Object so you should use multiple inheritance to put these things in Streams.

The following demonstration shows how a user might see if a Stream has any repeats in it.

>>> class PartialRepeat(repeat.RepeatMark, base.Music21Object):
...    def __init__(self, **keywords):
...        super().__init__(**keywords)
>>> s = stream.Stream()
>>> s.append(note.Note())
>>> s.append(PartialRepeat())
>>> repeats = s.getElementsByClass('RepeatMark')  # not a Music21Object, so use quotes
>>> if repeats:
...    print('Stream has %s repeat(s) in it' % (len(repeats)))
Stream has 1 repeat(s) in it

RepeatMark bases

RepeatMark read-only properties

Read-only properties inherited from ProtoM21Object:

RepeatMark methods

Methods inherited from ProtoM21Object:

Functions

music21.repeat.deleteMeasures(s, toDelete, *, inPlace=False, correctMeasureNumbers=True)

Given a Stream s and a list of numbers, toDelete, removes each measure with a number corresponding to a number in toDelete and then renumbers the remaining measures in the Stream.

TODO: Move to someplace more appropriate.

>>> from copy import deepcopy
>>> chorale1 = corpus.parse('bwv10.7.mxl')
>>> s = deepcopy(chorale1)
>>> repeat.deleteMeasures(s, [6, 3, 4], inPlace=True)
>>> m2 = search.translateStreamToString(chorale1.parts[1].measure(2).notesAndRests)
>>> resm2 = search.translateStreamToString(s.parts[1].measure(2).notesAndRests)
>>> m2 == resm2
True
>>> m5 = search.translateStreamToString(chorale1.parts[1].measure(5).notesAndRests)
>>> resm3 = search.translateStreamToString(s.parts[1].measure(3).notesAndRests)
>>> m5 == resm3
True
>>> m7 = search.translateStreamToString(chorale1.parts[1].measure(7).notesAndRests)
>>> resm4 = search.translateStreamToString(s.parts[1].measure(4).notesAndRests)
>>> m7 == resm4
True
>>> lenS = len(s.parts[0].getElementsByClass(stream.Measure))
>>> lenChorale1 = len(chorale1.parts[0].getElementsByClass(stream.Measure))
>>> lenS + 3 == lenChorale1
True
music21.repeat.insertRepeat(s, start, end, *, inPlace=False)

Given a stream s, inserts a start-repeat at the beginning of the bar specified by start and inserts an end-repeat at the bar specified by barEnd. Only alters the stream s if inPlace=True.

>>> from copy import deepcopy
>>> chorale1 = corpus.parse('bwv10.7.mxl')
>>> s = repeat.insertRepeat(chorale1, 3, 6, inPlace=False)
>>> m4 = search.translateStreamToString( chorale1.parts[1].measure(4).notesAndRests)
>>> resm4 = search.translateStreamToString( s.parts[1].measure(4).notesAndRests)
>>> m6 = search.translateStreamToString( chorale1.parts[1].measure(4).notesAndRests)
>>> resm6 = search.translateStreamToString( s.parts[1].measure(4).notesAndRests)
>>> m7 = search.translateStreamToString( chorale1.parts[1].measure(4).notesAndRests)
>>> resm7 = search.translateStreamToString( s.parts[1].measure(4).notesAndRests)
>>> m4 == resm4
True
>>> m6 == resm6
True
>>> m7 == resm7
True

We should have 2 repeats in each part (a start and end) for a total of 8 repeats

>>> len(s.parts[0].flatten().getElementsByClass(bar.Repeat))
2
>>> len(s[bar.Repeat])
8
>>> s.parts[0].measure(3).leftBarline.direction
'start'
>>> s.parts[0].measure(6).rightBarline.direction
'end'
music21.repeat.insertRepeatEnding(s, start, end, endingNumber: int = 1, *, inPlace=False)

Designates a range of measures as being repeated endings (i.e. first and second endings) within a stream s, where s either contains measures, or contains parts which contain measures. Start and end are integers corresponding to the first and last measure number of the “repeatNum” ending. e.g. if start=6, end=7, and repeatNum=2, the method adds a second ending from measures 6 to 7.

Does not (yet) add a RepeatMark to the end of the first ending.

Example: create first and second endings over measures 4-6 and measures 11-13 of a chorale, respectively.

>>> c1 = corpus.parse('bwv10.7.mxl')
>>> repeat.insertRepeatEnding(c1,  4,  6, 1, inPlace=True)
>>> repeat.insertRepeatEnding(c1, 11, 13, 2, inPlace=True)

We now have 8 repeatBrackets since each part gets its own first and second ending.

>>> repeatBrackets = c1.flatten().getElementsByClass(spanner.RepeatBracket)
>>> len(repeatBrackets)
8
>>> len(c1.parts.first().getElementsByClass(spanner.RepeatBracket))
2