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
'3.0.1'
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 these pieces of information:
- id: identification string unique to the objects container (optional). Defaults to the id() of the element.
- 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 reference to the currently active Stream or None
- 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. - derivation: a
Derivation
object, or None, that shows where the object came from.
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.
classSet
¶ Returns a set (that is, unordered, but indexed) of all of the classes that this class belongs to, including string names, fullyQualified string names, and objects themselves.
It’s cached on a per class basis, so makes for a really fast way of checking to see if something belongs to a particular class when you don’t know if the user has given a string, a fully qualified string name, or an object.
Did I mention it’s fast? It’s a drop in substitute for the deprecated .isClassOrSubClass. It’s not as fast as x in n.classes or isinstance(n, x) if you know whether it’s a string or class, but this is good and safe.
>>> n = note.Note() >>> 'Note' in n.classSet True >>> 'music21.note.Note' in n.classSet True >>> note.Note in n.classSet True
>>> 'Rest' in n.classSet False >>> note.Rest in n.classSet False
>>> object in n.classSet True
>>> sorted([s for s in n.classSet if isinstance(s, str)]) ['GeneralNote', 'Music21Object', 'NotRest', 'Note', '....object', 'music21.base.Music21Object', 'music21.note.GeneralNote', 'music21.note.NotRest', 'music21.note.Note', 'object']
>>> sorted([s for s in n.classSet if not isinstance(s, str)], key=lambda x: x.__name__) [<class 'music21.note.GeneralNote'>, <class 'music21.base.Music21Object'>, <class 'music21.note.NotRest'>, <class 'music21.note.Note'>, <... 'object'>]
-
Music21Object.
classes
¶ Returns a tuple 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>
Changed 2015 Sep: returns a tuple, not a list.
-
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
Copies can retain measure numbers until set themselves:
>>> import copy >>> nCopy = copy.deepcopy(n2) >>> nCopy.measureNumber 12 >>> m3 = stream.Measure() >>> m3.number = 4 >>> m3.append(nCopy) >>> nCopy.measureNumber 4
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.
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.
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) >>> float(n1.offset) 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.
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 before 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
>>> n = note.Note() >>> n.quarterLength = 2.0 >>> n.quarterLength 2.0 >>> n.quarterLength = 1.0/3 >>> n.quarterLength Fraction(1, 3)
-
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.
containerHierarchy
(followDerivation=True, includeNonStreamDerivations=False)¶ Return a list of Stream subclasses that this object is contained within or (if followDerivation is set) is derived from.
This gives access to the hierarchy that contained or created this object.
>>> s = corpus.parse('bach/bwv66.6') >>> noteE = s[1][2][3] >>> noteE <music21.note.Note E> >>> [e for e in noteE.containerHierarchy()] [<music21.stream.Measure 1 offset=1.0>, <music21.stream.Part Soprano>, <music21.stream.Score 0x1049a5668>]
Note that derived objects also can follow the container hierarchy:
>>> import copy >>> n2 = copy.deepcopy(noteE) >>> [e for e in n2.containerHierarchy()] [<music21.stream.Measure 1 offset=1.0>, <music21.stream.Part Soprano>, <music21.stream.Score 0x1049a5668>]
Unless followDerivation is False:
>>> [e for e in n2.containerHierarchy(followDerivation=False)] []
if includeNonStreamDerivations is True then n2’s containerHierarchy will include n even though it’s not a container. It gives a good idea of how the hierarchy is being constructed.
>>> [e for e in n2.containerHierarchy(includeNonStreamDerivations=True)] [<music21.note.Note E>, <music21.stream.Measure 1 offset=1.0>, <music21.stream.Part Soprano>, <music21.stream.Score 0x1049a5668>]
The method follows activeSites, so set the activeSite as necessary.
>>> p = stream.Part(id="newPart") >>> m = stream.Measure(number=20) >>> p.insert(0, m) >>> m.insert(0, noteE) >>> noteE.activeSite <music21.stream.Measure 20 offset=0.0> >>> noteE.containerHierarchy() [<music21.stream.Measure 20 offset=0.0>, <music21.stream.Part newPart>]
-
Music21Object.
contextSites
(callerFirst=None, memo=None, offsetAppend=0.0, sortByCreationTime=False, priorityTarget=None, followDerivation=True)¶ 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.
getAllContextsByClass
(className)¶ Returns a generator that yields elements found by .getContextByClass and then finds the previous contexts for that element.
>>> s = stream.Stream() >>> s.append(meter.TimeSignature('2/4')) >>> s.append(note.Note('C')) >>> s.append(meter.TimeSignature('3/4')) >>> n = note.Note('D') >>> s.append(n) >>> for ts in n.getAllContextsByClass('TimeSignature'): ... print(ts, ts.offset) <music21.meter.TimeSignature 3/4> 1.0 <music21.meter.TimeSignature 2/4> 0.0
TODO: make it so that it does not skip over multiple matching classes at the same offset.
-
Music21Object.
getContextAttr
(attr)¶ Given the name of an attribute, search the Sites object for contexts having this attribute and return the best match.
DEPRECATED
>>> import music21 >>> class Mock(music21.Music21Object): ... attr1 = 234 >>> aObj = stream.Stream() >>> aObj.attr1 = 'test' >>> a = music21.Music21Object() >>> aObj.insert(0, a) >>> a.sites.getAttrByName('attr1') 'test'
>>> bObj = stream.Stream() >>> bObj.attr1 = 'came second' >>> bObj.insert(0, a) >>> a.sites.getAttrByName('attr1') 'test'
-
Music21Object.
getContextByClass
(className, getElementMethod='getElementAtOrBefore', 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 <music21.stream.Part 0x104ce64e0>
>>> 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.
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 getElementMethod is a string that selects which Stream method is used to get elements for searching. These strings are accepted:
- ‘getElementAtOrBefore’
- ‘getElementBeforeOffset’
- ‘getElementAtOrAfter’
- ‘getElementAfterOffset’
Use at or before to avoid getting the same element over and over again in a recursive context search.
The latter two do forward contexts – looking ahead.
-
Music21Object.
getOffsetBySite
(site, 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.
>>> 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) >>> float(n.getOffsetBySite(s1)) 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
Return type: list(spanner.Spanner)
-
Music21Object.
informSites
(changedInformation=None)¶ trigger called whenever sites need to be informed of a change in the parameters of this object.
changedInformation is not used now, but it can be a dictionary of what has changed.
subclass this to do very interesting things.
-
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
>>> n = note.Note() >>> n.isClassOrSubclass(('Note',)) True >>> n.isClassOrSubclass(('GeneralNote',)) True >>> n.isClassOrSubclass((note.Note,)) True >>> n.isClassOrSubclass((note.Rest,)) False >>> n.isClassOrSubclass((note.Note,note.Rest)) True >>> n.isClassOrSubclass(('Rest','Note')) True
-
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') >>> m3 = s.parts[0].measure(3) >>> m3.next() is s.parts[0].measure(4) True
Note that calling next() repeatedly gives...the same object. You’ll want to call next on that object...
>>> m3.next() is s.parts[0].measure(4) True >>> m3.next() is s.parts[0].measure(4) True
So do this instead:
>>> o = m3 >>> for i in range(4): ... print(o) ... o = o.next() <music21.stream.Measure 3 offset=9.0> <music21.stream.Measure 4 offset=13.0> <music21.stream.Measure 5 offset=17.0> <music21.stream.Measure 6 offset=21.0>
We can find the next element given a certain class with the classFilterList:
>>> n = m3.next('Note') >>> n <music21.note.Note A> >>> n.measureNumber 3 >>> n is m3.notes[0] True
..note:
There may be some unusual cases of using obj.next() in Python2 if obj uses itself as an Iterator, because Py2 assumes that each iterable has a .next() function. In Python3 there will be no problem since the `next()` function is renamed to `__next__()`.
-
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 Jan 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.sites.getAttrByName('attr1') 'test' >>> a.sites.setAttrByName('attr1', 3000) >>> a.sites.getAttrByName('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
And if it isn’t there? Nothing changes.
>>> b = note.Note() >>> b.setOffsetBySite(aSite, 40) >>> b.offset 0.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('start') >>> d, e = c.splitAtDurations() >>> d.tie.type 'start' >>> e.tie.type 'continue'
Rests have no ties:
>>> f = note.Rest() >>> f.quarterLength = 2.5 >>> g, h = f.splitAtDurations() >>> (g.duration.type, h.duration.type) ('half', 'eighth') >>> f.tie is None True >>> g.tie is None True
TODO: unit into a “split” function – document obscure uses.
-
Music21Object.
splitAtQuarterLength
(quarterLength, retainOrigin=True, addTies=True, displayTiedAccidentals=False)¶ Split an Element into two Elements at a provided quarterLength (offset) into the Element.
Returns a specialized tuple called a SplitTuple that also has a .spannerList element which is a list of spanners that were created during the split, such as by
TODO: unit into a “split” function – document obscure uses.
>>> a = note.Note('C#5') >>> a.duration.type = 'whole' >>> a.articulations = [articulations.Staccato()] >>> a.lyric = 'hi' >>> a.expressions = [expressions.Mordent(), expressions.Trill(), expressions.Fermata()] >>> st = a.splitAtQuarterLength(3) >>> b, c = st >>> b.duration.type 'half' >>> b.duration.dots 1 >>> b.duration.quarterLength 3.0 >>> b.articulations [] >>> 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 [<music21.articulations.Staccato>] >>> c.lyric >>> c.expressions [<music21.expressions.Fermata>] >>> c.getSpannerSites() [<music21.expressions.TrillExtension <music21.note.Note C#><music21.note.Note C#>>]
st is a _SplitTuple which can get the spanners from it for inserting into a Stream.
>>> st.spannerList [<music21.expressions.TrillExtension <music21.note.Note C#><music21.note.Note C#>>]
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 (7/10)
-
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.
TODO: unit into a “split” function – document obscure uses.
>>> 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.
isStream
¶ Boolean value for quickly identifying
Stream
objects (False by default). Deprecated
-
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 (subclass) 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.
NOTE: In the future spaces will not be allowed in group names.
>>> 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 group names
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
: