Pedal Point

This module illustrates how to identify and analyze a pedal point.

This module requires the music21 package. A pedal point is a tone that is sustained (or repeated) through several different chords or harmonies. It is often, but not always, in the lowest voice. Typically, it will function as a chord tone in some of these harmonies, and a non-chord tone in at least one. To identify a pedal point, you must analyze the harmonic context.

We’ll start by looking at the introduction of “Carillon Mystique” for piano by the French composer Melanie Bonis:

from music21 import *

carillon = converter.parse('tinyNotation: 4/4 GG-8 D- B- D- c- D- A- D- B- D- G- D- A- D- F D- G- D- F D- E- D- G- D- F D- E- D- F D- GG- D-')

Here is a link to the recording of the whole piece:

Instead of loading the whole piece, I’m just creating a simplified version of a short passage using music21’s tinyNotation. (To learn more about tinyNotation, click here.)

The principle of the pedal point is that through sustain or repetition over a long period of time, the pedal note generates tension, especially in relation to the harmony around it. This tension is finally resolved when the pedal note is changed or “released.”

In this example, the first note establishes the G-flat major tonality, after which a melody can be heard interspersed with the repeated note D-flat. The pedal point is often built on the dominant (the fifth scale degree) to build tension before a return to the tonic. This is exactly what happens here: the D-flat is repeated for four bars before we return to the tonic (the first scale degree).

The register of the notes is crucial here. Even though there are G-flats in the middle of this passage, because they occur in a register above the pedal point, they don’t give a feeling of resolution. When we finally hear the low G-flat from the very beginning return at the end of the fourth bar, it feels as though the pedal note is resolved. For this reason, the pedal note is often the lowest note in a musical texture.

Let’s take a look at a musical example in context. This is a choral work by the composer Amy Beach called “Prayer of a Tired Child” from the music21 corpus:

beach = corpus.parse('beach/prayer_of_a_tired_child.musicxml')

First, follow the score as you listen. We’ll focus on the vocal parts, rather than the piano accompaniment. The first phrase extends from measure 1 to measure 5. We notice that during this entire phrase, the lowest voice (Alto II) remains on the same pitch throughout (B-flat below middle C). In fact, the highest voice (Soprano I) also sustains a B-flat an octave higher until measure 4. In other words, we have a pedal point in the outer voices against changing harmonies in the inner voices.

Starting from the first quarter note in the vocal part, we have the following harmonies: E-flat, G, B-flat; B-flat, F, A-flat; E-flat, G, B-flat; and B-flat, D, F. In the key of E-flat major, we can understand this movement as alternating between I and V, even if we’re missing a note here and there.

The eighth-note pickups to bar three frame the B-flats as non-chord tones for the first time, as we have B-flat against C and E-flat in the Soprano II and Alto I parts. As discussed above, however, this is pretty typical.

Let’s use the music21 toolkit to analyze a little deeper. First, let’s isolate the vocal parts by removing the piano part. There are a number of ways to do this, but here we’ll use the .remove function and a while loop:

while len( > 4:

This block of code removes parts, starting from the bottom, until the total number of parts is equal to four. Just as with lists, we use the index “-1” to specify the bottom (last) part. (We could also use “4,” but “-1” is more generalizable.) If we view the score again, the piano part is gone:

Next, in order to analyze the chords, we want to use the chordify function. This allows us to reduce all of the parts onto a single staff:

beach_chords = beach.chordify()

We can view the chords on their own or, to make things a bit clearer, add the chords to a single staff below the vocal parts, like a piano reduction:

beach.insert(0, beach_chords)

The insert function allows us to add an element (beach_chords) to an existing score (technically, a stream) at a specified offset from the beginning (0, since we want the parts to line up). Now when we view the original score, a fifth staff has been added at the bottom with the reduction.

Now let’s analyze and label the the chords. First, we have to establish the key by creating a music21 key object:

beach_key = key.Key('E-')

Next, we’ll iterate over each chord in the last part of the score (the reduction) using a for loop along with .recurse() (to search through multiple depths of the stream) and .getElementsByClass to specify chords. For each chord (“c”), we generate a Roman numeral in our specified key, and then add the Roman numeral label below the note (as though it were a lyric).

Additionally, since we modulate to C minor in the middle of the piece, we only want to use the E-flat major Roman numerals where applicable. Therefore, let’s just analyze the first six bars:

for c in[-1].measures(1,6).recurse().getElementsByClass('Chord'):
 rn = roman.romanNumeralFromChord(c, beach_key)

We’ll use a similar block of code to add labels in C minor from measures 7-19:

beach_minor = key.Key('c')

for c in[-1].measures(7,19).recurse().getElementsByClass('Chord'):
 rn = roman.romanNumeralFromChord(c, beach_minor)

And then the return to E-flat major in bars 20-31 (remember to switch back the key in the second line of the code):

for c in[-1].measures(20,31).recurse().getElementsByClass('Chord'):
 rn = roman.romanNumeralFromChord(c, beach_key)

Now we have a fully analyzed score, which will allow us to more easily examine the harmonic role of the pedal point throughout the piece. For example, notice how the pedal note remains on the fifth scale degree by switching from B-flat to G when the piece modulates to C minor in the middle section.

Now let’s try adding another layer of labels corresponding to the role the pedal point plays in the harmony. This block of code will determine whether the pedal note B-flat is the root in measures 1-6 using an if statement:

for c in[-1].measures(1,6).recurse().getElementsByClass('Chord'):
 if pitch.Pitch('B-').name == c.root().name:

(Note that we must include the .name property so that matches in different octaves will be recognized.)

It turns out that B-flat is the root note for just about every other chord. And now for the middle section:

for c in[-1].measures(7,19).recurse().getElementsByClass('Chord'):
 if pitch.Pitch('G').name == c.root().name:

Again, the pedal note is quite frequently the root note, meaning that we have a lot of dominant harmonies. See the extensions below for ideas on how to conduct an even more in-depth analysis.


  1. Try using .third, .fifth, and .seventh to determine how often the pedal tones take on other roles in the chords in this piece. Or you can use .getChordStep() for even more flexibility.
  2. Can you write a loop or function that labels the entire piece and automatically takes the modulation in the middle section into account?

Further Reading

For more on pedal points, check out this page.