User’s Guide, Chapter 10: Examples 1¶
Well, that’s long enough to go without doing some actual work! Let’s see what is possible to do so far.|
Where do Chords move to?¶
Let’s take our favorite work so far, Bach’s BWV 66.6, and see where each chord goes.
We’ll begin, as always, with importing music21
and parsing the work
from the corpus.
from music21 import *
s = corpus.parse('bwv66.6')
Now let’s chordify it.
sChords = s.chordify()
sChords
<music21.stream.Part Soprano>
sChords
is a Part containing no Chords! It has measures, which
contain Chords. We’re going to want to see all the chords, so let’s
flatten it with .flatten()
.
sFlat = sChords.flatten()
sFlat
<music21.stream.Part Soprano_flat>
Inside sChords
is not just chords, but also the time signatures,
etc., so let’s create a Stream that only has the chords in sChords. And
we’ll get rid of all internal barlines, measures, etc. We’ll use
.getElementsByClass('Chord')
for that:
sOnlyChords = sFlat.getElementsByClass('Chord')
sOnlyChords
<music21.stream.iterator.StreamIterator for Part:Soprano_flat @:0>
We are eventually going to want to display each chord, so we’ll create a
new Stream
to do so. We’ll make it a Part
object:
displayPart = stream.Part(id='displayPart')
displayPart
<music21.stream.Part displayPart>
Now we’re going to want to look at each chord and the following chord,
so we want to go from the first chord, index 0
, to the second to
last chord, index len(sOnlyChords) - 1
, and then get each chord and
the next chord. We will do that with the following sequence of commands
for i in range(0, len(sOnlyChords) - 1):
thisChord = sOnlyChords[i]
nextChord = sOnlyChords[i + 1]
# do something with thisChord and nextChord here
Python hint: range(min, max)
or range(max)
is a “generator”
function that yields every number starting with min
(or zero if no
min is given) to one less than the maximum number. range()
is a
really useful function, and we will use it all the time to do the same
thing over a whole bunch of items. For instance:
for n in range(5):
print(n)
0
1
2
3
4
Then for each chord pair, we can create a new measure and append it to
displayPart
only if the first chord of each group is a triad or a
seventh. For the purposes of making this example short, let’s do it only
if the first chord’s root is “A”. And we can put them all in closed
position.
We can create a new function to do all this and call it
appendChordPairs()
def appendChordPairs(thisChord, nextChord):
if ((thisChord.isTriad() is True or
thisChord.isSeventh() is True) and
thisChord.root().name == 'A'):
closePositionThisChord = thisChord.closedPosition(forceOctave=4)
closePositionNextChord = nextChord.closedPosition(forceOctave=4)
m = stream.Measure()
m.append(closePositionThisChord)
m.append(closePositionNextChord)
displayPart.append(m)
Okay, so I think we have this set up. Let’s replace “# do something
”
with appendChordPairs()
:
for i in range(len(sOnlyChords) - 1):
thisChord = sOnlyChords[i]
nextChord = sOnlyChords[i + 1]
appendChordPairs(thisChord, nextChord)
Do we have it? Let’s see if displayPart
has anything in it?
len(displayPart)
7
Only seven pairs of chords, well, we did limit it to chords built on
A
. Let’s see it!
displayPart.show()
Learning from the last chapter, we can label the chords with Roman Numerals in the key of A. Obviously, the first chord is always going to be “I”, but where does “I” move to? That’s more interesting. We’ll cheat and use an analysis technique we’ll later see in Chapter 23.
keyA = key.Key('A')
for c in displayPart.recurse().getElementsByClass('Chord'):
rn = roman.romanNumeralFromChord(c, keyA)
c.addLyric(str(rn.figure))
displayPart.show()
Well, it’s basically everything that I expected, except for that
III6
chord! I smell a modulation happening here. Let’s make all the
pitches of that Chord pink so we can find them later. And we’ll softly
introduce a new concept, the derivation.chain()
(see
Chapter 13) to make sure that
everything that this note comes from is also pink.
for c in displayPart.recurse().getElementsByClass('Chord'):
if c.lyric == 'III6':
c.style.color = 'pink'
for x in c.derivation.chain():
x.style.color = 'pink'
displayPart.show()
Now we can find this chord more easily:
sChords.show()
And we can analyze each Measure’s key to show that indeed it is part of a modulation to f# minor:
for m in sChords.getElementsByClass('Measure'):
k = m.analyze('key')
print(m.number, k)
0 E major
1 E major
2 A major
3 f# minor
4 E major
5 A major
6 f# minor
7 C# major
8 F# major
9 b minor
This is a brief summary of some things we can do so far. I’d like to use other pieces besides this Chorale, so let’s move on to Chapter 11: Corpus Searching to learn more.