This document is hastily written to meet teaching deadlines. I want to make this interesting and clear. Your feedback is most welcome.

Most of this presentation is about "Western tonal music" which implies that the music probably has a beat, has familiar harmony, melody, etc. To keep things simple, I will make a lot of generalizations and describe music much more generally than I would like to. In particular, you should be aware that music does not have to have beats, chords, and other structures we will describe.

It is also possible to draw the note with the stem pointing down. It is not allowed to put the stem on the other side of the note. It's on the right side when pointing up and the left side when pointing down:

But one beat is not so interesting. Beats establish a rhythm when the occur in sequence. We write a sequence of beats by arranging them left-to-right on a line, like this:

If you clap your hands 4 times at a steady pulse, you will be performing this little piece of music.

We might represent rhythms on the computer as an array of time points, e.g. the little piece above could be represented by:

To notate measures, we need some way of grouping our quarter note beats. A vertical bar called a is used to separate measures. A working musician will often call a measure a bar, e.g. "give me a 2-bar intro." Here are 2 measures in notation:

for m = 0 to 2

for b = 0 to 4

print "measure:", m, ", beat: ", b, " at time ", 4 * m + b

Music would be really boring if it only
had quarter notes. This would
mean that all events take place on the beat and last for one beat.
Music notation allows for different durations. As you might imagine, a
2-beat duration is a half
note, and a 4-beat duration is a whole
note. Going to shorter durations, half a quarter note is an eighth note, etc. Here's what they
look like:

Here's an array representation:

Alternatively, we could write a loop to generate measures and beats:[[0],

[4, 6],

[8, 9, 10, 11],

[12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5],

[16, 16.25, 16.5, 16.75, 17, 18, 19]]

This code generates 5 measures. In each measure, b is initialized to zero, and b accumulates durations, and a different durations (looked up in the array durations) are used for each measure. Unlike the notation above, this actually generates 16 sixteenth notes in the last measure to avoid coding the special case.durations = [4, 2, 1, 0.5, 0.25]

for m = 0 to 5

var b = 0

while b < 3.9999

print "measure:", m, ", beat: ", b, " at time ", 4 * m + b

b = b + durations[m]

The time signature is the notation for an abstract concept called meter. You can almost use "meter" and "time signature" interchangeably, but if you are refering to the music notation, use "time signature." Here is how we write the time signature for 4 quarter notes:

The time signature 4/4 is also called "common time" (3/4 represented the Holy Trinity and was used in church, so 4/4 was used in secular music and therefore called "common"). Sometimes 4/4 is denoted with a big "C". The signature 2/2 is very similar in that there are 2 half notes = 4 quarter notes per measure, but we only divide the measure into 2 beats. This is also called "cut time" and can be written with a big "C" with a line through it:

Since rhythms are based on integer relationships (subdividing into 2 or 3, ties are effectively adding small integers), 3 turns out to be a very common duration. Music notation has a special way to introduce a factor of 3 (well, actually the factor is 3/2): When a note is followed by a dot, its duration is augmented by 50%; that is, the duration becomes 3/2 of the original. Here is the first measure of the previous notation example rewritten using a "dotted quarter note":sixteenth = 1/16 // note: Serpent integer division returns a float

eighth = 1/8

quarter = 1/4

half = 1/2

t1 = 0

t2 = t1 + quarter + eighth

t3 = t2 + eighth + half

t4 = t3 + quarter + eighth + sixteenth

t5 = t4 + sixteenth

t6 = t5 + eighth

t7 = t6 + eighth + quarter

rhythm = [[t1, t2], [t3, t4, t5, t6]]

print "rhythm ends at time", t7

If dots multiply by three, what about division by 3? This is also common in music. Taking a beat and subdividing into 3 equal time units creates aeighth = 1/8

quarter = 1/4

half = 1/2

t1 = 0

t2 = t1 + quarter * 1.5

t3 = t2 + eighth + half

rhythm = [[t1, t2]]

print "rhythm ends at time", t3

0.5 * 2/3 + 0.5 * 2/3 + 0.5 * 2/3 = 1

Here is what the notation looks like (this is in 4/4 time, but beats
are divided into triplets):et = 0.5 * 2/3 // duration of eighth note triplet

qt = 1 * 2/3 // duration of quarter note triplet

durations = [et, et, et, qt, et, et, et, et, et, qt]

sum = 0

rhythm = [] // compute the actual times of beats and put them here

for i = 0 to len(durations)

rhythm.append(sum)

sum = sum + durations[i] // keep running sum of durations

print rhythm, "next beat time is", sum

But pitch is not just a range from low to high. There is a special connection between pitches whose frequencies differ by a factor of exactly 2. In some way, these pitches seem like two versions of the same thing. They match even though one is much higher than the other. This other quality is called chroma, and pitches that differ in frequency by a factor of 2 are said to be an octave apart. (We should note here that these pure mathematical notions don't always match up exactly with human perception, but it's a good approximation. Still, it's my duty to warn you that the story is deeper and richer than what you will learn here.)

Octaves matter because our space of pitches seems to repeat itself every factor of two in frequency, or every octave in pitch. For this reason, we structure music pitch around octaves.

(Image from sciencebuddies.org.)

This pattern repeats every octave. The thing that is equal about the octave division is the frequency ratio between adjacent pitches. For what it's worth the ratio is the 12th root of 2 (but you could derive that, right?) This is called the equal-tempered scale because every semitone is equal in terms of frequency ratio.

The sequence of pitches in this 12-note octave is called the chromatic scale. It's kind of boring because every interval is the same, so there's no pattern and no point of reference.

We usually represent pitches on the computer using integers for the pitches of the chromatic scale. A particular note is called "Middle C" (see the picture above), and Middle C gets the number 60. The next note above Middle C is C-sharp (or C#), and has the number 61. We can describe the chromatic scale as a sequence of integers:

In addition to Middle C, every white key has a letter name. The letter names for an octave are C, D, E, F, G, A, B. These pitch names repeat in each octave. You would think the first pitch would be A, but it is C. What difference does it make if the names are cyclic? As shown in the figure above, Middle C is also called "C4." The "4" indicates the octave, and from the numbering, you can see that the octave goes from C to B: C4, D4, E4, F4, G4, A4, B4. Just above B4, we start a new octave with C5.chromatic_scale = []

for i = 60 to 73

chromatic_scale.append(i)

print "chromatic scale:", chromatic_scale

// this prints [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72]

Earlier, we said that there is a special similarity between pitches an octave apart, so it should make sense that they all have similar names. F2, F3, F4, F5, and F6 are all separated by exact octaves. Because they share the same chroma, we can just say these are all different F's. A set of pitches related by octaves is called a pitch class. There are of course 12 pitch classes.

Returning to our pitch numbers, notice that two pitch numbers with a difference of 12 are an octave apart. We can number pitch classes too. By convention, pitch classes are numbered from 0 to 12. The numerical pitch class of any pitch P is just P modulo 12.

def pitch_class(p)

return p % 12

def same_pitch_class(p1, p2)

return pitch_class(p1) == pitch_class(p2)

With 7 notes, you can construct scales where the intervals between adjacent pitch classes are just 1 or 2. These scales with these 2 intervals (1 or 2, also called half steps and hole steps) are called diatonic scales. The major scale, is the most common one. The C major scale is the major scale that starts on C and includes the white notes of the piano: C, D, E, F, G, A, B. In contrast, there are pentatonic scales, with 5 notes, constructed from intervals of 2 or 3. For example, C, D, F, G, A is a pentatonic scale. Pentatonic scales are not diatonic scales.

We can describe a scale numerically as a starting pitch (or pitch class) and a set of intervals above that pitch:

Notice that all intervals are 2 (0 to 2, 2 to 4, etc.) except for the interval from E (4) to F (5) and the interval from B (11) to C in the next octave (12). If you look at the picture of the keyboard, you will see that the only white notes not separated by black notes are in fact E and F, and B and C.// C D E F G A B

c_major = [0, [0, 2, 4, 5, 7, 9, 11]]

// subtract the third scale interval (index=2) from the first (index=0):But since music theorists started with pitch names and diatonic scales, intervals are more complicated. To begin with, intervals are based on counting scale steps from one pitch to another, starting with 1. So the interval from C to E is counted like this: C (1), D (2), E (3), and the answer is 3 (!). E is said to be a 3rd above C because it is the 3rd note. It is also the third note in the C major scale, so calling the interval from C to E a "third" does make some sense. The second complication is that since diatonic scale steps are not all the same size, counting scale steps does not tell you everything. Here is how intervals, expressed as numbers, are named:

major_third = c_major[1][2] - c_major[1][0]

- 0: unison
- 1: minor second, also a half step

- 2: major second, also a whole step

- 3: minor third
- 4: major third
- 5: perfect fourth
- 6: augmented fourth or diminished fifth
- 7: perfect fifth
- 8: minor sixth
- 9: major sixth
- 10: minor seventh
- 11: major seventh

Where does the major scale (or any other) come from? Who decides where to put the intervals of 1 and 2 (minor and major seconds)? It seems arbitrary, but there is an interesting property of the major scale: they come from a sequence of perfect fifths. Here's some code that, strangely enough, computes

The final value ofmajor = []

for i = 5 to 54 by 7

major.append(i % 12)

major.sort()

c_major = [0, major]

Scales can have the same set of intervals but start on different notes. In our representation, the first number can be changed to shift the scale to a new set of pitches. Here is a function that prints the pitch classes of a scale:

For example,// print the pitch classes of a scale

def print_scale(s) // s is in the form [base, [intervals...]]

var base = s[0]

var intervals = s[1]

for i in intervals

print (base + i) % 12,

Using scales can make melodies more coherent. You can generate a random pitch from a scale:4, 6, 8, 9, 11, 1, 3

Another possibility is to "adjust" a melody to use only pitches from a given scale. Since a pitch can be at most a minor second (1) away from a scale tone (assuming diatonic scales), you can just test to see if a pitch is in the scale, and if not, change it up or down by 1:require "utils" // import the irandom() function

// return a random pitch class in scale s

def random_from_scale(s)

var base = s[0]

var intervals = s[1]

var r = intervals[irandom(len(intervals))]

return (r + base) % 12

Although we have focused on the major scale, another common scale is the minor scale. The intervals of the minor scale are: [0, 2, 3, 5, 7, 8, 10], although there are some variations on the minor scale with other intervals. One version of minor (called melodic minor) is different depending on whether you are going up or down! Up is [0, 2, 3, 5, 7, 9, 11] and down is [12, 10, 8, 7, 5, 3, 2].require "utils" // import the irandom() function

// irandom(n) returns a random number in [0...n-1], inclusive

// test if a pitch is in scale s

def in_scale_test(p, s)

var base = s[0]

var intervals = s[1]

p = (p + 120 - base) % 12 // (positive) interval from base to p

return (p in intervals) // tests for membership

def force_to_scale_tone(p, s)

if in_scale_test(p, s)

return p // already in the scale

// adjust up or down: 50% chance of either

if irandom(2) == 0

return p + 1

else

return p -1

// generate some random notes in a scale:

for i = 0 to 20

print force_to_scale_tone(irandom(24) + 12, c_major),

One thing we should add is that the notions of key and scale are almost identical. The difference is just that "key" is used when talking about the set of pitches and their harmonic implications ("this piece is in the key of C minor"), whereas "scale" is a specific sequence of pitches ("this melody is derived from the C minor scale").

melody = [71, 71, 72, 74, 74, 72, 71, 69, 67, 67, 69, 71, 71, 69, 69]

def pitch_transpose(pitch, interval)

pitch + interval

def melody_transpose(melody, interval)

var new_melody = melody.copy() // make new result array same length

for p at i in melody

new_melody[i] = pitch_transpose(p, interval)

print "melody up a fifth is:", melody_transpose(melody, 7)

4 - 0 = 4 (a major third), and 7 - 4 = 3 (a minor third). So a major chord is a minor third on top of a major third.c_major

Another way to think about chords is through their relationship to scales. Notice that the C Major triad is the first, third, and fifth notes of the C Major scale. You can build most common chords by taking 3 to 5 alternating notes of diatonic scales!

Another important chord is the minor triad or "minor chord." The minor chord has a minor third and a perfect fifth: [0, 3, 7] (you will find these intervals in the minor scale, discussed earlier). You could also say this is a major third (from 3 to 7) on top of a minor third (from 0 to 3). Here are some notated minor thirds:

Major Triad (Maj) |
[0,
4,
7] |

Minor Triad (min) |
[0, 3, 7] |

Diminished Triad (dim) |
[0, 3, 6] |

Augmented Triad (aug) |
[0, 4, 8] |

Major Seventh (Maj7) |
[0, 4, 7, 11] |

Minor Seventh (min7) |
[0, 3, 7, 10] |

Dominant Seventh (7) |
[0, 4, 7, 10] |

Diminished Seventh (dim7) |
[0, 3, 6, 10] |

Diminished Sixth (dim6) |
[0, 3, 6, 9] |

Just as with scales, which we represented as a starting pitch class and a set of intervals, we can represent triads (or any chord) as a root and a set of intervals:

Of course, there is nothing "correct" or magical about these representations. You should think about representations that are best for your particular work. You can change representations:c_maj = [0, [0, 4, 7]]

d_maj = [2, [0, 4, 7]]

f_min = [5, [0, 3, 7]]

The# "root_interval" notation means [root, [...set of intervals above the root...]]

# "pitch_set" notation means [... set of pitch numbers ...]

#

# convert to pitch_set:

def root_interval_2_pitch_set(ri)

var root = ri[0]

var intervals = ri[1]

var ps = []

for interval in intervals

ps.append(root + interval)

return ps

# convert to root_interval:

# (to make this problem simpler, we will explicitly give the root pitch)

def pitch_set_2_root_interval(ps, root)

var ri = []

for p in ps

ri.append((1200 + p - root) % 12)

# sort the intervals in increasing order

# (In principle, we should remove duplicates as well.)

return [root, ri.sort()]

but the problem is this still sounds like C-major. There are actually 3 ways to represent the intervals in a major chord. We've seen [0, 4, 7] and we just encountered [0, 3, 8]. The last is [0, 5, 9]. These are simply "rotations" or what musicians call inversions of the major chord.pitch_set_2_root_interval([72, 64, 67], 64) ==> [64, [0, 3, 8]]

As a consequence, intervals are not the
whole story. You need to know the root of a chord and put the root on
the bottom to identify the chord type. Unfortunately, things can be a
bit ambiguous, especially when there are more then three notes in the
chord. For example, a C-sixth chord is a C-major triad with an added
major sixth interval (in pitch_set format, we could write [60, 64, 67, 69]) and an
A-minor-seventh chord is an A-minor triad with an added minor seventh
interval ([69, 72, 76, 79]).
Subtracting
12
from
the
last
three
pitches,
we
get
[69,
60, 64, 67], which is just
a permutation of the C-sixth chord.

Another aspect of voicing is the spread between tones and doublings, meaning repetition of notes at octaves. Closed voicings minimize the distance between chord tones. The music notation just above shows closed voicing for the C-major triad. Open voicings have greater distance between chord tones. Some open voicings are shown below, and in the last chord, the root (C) and fifth (G) appear in two different octaves, an example of doubling. Here, chords are notated on a grand staff (discussed earlier) which is typically used for piano music and gives a wider pitch range than a single 5-line staff.

The purpose of open voicings is to get a wider pitch spread. It's a different quality of sound and usually preferable if you want a piano accompaniment to sound big and full.

Major [0, 4, 7] |
Add major 7th [0, 4, 7, 11] Add major 6th [0, 4, 7, 9] Add major 7th and 9th [0, 4, 7, 11, 14] |

Minor [0, 3, 7] |
Add minor 7th [0, 4, 7, 10] Add major 6th [0, 4, 7, 9] Add minor 7th and major 9th [0, 4, 7, 10, 14] |

Dominant 7th [0, 4, 7, 10] |
Add major 9th [0, 4, 7, 10, 14] Add "flat 9" [0, 4, 7, 10, 13] |

How do you "suggest more is to follow"? One clue is that pitches that end on the tonic (the initial note of the scale) sound more "final" than others. A melody will generally sound incomplete unless it ends on the tonic.

Sometimes, melodies include short
distinctive phrases or sub-phrases called motives (or sometimes motifs). The most famous example is
the four-note motive at the beginning of Beethoven's Fifth Symphony,
which is used as a rhythmic and melodic building-block throughout the
entire symphony:

Source: Wikipedia
(image is public domain)Chord sequences are the foundation of harmonic structure. Just as pitch sequences sound complete and come to rest on the tonic of a scale, chord sequences tend to end on the tonic chord, the triad consisting of the tonic, third, and fifth notes of the scale (a major triad if in a major scale, and a minor triad if in a minor scale).

There are many common chord progressions. Most songs are filled with "conventional" chord transitions but often have an unusual chord transition or two. As with melody, rhythm, and harmony, if all the elements are completely expected and most likely, there are no surprises and the music can be very boring. On the other hand, if everything is a surprise, the music can sound completely incoherent, and again boring.

An aside: Modern composers often struggle to get away from tonal harmony and the common musical stuctures discussed here. This often sounds random to ears unaccustomed to this approach. Interestingly, if you avoid tonal music, your choices are anything but random, so even atonal music has a lot of predictability which you learn to hear with experience.

Common chord progressions are usually related to the interval of the fifth. In particular, a descending fifth is heard as a kind of resolution. E.g. a very final sounding final chord transition, or cadence, is G major to C major. Almost any movement up or down by a fifth within the scale is common.

Let's discuss that phrase "within the scale" in some detail. Although there are exceptions within almost every popular song, for the most part song melodies stay within a scale, and chords that accompany the melody also use pitches from the scale. Recall that the interval of a fifth is 7 semitones. If we shift (transpose) all notes of a chord up by exactly 7 semitones, this is called a chromatic transposition. If we shift within the scale, we would shift up by 4 scale tones. This is called a tonal transposition. Tonal transposition takes place within a designated scale or key.

Notice that with tonal transposition, intervals measured in semitones are not preserved. For example, in the second line of output, we see that when we transpose a C Major triad up one step, the result is a D minor triad.c_major = [0, [0, 2, 4, 5, 7, 9, 11]] // C Major scale

c_minor = [0, [0, 2, 3, 5, 7, 8, 10]] // C minor scale

major_mode = c_major[1] // intervals of the major scale

minor_mode = c_minor[1] // intervals of the (natural) minor scale

# "root_interval" notation means [root, [...set of intervals above the root...]]

# "pitch_set" notation means [... set of pitch numbers ...]

#

# convert to pitch_set:

def root_interval_2_pitch_set(ri)

var root = ri[0]

var intervals = ri[1]

var ps = []

for interval in intervals

ps.append(root + interval)

return ps

# convert to root_interval:

# (to make this problem simpler, we will explicitly give the root pitch)

def pitch_set_2_root_interval(ps, root)

var ri = []

for p in ps

ri.append((1200 + p - root) % 12)

# sort the intervals in increasing order

# (In principle, we should remove duplicates as well.)

return [root, ri.sort()]

# compute the tonal tranposition of p by interval within scale

# interval is 1=unison, 2=second, 3=third, etc.

def pitch_tonal_transpose(p, interval, scale)

var pc = p % 12 // pitch class of p

// how many semitones is pc above the root of the scale?:

var steps_from_root = (p + 1200 - scale[0]) % 12

// what scale step is this (zero-based offset):

var scale_step = scale[1].index(steps_from_root)

if scale_step == -1 // -1 means "not found in array"

return "pitch is not in the scale"

// compute the scale index after transposition

var transposed = (scale_step + interval - 1)

// shift tranposed (an index) to be within array of intervals

// keep track of octaves by adding/subtracting to octave

var octave = 0

while transposed < 0

transposed = transposed + len(scale[1])

octave = octave - 12

while transposed >= len(scale[1])

transposed = transposed - len(scale[1])

octave = octave + 12

// add the transposition in semitones to p:

return p + octave + scale[1][transposed] - steps_from_root

def chord_tonal_transpose(chord, interval, scale)

// first transpose the root

var new_root = pitch_tonal_transpose(chord[0], interval, scale)

// compute and transpose each pitch:

var pitches = root_interval_2_pitch_set(chord)

for p at i in pitches

pitches[i] = pitch_tonal_transpose(p, interval, scale)

return pitch_set_2_root_interval(pitches, new_root)

// example: print all tonal transpositions of C-major (in key of C)

c_major_triad = [60, [0, 4, 7]]

for i = 0 to 7

var triad = chord_tonal_transpose(c_major_triad, i + 1, c_major)

print triad, "=", root_interval_2_pitch_set(triad)

// OUTPUT LOOKS LIKE THIS:

[60, [0, 4, 7]] = [60, 64, 67]

[62, [0, 3, 7]] = [62, 65, 69]

[64, [0, 3, 7]] = [64, 67, 71]

[65, [0, 4, 7]] = [65, 69, 72]

[67, [0, 4, 7]] = [67, 71, 74]

[69, [0, 3, 7]] = [69, 72, 76]

[71, [0, 3, 6]] = [71, 74, 77]

The length of this code may seen daunting. Most of the code is dealing with translations between representations as semitones, scale steps, relative intervals, and absolute pitches. In this case, it would be easier to work with scale steps (7 steps to the octave). Then tonal transposition would be simple addition.

For computer generated music, it might make more sense to store chords in a table, similar to the output shown above. Then, the chords can be transposed chromatically to any desired key.

Typical chord progressions start on the tonic, move away from the tonic, and return to the tonic. The return often involve descending tonally by fifths. Another principle of chord progressions is that transitions seem to make more sense when the two chords share at least one pitch. Notice that since major and minor chords contain the interval of the fifth, that a transposition up or down by a fifth will always result in a common tone. Wikipedia's article on "Chord progression" gives a number of examples.

In computer generated music, random algorithms are often used to generate sequences. If these sequences lack repetition at the level of phrases or melodies, then they will miss out on a structural element that is very common in most music. One of the tricks of all composers is repetition with variation. A literal repetition can be boring, so often composers make small changes such as voicing chords differently, adding another accompanient voice, changing the rhythm, etc., while repeating other aspects of the music.