User’s Guide: Chapter 18: Intervals

Intervals, or distances in pitch space between two pitches, are fundamental concepts of music theory, dating back at least to Ancient Greece, and are thus fundamental concepts in music21 as well.

Different forms of music theory analysis, such as tonal theory, modal theory, and chromatic (atonal) theory use different kinds of intervals. Thus music21 has a collection of interval classes that can be used in different situations. They are all found in the interval module, which also contains some handy tools for creating and comparing intervals. This chapter of the User’s Guide explains how to create and use Interval objects.

The Interval Class

We’re going to break from the tradition of starting with the simplest objects and begin with the most flexible but also complex object, simply called Interval, since if you’re going to learn about even a single Interval, it might as well be the most useful one.

We can create an Interval object by giving an abbreviation for the interval as a string. For instance, if we want to model a perfect fifth, we’ll use the string "P5":

i = interval.Interval('P5')
i
 <music21.interval.Interval P5>

Now we can see some properties of Interval objects:

i.niceName
 'Perfect Fifth'
i.name
 'P5'
i.semitones
 7
i.isStep
 False

Here’s a rule that assumes a musical context from the late fourteenth century to the end of the nineteenth century:

i.isConsonant()
 True

What do we need to make this interval add up to an octave? That’s the complement:

i.complement
 <music21.interval.Interval P4>

The .intervalClass of an Interval of the number of semitones of the smaller of the interval or its complement:

i.intervalClass
 5

A cent is 1/100th of a semitone:

i.cents
 700.0

We can get a descending form of the Interval with the .reverse() method:

i.reverse()
 <music21.interval.Interval P-5>

Let’s suppose that the interval is the distance between B4 and some other note, what note would that be?

i.noteStart = note.Note('B4')
i.noteEnd
 <music21.note.Note F#>

Or we can use this interval to transpose any given Note:

i.transposeNote(note.Note('C5'))
 <music21.note.Note G>

Or we can use intervals to transpose pitches:

i.transposePitch(pitch.Pitch('C5'))
 <music21.pitch.Pitch G5>

Note that Pitch, Note, Chord, and Stream objects all have a .transpose() method. These methods take Interval objects as arguments (or, if given something else such as a string, the methods try to automatically create an Interval):

pitch.Pitch('E3').transpose(i)
 <music21.pitch.Pitch B3>
chord.Chord("F A C").transpose(i)
 <music21.chord.Chord C E G>
s = converter.parse('tinyNotation: 4/4 c4 d e8 f# g4')
s2 = s.transpose(i)
s2.show()
../_images/usersGuide_18_intervals_30_0.png

All intervals have properties called “simpleName” and “semiSimpleName” that become useful for reducing compound intervals (those over an octave) to smaller forms.

i2 = interval.Interval('P-12')
i2.simpleName
 'P5'
i2.directedSimpleName
 'P-5'

For most intervals, simple and semiSimple mean the same thing, but while simple will reduce an octave to a unison, semiSimple treats octaves as distinct intervals. There are certain theories where we want to consider, say, parallel octaves and parallel unisons differently (or at least display a different message to the user), but where we don’t care about the difference between a third and a tenth:

p8 = interval.Interval('P8')
m10 = interval.Interval('m10')
(p8.simpleNiceName, m10.simpleNiceName)
 ('Perfect Unison', 'Minor Third')
(p8.semiSimpleNiceName, m10.semiSimpleNiceName)
 ('Perfect Octave', 'Minor Third')

Note that capitalization makes a difference in determining Major and minor:

interval.Interval('m3').niceName
 'Minor Third'
interval.Interval('M3').niceName
 'Major Third'

Creating diminished and Augmented intervals is as simple as using “d” and “A” in the string:

interval.Interval('d5').niceName
 'Diminished Fifth'
interval.Interval('A4').niceName
 'Augmented Fourth'

And, yes, multiple letters can get certain obscure intervals:

for intName in ['d5', 'dd5', 'ddd5', 'A4', 'AA4', 'AAA4']:
    iTemp = interval.Interval(intName)
    print(iTemp.niceName)
 Diminished Fifth
 Doubly-Diminished Fifth
 Triply-Diminished Fifth
 Augmented Fourth
 Doubly-Augmented Fourth
 Triply-Augmented Fourth

Up to a reasonable limit:

interval.Interval('dddd5').niceName
 'Quadruply-Diminished Fifth'
interval.Interval('dddd5').transposePitch(pitch.Pitch('C4'))
 <music21.pitch.Pitch G----4>
try:
    interval.Interval('ddddd5').niceName
except TypeError:
    print("Can't do five ds!")
 Can't do five ds!

Other ways of constructing Interval objects

The method of creating an interval from a string such as “A4” or “d5” is great if you know the interval’s name in advance. But what if you don’t? Fortunately, there are some other great ways to create them.

First, if you have two Note or Pitch objects, pass them into the Interval constructor as the first and second elements:

e = note.Note('E4')
a = note.Note('A4')
p4 = interval.Interval(e, a)
p4.niceName
 'Perfect Fourth'

Or, you can create intervals from an integer, representing the number of half-steps:

interval.Interval(7)
 <music21.interval.Interval P5>
for semitones in range(14):
    tempInt = interval.Interval(semitones)
    print(semitones, tempInt.niceName)
 0 Perfect Unison
 1 Minor Second
 2 Major Second
 3 Minor Third
 4 Major Third
 5 Perfect Fourth
 6 Diminished Fifth
 7 Perfect Fifth
 8 Minor Sixth
 9 Major Sixth
 10 Minor Seventh
 11 Major Seventh
 12 Perfect Octave
 13 Minor Ninth

Now, music theory geeks will wonder, how does music21 know that six semitones is a “Diminished Fifth” and not an Augmented Fourth? (Or for that matter, that three semitones is a Minor Third and not an Augmented Second or Triply-Augmented Unison?)

The answer is that it takes a good guess, but it records that the “diatonic interval” (that is “Diminished Fifth,” etc.) is just a guess, or is “implicit”:

sixSemis = interval.Interval(6)
d5 = interval.Interval('d5')
(sixSemis.implicitDiatonic, d5.implicitDiatonic)
 (True, False)

This distinction makes a difference if we use these two interval objects to transpose a pitch. Take the pitch “G flat”. A diminished fifth above it is “D double flat”, but if most of us were inclined to think about “a tritone above G flat” we’d probably think of C. The implicitDiatonic flag allows the six-semitone interval to make these sorts of intelligent decisions, while the interval that was explicitly specified to be a diminished fifth will do exactly what is asked (so long as it doesn’t go to more than quadruple flat or sharp):

sixSemis.transposePitch(pitch.Pitch('G-'))
 <music21.pitch.Pitch C>
d5.transposePitch(pitch.Pitch('G-'))
 <music21.pitch.Pitch D-->

We can create new intervals by adding existing Intervals together:

i1 = interval.Interval('P5')
i2 = interval.Interval('M3')
i3 = interval.add([i1, i2])
i3
 <music21.interval.Interval M7>

Here’s a nice way of making sure that a major scale actually does repeat at an octave (and a demo that “W” and “H” are synonyms for whole and half steps; and that interval.add() can automatically convert strings to Intervals:

interval.add(["W", "W", "H", "W", "W", "W", "H"])
 <music21.interval.Interval P8>

Or one can create new intervals by subtracting old ones:

interval.subtract([i1, i2])
 <music21.interval.Interval m3>

Subtraction, of course, is not commutative:

iDown = interval.subtract([i2, i1])
iDown.directedNiceName
 'Descending Minor Third'

Intervals are returned by several analysis routines in music21. For instance, if you want to know the range from the lowest to the highest note in a piece:

s = converter.parse('4/4 c4 d e f# g# a# g f e1', format="tinyNotation")
s.show()
../_images/usersGuide_18_intervals_68_0.png
s.analyze('range')
 <music21.interval.Interval A6>
a6 = s.analyze('range')
a6.semitones
 10