ï~~Proceedings of the International Computer Music Conference 2011, University of Huddersfield, UK, 31 July - 5 August 2011
# adding another Part to the Score results in a
# different flat representation
n5 = note.Note('a#1', quarterLength=2.5)
n6 = note.Note('b2', quarterLength=1.5)
m3 = stream.Measure(number=1)
m3.append([cf2, rl])
rl = note.Rest(type='whole')
cf2 = m3.bestClef() # cf2 is a BassClef
m4 = stream.Measure(number=2)
m4.append([n5, n6])
p2 = stream.Part()
p2.append([m3, m4])
sl.insert(0, p2)
# objects are sorted by offset
slFlat = sl.flat
assert len(sl) == 3
assert len(slFlat) == 10
assert slFlat[6] == n3
assert slFlat[7] == n5
assert slFlat[8] == n4
assert slFlat[9] == n6
# the B in m. 2 (=p2,m4) now has offsets for
# both flat non-flat sites
assert n6.getOffsetBySite(m4) == 2.5
assert n6.getOffsetBySite(slFlat) == 6.5
s1. show ()
i~i~iii!#...........
Figure 6. Access to flat and non-flat representations,
and adding and displaying an additional Part.
3.4. Iterating and Filtering Elements by Class
The music21 system makes great use of subclassing and
class definition to distinguish system components. Each
clef and each ornament type, for example, are given
unique class definitions. As all Music2lObjects can
reside on Streams, it is often necessary to filter a Stream
by class, return a new Stream with just the desired Music21Objects, and then process the results. As is typical
in object-oriented languages, more general classes, inherited by subclasses, can be used for broader filters;
specific class types or lists of classes can be used for
more narrow filters.
For example, a complex polyphonic work might
contain nested Streams defining Parts, Measures, and
Voices, and within these Measures have Clef, TimeSignature, Note, Rest, and Chord objects. If a user needs to
find the distribution of pitch usage, or look for a specific
pitch, iterating over all these elements is unnecessary.
Instead, the getElementsByClass () method on the flat
representation can be used, where a list of desired classes (Python names or strings) is given. The returned,
independent Stream includes only the matching classes
with offset positions transferred from the source. As
with Python lists, the Stream can be iterated in standard
loop syntax.
Because calls to getElementsByClass (
[note.Note, chord.Chord]) are so common, the notes
property on Streams provides quick access to a new
Stream containing only Note and note-like entities.
Figure 7 demonstrates applications of using getElementsByClass () and the notes property, iterating over
various collected Music21Objects and gathering information or transforming objects.
# get the Clef object, and report its sign,
# from Measure 1
assert ml.getElementsByClass ('Clef') [0].sign ==
'C'
# collect into a list the sign of all clefs in
# the flat Score
assert [cf.sign for cf in
sl.flat.getElementsByClass ('Clef')] == ['C',
'F']
# collect the offsets of Measures in the first
# part
assert [e.offset for e in pl.elements] == [0.0,
4.0]
# collect the offsets of Notes in the first
# part after flattening
assert [e.offset for e in pl.flat.notes] ==
[0.0, 2.0, 4.0, 4.5]
# get all pitch names
match = [ ]
for e in sl.flat.notes:
match.append(e.pitch.nameWithOctave)
assert match == ['G3', 'C4', 'G#3', 'A#1', 'D4', 'B2']
# collect all the Notes using the
# getElementsByClass form and transpose them
# up a perfect fifth
for n in sl.flat.getElementsByClass('Note'):
n.transpose('P5', inPlace=True)
s. show ()
Â~r...'..............................................................................
Figure 7. Iterating and filtering a Stream by class, and
then displaying the results of transposition applied to
filtered Note objects.
Similar to the Stream returned by the flat property, the
Streams returned by getElementsByClass() and the
notes property offer alternative "views" of the same
Music21 Components. Figure 8, expanding the previous
presentations, illustrates references of the same Music21Objects in multiple parallel Stream instances, each
retaining relative but independent offset positions.
With the frequent derivation of one Stream from an
other, by usage of both the flat property as well as by
getElementsByClass () and similar methds, it is useful
65