This module demonstrates how to perform the post-tonal transposition operation on pitches and pitch classes.
There are two ways of thinking about transposition in post-tonal music: as a way of measuring distance between notes, or as an operation that can be applied to notes.
Let’s start with two notes, G4 and C5, given as 67 and 72 in MIDI note numbers. The difference between them is 5 semitones (you can review math in Python if necessary):
72 - 67
> 5
So we could say that to get from G4 to C5, we have to travel up 5 semitones. We call this T5. To get from C5 to G4, we have to travel down 5 semitones (T-5):
67 - 72
> -5
Now let’s apply this to an actual melody. We’ll use the first movement of American composer Marion Bauer’s Viola Sonata (1932). You can listen to it here:
The first movement begins with a characteristic six-note motif on the piano: C-F#-B-A-C-B. The viola repeats it in measure 4 (0:10). In MIDI notes, the motif would be represented as:
motif = [48, 54, 59, 57, 60, 71]
In post-tonal music, it is common for motifs such as these to be repeated not only as they were first played, but also in different registers (as we saw in the previous module) and in various transpositions. If we continue listening, we can hear numerous statements of this motif.
Around 4:10, the piano seems to play another version of this motif in the right hand:
piano = [67, 73, 78, 76, 79, 90]
We can find the difference between each note in these two melodies by subtracting one from the other. However, we can’t simply subtract one list from another using the “-” operator. We have to iterate over both lists simultaneously in order to compare the corresponding note in each melody.
In order to compare two melodies like this, first we have to ensure that they are the same length:
len(motif)
> 6
len(piano)
> 6
If the lengths match, we can use the length as a range for a for loop (using the helpful range function):
for x in range(6):
print(motif[x] - piano[x])
> -19
> -19
> -19
> -19
> -19
> -19
We step through each of the eight notes in each list, comparing (and printing) the differences as we go. It seems that the notes in the original motif and in the later piano statement are all related by T-19. This means that if we were to transpose the piano’s statement down by 19 semitones, it would be identical to the original statement.
This is helpful information in some musical contexts, but in studying post-tonal music, we often want to know the pitch class relationships. We can use a list comprehension to quickly generate lists of pitch classes:
motif_pc = [x % 12 for x in motif]
piano_pc = [x % 12 for x in piano]
Now let’s try the same comparison operation as before, but using these new lists:
for x in range(6):
print(motif_pc[x] - piano_pc[x])
> -7
> 5
> 5
> 5
> -7
> 5
This is an unexpected result! Even though the melodies are related by T-19, when we convert to pitch classes, there’s no longer a single Tn that describes the relationship for all of the notes. Why would this be?
Recall that there are only 12 pitch classes (0-11), and that if we keep rising by semitones past 11, we start over at 0. If we descend, we go straight from 0 back to 11, not -1. Just like how two hours before 1:00 isn’t -1:00, it’s 11:00!
In order to respect this circular structure, we have to apply a final modulo (%) 12 operation to the subtraction. And as soon as we do that:
for x in range(6):
print((motif_pc[x] - piano_pc[x]) % 12)
> 5
> 5
> 5
> 5
> 5
> 5
Voila! Now we can see that each of the pitch classes of the harp melody are related to the pitch classes of the violin melody by T5.
Put another way, if we add 5 semitones to each note in the piano statement of teh melody (modulo 12), it will be identical to the first statement of the motif, at least in terms of pitch class.
Let’s prove it:
motif_pc
> [0, 6, 11, 9, 0, 11]
piano_pc
> [7, 1, 6, 4, 7, 6]
for x in piano_pc:
print((x + 5) % 12)
> 0
> 6
> 11
> 9
> 0
> 11
Or more succinctly:
print([(x + 5) % 12 for x in piano_pc])
> [0, 6, 11, 9, 0, 11]
This transformation of the piano’s melody matches the pitch classes of the original motif.
The next step is to organize all of these steps into a single algorithm or function. To explore building transposition-related functions, try this module.
Extensions
- What value n for the transposition operation Tn transforms the original motif into the piano’s statement (i.e. the reverse operation)? What is significant about the relationship between this number and the 5 in T5 discussed above?
- What generic Python functions above can be replaced with equivalents from the music21 post-tonal toolkit?
- Are other statements of the same idea in Bauer’s Sonata also related by transposition? If so, how do they compare?
Further Reading
For more on this topic, see the Open Music Theory entry.