music21.base¶
music21.base is what you get in music21 if you type import music21
. It
contains all the most low-level objects that also appear in the music21 module
(i.e., music21.base.Music21Object is the same as music21.Music21Object).
Music21 base classes for Stream
objects and all
elements contained within them including Notes, etc.. Additional objects for
defining and manipulating elements are included.
The namespace of this file, as all base.py files, is loaded into the package that contains this file via __init__.py. Everything in this file is thus available after importing music21.
>>> import music21
>>> music21.Music21Object
<class 'music21.base.Music21Object'>
>>> music21.VERSION_STR
'2.0.11'
Alternatively, after doing a complete import, these classes are available under the module “base”:
>>> base.Music21Object
<class 'music21.base.Music21Object'>
Music21Object¶
-
class
music21.base.
Music21Object
(*arguments, **keywords)¶ Base class for all music21 objects.
All music21 objects have seven pieces of information:
- id: identification string unique to the objects container (optional)
- groups: a Groups object: which is a list of strings identifying internal subcollections (voices, parts, selections) to which this element belongs
- duration: Duration object representing the length of the object
- activeSite: a weakreference to the currently active Location
- offset: a floating point value, generally in quarter lengths, specifying the position of the object in a site.
- priority: int representing the position of an object among all objects at the same offset.
- sites: a Sites object that stores all the Streams and Contexts that an object is in.
Contexts, locations, and offsets are stored in a
Sites
object. Locations specify connections of this object to one location in a Stream subclass. Contexts are weakrefs for current objects that are associated with this object (similar to locations but without an offset)Each of these may be passed in as a named keyword to any music21 object.
Some of these may be intercepted by the subclassing object (e.g., duration within Note)
Music21Object
read-only properties
-
Music21Object.
beat
¶ Return the beat of this object as found in the most recently positioned Measure. Beat values count from 1 and contain a floating-point designation between 0 and 1 to show proportional progress through the beat.
>>> n = note.Note() >>> n.quarterLength = .5 >>> m = stream.Measure() >>> m.timeSignature = meter.TimeSignature('3/4') >>> m.repeatAppend(n, 6) >>> [m.notes[i].beat for i in range(6)] [1.0, 1.5, 2.0, 2.5, 3.0, 3.5]
>>> m.timeSignature = meter.TimeSignature('6/8') >>> [m.notes[i].beat for i in range(6)] [1.0, Fraction(4, 3), Fraction(5, 3), 2.0, Fraction(7, 3), Fraction(8, 3)]
>>> s = stream.Stream() >>> s.insert(0, meter.TimeSignature('3/4')) >>> s.repeatAppend(note.Note(), 8) >>> [n.beat for n in s.notes] [1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0]
>>> s = stream.Stream() >>> ts = meter.TimeSignature('4/4') >>> s.insert(0, ts) >>> n = note.Note(type='eighth') >>> s.repeatAppend(n, 8) >>> s.makeMeasures(inPlace = True) >>> [n.beat for n in s.flat.notes] [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
-
Music21Object.
beatDuration
¶ Return a
Duration
of the beat active for this object as found in the most recently positioned Measure.If extending beyond the Measure, or in a Stream with a TimeSignature, the meter modulus value will be returned.
>>> n = note.Note() >>> n.quarterLength = .5 >>> m = stream.Measure() >>> m.timeSignature = meter.TimeSignature('3/4') >>> m.repeatAppend(n, 6) >>> [m.notes[i].beatDuration.quarterLength for i in range(6)] [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
>>> m.timeSignature = meter.TimeSignature('6/8') >>> [m.notes[i].beatDuration.quarterLength for i in range(6)] [1.5, 1.5, 1.5, 1.5, 1.5, 1.5]
>>> s = stream.Stream() >>> s.insert(0, meter.TimeSignature('2/4+3/4')) >>> s.repeatAppend(note.Note(), 8) >>> [n.beatDuration.quarterLength for n in s.notes] [2.0, 2.0, 3.0, 3.0, 3.0, 2.0, 2.0, 3.0]
-
Music21Object.
beatStr
¶ Return a string representation of the beat of this object as found in the most recently positioned Measure. Beat values count from 1 and contain a fractional designation to show progress through the beat.
>>> n = note.Note() >>> n.quarterLength = .5 >>> m = stream.Measure() >>> m.timeSignature = meter.TimeSignature('3/4') >>> m.repeatAppend(n, 6) >>> [m.notes[i].beatStr for i in range(6)] ['1', '1 1/2', '2', '2 1/2', '3', '3 1/2'] >>> m.timeSignature = meter.TimeSignature('6/8') >>> [m.notes[i].beatStr for i in range(6)] ['1', '1 1/3', '1 2/3', '2', '2 1/3', '2 2/3']
>>> s = stream.Stream() >>> s.insert(0, meter.TimeSignature('3/4')) >>> s.repeatAppend(note.Note(), 8) >>> [n.beatStr for n in s.notes] ['1', '2', '3', '1', '2', '3', '1', '2']
-
Music21Object.
beatStrength
¶ Return the metrical accent of this object in the most recently positioned Measure. Accent values are between zero and one, and are derived from the local TimeSignature’s accent MeterSequence weights. If the offset of this object does not match a defined accent weight, a minimum accent weight will be returned.
>>> n = note.Note() >>> n.quarterLength = .5 >>> m = stream.Measure() >>> m.timeSignature = meter.TimeSignature('3/4') >>> m.repeatAppend(n, 6) >>> [m.notes[i].beatStrength for i in range(6)] [1.0, 0.25, 0.5, 0.25, 0.5, 0.25]
>>> m.timeSignature = meter.TimeSignature('6/8') >>> [m.notes[i].beatStrength for i in range(6)] [1.0, 0.25, 0.25, 0.5, 0.25, 0.25]
We can also get the beatStrength for elements not in a measure, if the enclosing stream has a
TimeSignature
. We just assume that the time signature carries through to hypothetical following measures:>>> n = note.Note('E--3', type='quarter') >>> s = stream.Stream() >>> s.insert(0.0, meter.TimeSignature('2/2')) >>> s.repeatAppend(n, 12) >>> [s.notes[i].beatStrength for i in range(12)] [1.0, 0.25, 0.5, 0.25, 1.0, 0.25, 0.5, 0.25, 1.0, 0.25, 0.5, 0.25]
Changing the meter changes the output, of course:
>>> s.insert(4.0, meter.TimeSignature('3/4')) >>> [s.notes[i].beatStrength for i in range(12)] [1.0, 0.25, 0.5, 0.25, 1.0, 0.5, 0.5, 1.0, 0.5, 0.5, 1.0, 0.5]
Test not using measures
>>> n = note.Note("E--3") >>> n.quarterLength = 2 >>> s = stream.Stream() >>> s.isMeasure False >>> s.insert(0, meter.TimeSignature('2/2')) >>> s.repeatAppend(n, 16) >>> s.notes[0].beatStrength 1.0 >>> s.notes[1].beatStrength 0.5 >>> s.notes[4].beatStrength 1.0 >>> s.notes[5].beatStrength 0.5
-
Music21Object.
classes
¶ Returns a list containing the names (strings, not objects) of classes that this object belongs to – starting with the object’s class name and going up the mro() for the object. Very similar to Perl’s @ISA array:
>>> q = note.Note() >>> q.classes ['Note', 'NotRest', 'GeneralNote', 'Music21Object', 'object']
Having quick access to these things as strings makes it easier to do comparisons:
Example: find GClefs that are not Treble clefs (or treble 8vb, etc.):
>>> s = stream.Stream() >>> s.insert(10, clef.GClef()) >>> s.insert(20, clef.TrebleClef()) >>> s.insert(30, clef.FrenchViolinClef()) >>> s.insert(40, clef.Treble8vbClef()) >>> s.insert(50, clef.BassClef()) >>> s2 = stream.Stream() >>> for t in s: ... if 'GClef' in t.classes and 'TrebleClef' not in t.classes: ... s2.insert(t) >>> s2.show('text') {10.0} <music21.clef.GClef> {30.0} <music21.clef.FrenchViolinClef>
-
Music21Object.
containerHierarchy
¶ Return a list of Stream subclasses that this Stream is contained within or derived from. This provides a way of seeing Streams contained within Streams.
>>> s = corpus.parse('bach/bwv66.6') >>> [e for e in s[1][2][3].containerHierarchy] [<music21.stream.Measure 1 offset=1.0>, <music21.stream.Part Soprano>, <music21.stream.Score ...>]
Note that derived objects also can follow the container hierarchy:
>>> import copy >>> n2 = copy.deepcopy(s[1][2][3]) >>> [e for e in s[1][2][3].containerHierarchy] [<music21.stream.Measure 1 offset=1.0>, <music21.stream.Part Soprano>, <music21.stream.Score ...>]
-
Music21Object.
derivation
¶ Return the
Derivation
object for this element.Or create one if none exists:
>>> n = note.Note() >>> n.derivation <Derivation of <music21.note.Note C> from None via "None"> >>> import copy >>> n2 = copy.deepcopy(n) >>> n2.pitch.step = 'D' # for seeing easier... >>> n2.derivation <Derivation of <music21.note.Note D> from <music21.note.Note C> via "__deepcopy__"> >>> n2.derivation.origin is n True
Note that (for now at least) derivation.origin is NOT a weakref:
>>> del n >>> n2.derivation <Derivation of <music21.note.Note D> from <music21.note.Note C> via "__deepcopy__"> >>> n2.derivation.origin <music21.note.Note C>
-
Music21Object.
fullyQualifiedClasses
¶ Similar to .classes, returns a list containing the names (strings, not objects) of classes with the full package name that this object belongs to – starting with the object’s class name and going up the mro() for the object. Very similar to Perl’s @ISA array:
>>> q = note.Note() >>> q.fullyQualifiedClasses ['music21.note.Note', 'music21.note.NotRest', 'music21.note.GeneralNote', 'music21.base.Music21Object', '...builtin...object']
The last one (object) will be different in Py2 (__builtin__.object) and Py3 (builtins.object)
-
Music21Object.
isGrace
¶ Return True or False if this music21 object has a GraceDuration.
>>> n = note.Note() >>> n.isGrace False >>> ng = n.getGrace() >>> ng.isGrace True
-
Music21Object.
measureNumber
¶ Return the measure number of a
Measure
that contains this object if the object is in a measure.Returns None if the object is not in a measure. Also note that by default Measure objects have measure number 0.
If an object belongs to multiple measures (not in the same hierarchy...) then it returns the measure number of the
activeSite()
if that is aMeasure
object. Otherwise it will usegetContextByClass()
to find the number of the measure it was most recently added to.>>> m = stream.Measure() >>> m.number = 12 >>> n = note.Note() >>> m.append(n) >>> n.measureNumber 12
>>> n2 = note.Note() >>> n2.measureNumber is None True >>> m2 = stream.Measure() >>> m2.append(n2) >>> n2.measureNumber 0
This updates live if the measure number changes:
>>> m2.number = 11 >>> n2.measureNumber 11
The most recent measure added to is used unless activeSite is a measure:
>>> m.append(n2) >>> n2.measureNumber 12 >>> n2.activeSite = m2 >>> n2.measureNumber 11
Music21Object
read/write properties
-
Music21Object.
activeSite
¶ A reference to the most-recent object used to contain this object. In most cases, this will be a Stream or Stream sub-class. In most cases, an object’s activeSite attribute is automatically set when an the object is attached to a Stream.
>>> n = note.Note("C#4") >>> p = stream.Part() >>> p.insert(20.0, n) >>> n.activeSite is p True >>> n.offset 20.0
>>> m = stream.Measure() >>> m.insert(10.0, n) >>> n.activeSite is m True >>> n.offset 10.0 >>> n.activeSite = p >>> n.offset 20.0
-
Music21Object.
duration
¶ Get and set the duration of this object as a Duration object.
-
Music21Object.
offset
¶ The offset property sets or returns the position of this object as a float or fractions.Fraction value (generally in quarterLengths), depending on what is representable.
Offsets are measured from the start of the object’s activeSite, that is, the most recently referenced Stream or Stream subclass such as Part, Measure, or Voice. It is a simpler way of calling o.getOffsetBySite(o.activeSite, returnType=’rational’).
If we put a Note into a Stream, we will see the activeSite changes.
>>> import fractions >>> n1 = note.Note("D#3") >>> n1.activeSite is None True
>>> m1 = stream.Measure() >>> m1.number = 4 >>> m1.insert(10.0, n1) >>> n1.offset 10.0 >>> n1.activeSite <music21.stream.Measure 4 offset=0.0>
>>> n1.activeSite is m1 True
The most recently referenced Stream becomes an object’s activeSite and thus the place where .offset looks to find its number.
>>> m2 = stream.Measure() >>> m2.insert(3.0/5, n1) >>> m2.number = 5 >>> n1.offset Fraction(3, 5) >>> n1.activeSite is m2 True
Notice though that .offset depends on the .activeSite which is the most recently accessed/referenced Stream.
Here we will iterate over the elements in m1 and we will see that the .offset of n1 now is its offset in m1 even though we haven’t done anything directly to n1. Simply iterating over a site is enough to change the .activeSite of its elements:
>>> for element in m1: ... pass >>> n1.offset 10.0
The property can also set the offset for the object if no container has been set:
>>> n1 = note.Note() >>> n1.id = 'hi' >>> n1.offset = 20/3. >>> n1.offset Fraction(20, 3) >>> n1.offsetFloat 6.666...
>>> s1 = stream.Stream() >>> s1.append(n1) >>> n1.offset 0.0 >>> s2 = stream.Stream() >>> s2.insert(30.5, n1) >>> n1.offset 30.5
After calling getElementById on s1, the returned element’s offset will be its offset in s1.
>>> n2 = s1.getElementById('hi') >>> n2 is n1 True >>> n2.offset 0.0
Iterating over the elements in a Stream will make its offset be the offset in iterated Stream.
>>> for thisElement in s2: ... thisElement.offset 30.5
When in doubt, use .getOffsetBySite(streamObj) which is safer.
-
Music21Object.
offsetFloat
¶ old style: always returns a float
-
Music21Object.
offsetRational
¶ synonym for .offset
-
Music21Object.
priority
¶ Get and set the priority integer value.
Priority specifies the order of processing from left (lowest number) to right (highest number) of objects at the same offset. For instance, if you want a key change and a clef change to happen at the same time but the key change to appear first, then set: keySigElement.priority = 1; clefElement.priority = 2 this might be a slightly counterintuitive numbering of priority, but it does mean, for instance, if you had two elements at the same offset, an allegro tempo change and an andante tempo change, then the tempo change with the higher priority number would apply to the following notes (by being processed second).
Default priority is 0; thus negative priorities are encouraged to have Elements that appear non-priority set elements.
In case of tie, there are defined class sort orders defined in music21.base.classSortOrder. For instance, a key signature change appears before a time signature change before a note at the same offset. This produces the familiar order of materials at the start of a musical score.
>>> import music21 >>> a = music21.Music21Object() >>> a.priority = 3 >>> a.priority = 'high' Traceback (most recent call last): ElementException: priority values must be integers.
-
Music21Object.
quarterLength
¶ Set or Return the Duration as represented in Quarter Length, possibly as a fraction
note: the setter is identical to .quarterLengthFloat
>>> n = note.Note() >>> n.quarterLength = 2.0 >>> n.quarterLength 2.0 >>> n.quarterLength = 1.0/3 >>> n.quarterLength Fraction(1, 3)
-
Music21Object.
quarterLengthFloat
¶ Set or Return the Duration as represented in Quarter Length as a float
>>> n = note.Note() >>> n.quarterLengthFloat = 2.0 >>> n.quarterLengthFloat 2.0 >>> n.quarterLengthFloat = 1.0/3 >>> n.quarterLengthFloat 0.333...
-
Music21Object.
seconds
¶ Get or set the duration of this object in seconds, assuming that this object has a
MetronomeMark
orMetricModulation
in its past context.>>> s = stream.Stream() >>> s.repeatAppend(note.Note(), 12) >>> s.insert(0, tempo.MetronomeMark(number=120)) >>> s.insert(6, tempo.MetronomeMark(number=240)) >>> [n.seconds for n in s.notes] [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25]
Music21Object
methods
-
Music21Object.
contextSites
(callerFirst=None, memo=None, offsetAppend=0.0, sortByCreationTime=False, priorityTarget=None)¶ A generator that returns a list of tuples of sites to search for a context...
Each tuple contains a Stream object, the offset of this element in that Stream, and the method of searching that should be applied to search for a context. These methods are:
- ‘flatten’ – flatten the stream and then look from this offset backwards.
- ‘elementsOnly’ – only search the stream’s personal elements from this offset backwards
- ‘elementsFirst’ – search this stream backwards, and then flatten and search backwards
>>> c = corpus.parse('bwv66.6') >>> c.id = 'bach' >>> n = c[2][4][2] >>> n <music21.note.Note G#> >>> for y in n.contextSites(): ... print(y) (<music21.stream.Measure 3 offset=9.0>, 0.5, 'elementsFirst') (<music21.stream.Part Alto>, 9.5, 'flatten') (<music21.stream.Score bach>, 9.5, 'elementsOnly') >>> m = c[2][4] >>> m <music21.stream.Measure 3 offset=9.0> >>> for y in m.contextSites(): ... print(y) (<music21.stream.Measure 3 offset=9.0>, 0.0, 'elementsFirst') (<music21.stream.Part Alto>, 9.0, 'flatten') (<music21.stream.Score bach>, 9.0, 'elementsOnly')
>>> import copy >>> m2 = copy.deepcopy(m) >>> m2.number = 3333 >>> for y in m2.contextSites(): ... print(y) (<music21.stream.Measure 3333 offset=0.0>, 0.0, 'elementsFirst') (<music21.stream.Part Alto>, 9.0, 'flatten') (<music21.stream.Score bach>, 9.0, 'elementsOnly')
>>> tempPartStream = c.parts >>> tempPartStream.id = 'partStream' # for identificationBelow >>> m3 = tempPartStream[1].measure(3) >>> for y in m3.contextSites(): ... print(y) (<music21.stream.Measure 3 offset=9.0>, 0.0, 'elementsFirst') (<music21.stream.Part Alto>, 9.0, 'flatten') (<music21.stream.Score partStream>, 9.0, 'elementsOnly') (<music21.stream.Score bach>, 9.0, 'elementsOnly')
Sorting order:
>>> p1 = stream.Part() >>> p1.id = 'p1' >>> m1 = stream.Measure() >>> m1.number = 1 >>> n = note.Note() >>> m1.append(n) >>> p1.append(m1) >>> for y in n.contextSites(): ... print(y[0]) <music21.stream.Measure 1 offset=0.0> <music21.stream.Part p1>
>>> p2 = stream.Part() >>> p2.id = 'p2' >>> m2 = stream.Measure() >>> m2.number = 2 >>> m2.append(n) >>> p2.append(m2)
The keys could have appeared in any order, but by default we set set priorityTarget to activeSite. So this is the same as omitting.
>>> for y in n.contextSites(priorityTarget=n.activeSite): ... print(y[0]) <music21.stream.Measure 2 offset=0.0> <music21.stream.Part p2> <music21.stream.Measure 1 offset=0.0> <music21.stream.Part p1>
Or sort by creationTime...
>>> for y in n.contextSites(sortByCreationTime = True): ... print(y[0]) <music21.stream.Measure 2 offset=0.0> <music21.stream.Part p2> <music21.stream.Measure 1 offset=0.0> <music21.stream.Part p1>
oldest first...
>>> for y in n.contextSites(sortByCreationTime='reverse'): ... print(y[0]) <music21.stream.Measure 1 offset=0.0> <music21.stream.Part p1> <music21.stream.Measure 2 offset=0.0> <music21.stream.Part p2>
-
Music21Object.
findAttributeInHierarchy
(attrName)¶ If this element is contained within a Stream (or other Music21 element), findAttributeInHierarchy() searches the attributes of the activeSite for this attribute and returns its value.
If the activeSite does not have this attribute then we search its activeSite and up through the hierarchy until we find a value for this attribute. Or it Returns None if there is no match.
>>> m = stream.Measure() >>> m.number = 12 >>> n = note.Note() >>> m.append(n) >>> n.activeSite is m True >>> n.findAttributeInHierarchy('number') 12 >>> print(n.findAttributeInHierarchy('elephant')) None
Recursive searches also work. Here, the Score object is the only one with a ‘parts’ attribute.
>>> p1 = stream.Part() >>> p1.insert(0, m) >>> p2 = stream.Part() >>> s = stream.Score() >>> s.insert(0, p1) >>> s.insert(0, p2) >>> n.activeSite.activeSite is p1 True >>> n.activeSite.activeSite.activeSite is s True
>>> parts = n.findAttributeInHierarchy('parts') >>> (parts[0] is p1, parts[1] is p2) (True, True)
-
Music21Object.
getAllContextsByClass
(className, found=None, idFound=None, memo=None)¶ Search both Sites as well as associated objects to find all matching classes. Returns [] if not match is found.
DEPRECATED possibly May 2014: Not sure if it works well...
-
Music21Object.
getContextAttr
(attr)¶ Given the name of an attribute, search the Sites object for contexts having this attribute and return the best match.
>>> import music21 >>> class Mock(music21.Music21Object): ... attr1 = 234 >>> aObj = Mock() >>> aObj.attr1 = 'test' >>> a = music21.Music21Object() >>> a.sites.add(aObj) >>> a.getContextAttr('attr1') 'test'
-
Music21Object.
getContextByClass
(className, callerFirst=None, getElementMethod='getElementAtOrBefore', memo=None, serialReverseSearch=True, sortByCreationTime=False)¶ A very powerful method in music21 of fundamental importance: Returns the element matching the className that is closest to this element in its current hierarchy. For instance, take this stream of changing time signatures:
>>> s1 = converter.parse('tinynotation: 3/4 C4 D E 2/4 F G A B 1/4 c') >>> s2 = s1.makeMeasures() >>> s2.__class__ = stream.Part >>> s2.show('t') {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 C> {1.0} <music21.note.Note D> {2.0} <music21.note.Note E> {3.0} <music21.stream.Measure 2 offset=3.0> {0.0} <music21.meter.TimeSignature 2/4> {0.0} <music21.note.Note F> {1.0} <music21.note.Note G> {5.0} <music21.stream.Measure 3 offset=5.0> {0.0} <music21.note.Note A> {1.0} <music21.note.Note B> {7.0} <music21.stream.Measure 4 offset=7.0> {0.0} <music21.meter.TimeSignature 1/4> {0.0} <music21.note.Note C> {1.0} <music21.bar.Barline style=final>
Let’s get the last two notes of the piece, the B and high c:
>>> c = s2.measure(4).notes[0] >>> c <music21.note.Note C>
>>> b = s2.measure(3).notes[-1] >>> b <music21.note.Note B>
Now when we run getContextByClass(‘TimeSignature’) on c, we get a time signature of 1/4.
>>> c.getContextByClass('TimeSignature') <music21.meter.TimeSignature 1/4>
Doing what we just did wouldn’t be hard to do with other methods, though getContextByClass makes it easier. But the time signature context for b would be much harder to get without this method, since in order to do it, it searches backwards within the measure, finds that there’s nothing there. It goes to the previous measure and searches that one backwards until it gets the proper TimeSignature of 2/4:
>>> b.getContextByClass('TimeSignature') <music21.meter.TimeSignature 2/4>
The method is smart enough to stop when it gets to the beginning of the part. This is all you need to know for most uses. The rest of the docs are for advanced uses:
The methods searches both Sites as well as associated objects to find a matching class. Returns None if not match is found.
A reference to the caller is required to find the offset of the object of the caller. This is needed for serialReverseSearch.
The caller may be a Sites reference from a lower-level object. If so, we can access the location of that lower-level object. However, if we need a flat representation, the caller needs to be the source Stream, not its Sites reference.
The callerFirst is the first object from which this method was called. This is needed in order to determine the final offset from which to search.
The getElementMethod is a string that selects which Stream method is used to get elements for searching. The strings ‘getElementAtOrBefore’ and ‘getElementBeforeOffset’ are currently accepted.
-
Music21Object.
getOffsetBySite
(site, returnType='rational', stringReturns=False)¶ If this class has been registered in a container such as a Stream, that container can be provided here, and the offset in that object can be returned.
Note that this is different than the elementOffset() method on Stream in that this can never access the flat representation of a Stream.
>>> n = note.Note('A-4') # a Music21Objecct >>> n.offset = 30 >>> n.getOffsetBySite(None) 30.0
>>> s1 = stream.Stream() >>> s1.id = 'containingStream' >>> s1.insert(20.0/3, n) >>> n.getOffsetBySite(s1) Fraction(20, 3) >>> n.getOffsetBySite(s1, returnType='float') 6.6666...
n.getOffsetBySite(None) should still return 30.0
>>> n.getOffsetBySite(None) 30.0
If the Stream does not contain the element then a SitesException is raised:
>>> s2 = stream.Stream() >>> s2.id = 'notContainingStream' >>> n.getOffsetBySite(s2) Traceback (most recent call last): SitesException: an entry for this object <music21.note.Note A-> is not stored in stream <music21.stream.Stream notContainingStream>
If the object is stored at the end of the Stream, then the highest time is usually returned:
>>> s3 = stream.Stream() >>> n3 = note.Note(type='whole') >>> s3.append(n3) >>> rb = bar.Barline() >>> s3.storeAtEnd(rb) # s3.rightBarline = rb would do the same... >>> rb.getOffsetBySite(s3) 4.0
However, setting stringReturns to True will return ‘highestTime’
>>> s3._endElements [<music21.bar.Barline style=regular>]
>>> rb.getOffsetBySite(s3, stringReturns=True) 'highestTime'
Normal numbers are still returned as a float or Fraction:
>>> n3.getOffsetBySite(s3, stringReturns=True) 0.0
-
Music21Object.
getSpannerSites
(spannerClassList=None)¶ Return a list of all
Spanner
objects (or Spanner subclasses) that contain this element. This method provides a way for objects to be aware of what Spanners they reside in. Note that Spanners are not Streams but specialized Music21Objects that use a Stream subclass, SpannerStorage, internally to keep track of the elements that are spanned.>>> n1 = note.Note('C4') >>> n2 = note.Note('D4') >>> sp1 = spanner.Slur(n1, n2) >>> n1.getSpannerSites() == [sp1] True
Note that not all Spanners are in the spanner module. They tend to reside in modules closer to their musical function:
>>> sp2 = dynamics.Crescendo(n2, n1)
The order that Spanners are returned is usually the order they were created, but on fast computers there can be ties, so use a set comparison if you expect multiple:
>>> set(n2.getSpannerSites()) == set([sp1, sp2]) True
Optionally a class name or list of class names can be specified and only Spanners of that class will be returned
>>> sp3 = dynamics.Diminuendo(n1, n2) >>> n2.getSpannerSites('Diminuendo') == [sp3] True
A larger class name can be used to get all subclasses:
>>> set(n2.getSpannerSites('DynamicWedge')) == set([sp2, sp3]) True >>> set(n2.getSpannerSites(['Slur','Diminuendo'])) == set([sp1, sp3]) True
>>> set(n2.getSpannerSites(['Slur','Diminuendo'])) == set([sp3, sp1]) True
Example: see which pairs of notes are in the same slur.
>>> n3 = note.Note('E4') >>> sp4 = spanner.Slur(n1, n3)
>>> for n in [n1, n2, n3]: ... for nOther in [n1, n2, n3]: ... if n is nOther: ... continue ... nSlurs = n.getSpannerSites('Slur') ... nOtherSlurs = nOther.getSpannerSites('Slur') ... for thisSlur in nSlurs: ... if thisSlur in nOtherSlurs: ... print("%s shares a slur with %s" % (n.name, nOther.name)) C shares a slur with D C shares a slur with E D shares a slur with C E shares a slur with C
-
Music21Object.
hasSite
(other)¶ Return True if other is a site in this Music21Object
Matches on id(other)
>>> s = stream.Stream() >>> n = note.Note() >>> s.append(n) >>> n.hasSite(s) True >>> n.hasSite(stream.Stream()) False
-
Music21Object.
isClassOrSubclass
(classFilterList)¶ Given a class filter list (a list or tuple must be submitted), which may have strings or class objects, determine if this class is of the provided classes or a subclasses.
NOTE: this is a performance critical operation for performance, only accept lists or tuples
-
Music21Object.
mergeAttributes
(other)¶ Merge all elementary, static attributes. Namely, id and groups attributes from another music21 object. Can be useful for copy-like operations.
>>> m1 = base.Music21Object() >>> m2 = base.Music21Object() >>> m1.id = 'music21Object1' >>> m1.groups.append("group1") >>> m2.mergeAttributes(m1) >>> m2.id 'music21Object1' >>> "group1" in m2.groups True
-
Music21Object.
next
(classFilterList=None, flattenLocalSites=False, beginNearest=True)¶ Get the next element found in the activeSite (or other Sites) of this Music21Object.
The classFilterList can be used to specify one or more classes to match.
The flattenLocalSites parameter determines if the sites of this element (e.g., a Measure’s Part) are flattened on first search. When True, elements contained in adjacent containers may be selected first.
>>> s = corpus.parse('bwv66.6') >>> s.parts[0].measure(3).next() == s.parts[0].measure(4) True >>> s.parts[0].measure(3).next('Note', flattenLocalSites=True) == s.parts[0].measure(3).notes[0] True
-
Music21Object.
previous
(classFilterList=None, flattenLocalSites=False, beginNearest=True)¶ Get the previous element found in the activeSite or other .sites of this Music21Object.
The classFilterList can be used to specify one or more classes to match.
The flattenLocalSites parameter determines if the sites of this element (e.g., a Measure’s Part) are flattened on first search. When True, elements contained in adjacent containers may be selected first.
>>> s = corpus.parse('bwv66.6') >>> m2 = s.parts[0].measure(2) >>> m3 = s.parts[0].measure(3) >>> m3.previous() is m2 True >>> m3.previous('Note', flattenLocalSites=True) is m2.notes[-1] True
TODO: Try: l = corpus.parse(‘luca/gloria’); for el in l.recurse: print(el, el.previous(‘Note’)) SLOWEST THING EVER! why????
-
Music21Object.
purgeLocations
(rescanIsDead=False)¶ Remove references to all locations in objects that no longer exist.
-
Music21Object.
purgeOrphans
(excludeStorageStreams=True)¶ A Music21Object may, due to deep copying or other reasons, have contain a site (with an offset); yet, that site may no longer contain the Music21Object. These lingering sites are called orphans. This methods gets rid of them.
The excludeStorageStreams are SpannerStorage and VariantStorage.
-
Music21Object.
removeLocationBySite
(site)¶ DEPRECATED Feb 2016: use self.sites.remove() instead and set activeSite manually.
Remove a location in the
Sites
object.This is only for advanced location method and is not a complete or sufficient way to remove an object from a Stream.
-
Music21Object.
setContextAttr
(attrName, value)¶ Given the name of an attribute, search Contexts and return the best match.
>>> import music21 >>> class Mock(music21.Music21Object): ... attr1 = 234 >>> aObj = Mock() >>> aObj.attr1 = 'test' >>> a = music21.Music21Object() >>> a.sites.add(aObj) >>> a.getContextAttr('attr1') 'test' >>> a.setContextAttr('attr1', 3000) >>> a.getContextAttr('attr1') 3000
-
Music21Object.
setOffsetBySite
(site, value)¶ Change the offset for a site. These are equivalent:
n1.setOffsetBySite(stream1, 20)and
stream1.setElementOffset(n1, 20)>>> import music21 >>> aSite = stream.Stream() >>> a = music21.Music21Object() >>> a.sites.add(aSite) >>> aSite.setElementOffset(a, 20) >>> a.setOffsetBySite(aSite, 30) >>> a.getOffsetBySite(aSite) 30.0
-
Music21Object.
show
(fmt=None, app=None, **keywords)¶ Displays an object in a format provided by the fmt argument or, if not provided, the format set in the user’s Environment
- Valid formats include (but are not limited to)::
- musicxml text midi lily (or lilypond) lily.png lily.pdf lily.svg braille vexflow musicxml.png
N.B. score.write(‘lily’) returns a bare lilypond file, score.show(‘lily’) runs it through lilypond and displays it as a png.
-
Music21Object.
sortTuple
(useSite=False)¶ Returns a collections.namedtuple called SortTuple(atEnd, offset, priority, classSortOrder, isNotGrace, insertIndex) which contains the six elements necessary to determine the sort order of any set of objects in a Stream.
1) atEnd = {0, 1}; Elements specified to always stay at the end of a stream (
stream.storeAtEnd
) sort after normal elements.2) offset = float; Offset (with respect to the active site) is the next and most important parameter in determining the order of elements in a stream (the note on beat 1 has offset 0.0, while the note on beat 2 might have offset 1.0).
3) priority = int; Priority is a user-specified property (default 0) that can set the order of elements which have the same offset (for instance, two Parts both at offset 0.0).
4) classSortOrder = int or float; ClassSortOrder is the third level of comparison that gives an ordering to elements with different classes, ensuring, for instance that Clefs (classSortOrder = 0) sort before Notes (classSortOrder = 20).
- isNotGrace = {0, 1}; 0 = grace, 1 = normal. Grace notes sort before normal notes
6) The last tie breaker is the creation time (insertIndex) of the site object represented by the activeSite.
>>> n = note.Note() >>> n.offset = 4.0 >>> n.priority = -3 >>> n.sortTuple() SortTuple(atEnd=0, offset=4.0, priority=-3, classSortOrder=20, isNotGrace=1, insertIndex=0) >>> st = n.sortTuple()
Check that all these values are the same as above...
>>> st.offset == n.offset True >>> st.priority == n.priority True
An object’s classSortOrder comes from the Class object itself:
>>> st.classSortOrder == note.Note.classSortOrder True
Inserting the note into the Stream will set the insertIndex. Most implementations of music21 will use a global counter rather than an actual timer. Note that this is a last resort, but useful for things such as mutiple Parts inserted in order. It changes with each run, so we can’t display it here...
>>> s = stream.Stream() >>> s.insert(n) >>> n.sortTuple() SortTuple(atEnd=0, offset=4.0, priority=-3, classSortOrder=20, isNotGrace=1, insertIndex=...) >>> nInsertIndex = n.sortTuple().insertIndex
If we create another nearly identical note, the insertIndex will be different:
>>> n2 = note.Note() >>> n2.offset = 4.0 >>> n2.priority = -3 >>> s.insert(n2) >>> n2InsertIndex = n2.sortTuple().insertIndex >>> n2InsertIndex > nInsertIndex True
>>> rb = bar.Barline() >>> s.storeAtEnd(rb) >>> rb.sortTuple() SortTuple(atEnd=1, offset=0.0, priority=0, classSortOrder=-5, isNotGrace=1, insertIndex=...)
-
Music21Object.
splitAtDurations
()¶ Takes a Music21Object (e.g., a note.Note) and returns a list of similar objects with only a single duration.DurationTuple in each. Ties are added if the object supports ties.
Articulations only appear on the first note. Same with lyrics.
Fermatas should be on last note, but not done yet.
>>> a = note.Note() >>> a.duration.clear() # remove defaults >>> a.duration.addDurationTuple(duration.durationTupleFromTypeDots('half', 0)) >>> a.duration.quarterLength 2.0 >>> a.duration.addDurationTuple(duration.durationTupleFromTypeDots('whole', 0)) >>> a.duration.quarterLength 6.0 >>> b = a.splitAtDurations() >>> b [<music21.note.Note C>, <music21.note.Note C>] >>> b[0].pitch == b[1].pitch True >>> b[0].duration <music21.duration.Duration 2.0> >>> b[0].duration.type 'half' >>> b[1].duration.type 'whole' >>> b[0].quarterLength, b[1].quarterLength (2.0, 4.0)
>>> c = note.Note() >>> c.quarterLength = 2.5 >>> d, e = c.splitAtDurations() >>> d.duration.type 'half' >>> e.duration.type 'eighth' >>> d.tie.type 'start' >>> print(e.tie) <music21.tie.Tie stop>
Assume c is tied to the next note. Then the last split note should also be tied
>>> c.tie = tie.Tie() >>> d, e = c.splitAtDurations() >>> e.tie.type 'start'
Rests have no ties:
>>> f = note.Rest() >>> f.quarterLength = 2.5 >>> g, h = f.splitAtDurations() >>> (g.duration.type, h.duration.type) ('half', 'eighth') >>> g.tie is None True
-
Music21Object.
splitAtQuarterLength
(quarterLength, retainOrigin=True, addTies=True, displayTiedAccidentals=False, delta=1e-06)¶ Split an Element into two Elements at a provided quarterLength (offset) into the Element.
>>> a = note.Note('C#5') >>> a.duration.type = 'whole' >>> a.articulations = [articulations.Staccato()] >>> a.lyric = 'hi' >>> a.expressions = [expressions.Mordent(), expressions.Trill(), expressions.Fermata()] >>> b, c = a.splitAtQuarterLength(3) >>> b.duration.type 'half' >>> b.duration.dots 1 >>> b.duration.quarterLength 3.0 >>> b.articulations [<music21.articulations.Staccato>] >>> b.lyric 'hi' >>> b.expressions [<music21.expressions.Mordent>, <music21.expressions.Trill>] >>> c.duration.type 'quarter' >>> c.duration.dots 0 >>> c.duration.quarterLength 1.0 >>> c.articulations [] >>> c.lyric >>> c.expressions [<music21.expressions.Trill>, <music21.expressions.Fermata>]
Make sure that ties remain as they should be:
>>> d = note.Note('D#4') >>> d.duration.quarterLength = 3.0 >>> d.tie = tie.Tie('start') >>> e, f = d.splitAtQuarterLength(2.0) >>> e.tie, f.tie (<music21.tie.Tie start>, <music21.tie.Tie continue>)
Should be the same for chords...
>>> g = chord.Chord(['C4', 'E4', 'G4']) >>> g.duration.quarterLength = 3.0 >>> g._notes[1].tie = tie.Tie('start') >>> h, i = g.splitAtQuarterLength(2.0) >>> for j in range(0,3): ... h._notes[j].tie, i._notes[j].tie (<music21.tie.Tie start>, <music21.tie.Tie stop>) (<music21.tie.Tie start>, <music21.tie.Tie continue>) (<music21.tie.Tie start>, <music21.tie.Tie stop>)
If quarterLength == self.quarterLength then the second element will be None.
>>> n = note.Note() >>> n.quarterLength = 0.5 >>> a, b = n.splitAtQuarterLength(0.5) >>> b is None True >>> a is n True
(same with retainOrigin off)
>>> n = note.Note() >>> n.quarterLength = 0.5 >>> a, b = n.splitAtQuarterLength(0.5, retainOrigin=False) >>> a is n False
If quarterLength > self.quarterLength then a DurationException will be raised:
>>> n = note.Note() >>> n.quarterLength = 0.5 >>> a, b = n.splitAtQuarterLength(0.7) Traceback (most recent call last): DurationException: cannot split a duration (0.5) at this quarterLength (0.7)
-
Music21Object.
splitByQuarterLengths
(quarterLengthList, addTies=True, displayTiedAccidentals=False)¶ Given a list of quarter lengths, return a list of Music21Object objects, copied from this Music21Object, that are partitioned and tied with the specified quarter length list durations.
>>> n = note.Note() >>> n.quarterLength = 3 >>> post = n.splitByQuarterLengths([1,1,1]) >>> [n.quarterLength for n in post] [1.0, 1.0, 1.0]
-
Music21Object.
write
(fmt=None, fp=None, **keywords)¶ Write out a file of music notation (or an image, etc.) in a given format. If fp is specified as a file path then the file will be placed there. If it is not given then a temporary file will be created.
If fmt is not given then the default of your Environment’s ‘writeFormat’ will be used. For most people that is musicxml.
Returns the full path to the file.
Music21Object
instance variables
-
Music21Object.
classSortOrder
¶ Property which returns an number (int or otherwise) depending on the class of the Music21Object that represents a priority for an object based on its class alone – used as a tie for stream sorting in case two objects have the same offset and priority. Lower numbers are sorted to the left of higher numbers. For instance, Clef, KeySignature, TimeSignature all come (in that order) before Note.
All undefined classes have classSortOrder of 20 – same as note.Note
>>> m21o = base.Music21Object() >>> m21o.classSortOrder 20
>>> tc = clef.TrebleClef() >>> tc.classSortOrder 0
>>> ks = key.KeySignature(3) >>> ks.classSortOrder 2
New classes can define their own default classSortOrder
>>> class ExampleClass(base.Music21Object): ... classSortOrder = 5 ... >>> ec1 = ExampleClass() >>> ec1.classSortOrder 5
-
Music21Object.
groups
¶ An instance of a
Group
object which describes arbitrary Groups that this object belongs to.
-
Music21Object.
hideObjectOnPrint
¶ if set to True will not print upon output (only used in MusicXML output at this point and Lilypond for notes, chords, and rests).
-
Music21Object.
id
¶ A unique identification string; not to be confused with the default .id() method. However, if not set, will return the id() number
-
Music21Object.
xPosition
¶ if set, defines the display x-position from the start of the container (in musicxml “tenths” by default)
ElementWrapper¶
-
class
music21.base.
ElementWrapper
(obj=None)¶ An ElementWrapper is a way of containing any object that is not a
Music21Object
, so that that object can be positioned within aStream
.The object stored within ElementWrapper is available from the
obj
attribute. All the attributes of the stored object (except .id and anything else that conflicts with a Music21Object attribute) are gettable and settable by querying the ElementWrapper. This feature makes it possible easily to mix Music21Objects and non-Music21Objects with similarly named attributes in the same Stream.This example inserts 10 random wave files into a music21 Stream and then reports their filename and number of audio channels (in this example, it’s always 2) if they fall on a strong beat in fast 6/8
>>> import music21 >>> import wave >>> import random
>>> s = stream.Stream() >>> s.id = 'mainStream' >>> s.append(meter.TimeSignature('fast 6/8')) >>> for i in range(10): ... fileName = 'thisSound_' + str(random.randint(1,20)) + '.wav' ... soundFile = wave.open(fileName) ... soundFile.fileName = fileName ... el = music21.ElementWrapper(soundFile) ... s.insert(i, el)
>>> for j in s.getElementsByClass('ElementWrapper'): ... if j.beatStrength > 0.4: ... (j.offset, j.beatStrength, j.getnchannels(), j.fileName) (0.0, 1.0, 2, 'thisSound_1.wav') (3.0, 1.0, 2, 'thisSound_16.wav') (6.0, 1.0, 2, 'thisSound_12.wav') (9.0, 1.0, 2, 'thisSound_8.wav') >>> for j in s.getElementsByClass('ElementWrapper'): ... if j.beatStrength > 0.4: ... (j.offset, j.beatStrength, j.getnchannels() + 1, j.fileName) (0.0, 1.0, 3, 'thisSound_1.wav') (3.0, 1.0, 3, 'thisSound_16.wav') (6.0, 1.0, 3, 'thisSound_12.wav') (9.0, 1.0, 3, 'thisSound_8.wav')
Test representation of an ElementWrapper
>>> for i, j in enumerate(s.getElementsByClass('ElementWrapper')): ... if i == 2: ... j.id = None ... else: ... j.id = str(i) + "_wrapper" ... if i <=2: ... print(j) <ElementWrapper id=0_wrapper offset=0.0 obj="<...Wave_read object..."> <ElementWrapper id=1_wrapper offset=1.0 obj="<...Wave_read object..."> <ElementWrapper offset=2.0 obj="<...Wave_read object...">
ElementWrapper
bases
ElementWrapper
read-only properties
Read-only properties inherited from Music21Object
:
ElementWrapper
read/write properties
Read/write properties inherited from Music21Object
:
ElementWrapper
methods
-
ElementWrapper.
isTwin
(other)¶ A weaker form of equality. a.isTwin(b) is true if a and b store either the same object OR objects that are equal. In other words, it is essentially the same object in a different context
>>> import copy >>> import music21
>>> aE = music21.ElementWrapper(obj = "hello")
>>> bE = copy.copy(aE) >>> aE is bE False >>> aE == bE True >>> aE.isTwin(bE) True
>>> bE.offset = 14.0 >>> bE.priority = -4 >>> aE == bE False >>> aE.isTwin(bE) True
Methods inherited from Music21Object
:
ElementWrapper
instance variables
-
ElementWrapper.
obj
¶ The object this wrapper wraps. It should not be a Music21Object.
Instance variables inherited from Music21Object
:
Groups¶
-
class
music21.base.
Groups
¶ Groups is a list of strings used to identify associations that an element might have.
The Groups object enforces that all elements must be strings, and that the same element cannot be provided more than once.
>>> g = Groups() >>> g.append("hello") >>> g[0] 'hello'
>>> g.append("hello") # not added as already present >>> len(g) 1
>>> g ['hello']
>>> g.append(5) Traceback (most recent call last): GroupException: Only strings can be used as list names
Groups
bases
Groups
methods
-
Groups.
append
(value)¶
TestMock¶
-
class
music21.base.
TestMock
¶
TestMock
bases
TestMock
read-only properties
Read-only properties inherited from Music21Object
:
TestMock
read/write properties
Read/write properties inherited from Music21Object
:
TestMock
methods
Methods inherited from Music21Object
:
TestMock
instance variables
Instance variables inherited from Music21Object
: