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"
:
from music21 import *
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()
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 interval.IntervalException:
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()
s.analyze('range')
<music21.interval.Interval A6>
a6 = s.analyze('range')
a6.semitones
10