Pitch Class Sets

tuning
music theory

January 03, 2021

Let's explore the world of pitch class sets. Note: This post is not optimized for dark mode.

Harmonic & Chromatic Circles

There are (at least) two ways we can represent 12 notes in a circle:

Circle of Fifths

CGDAEBGbDbAbEbBbF

Chromatic Circle

CDbDEbEFGbGAbABbB
C
major


Chroma: 101011010101 = 2773

The blue line connects all pitches that are part of the selected scale. Using those representations, we can build a geometric intuition for musical phenomena. In a nutshell, the circle of fifth helps to understand harmonic relationships, while the chromatic circle works better for melodic content.

Chromas & Set Numbers

In the circles above, a so called chroma is displayed for each scale. A chroma is a format to represent a set of notes. For example, the chroma of a C major scale is 101011010101.

The idea: each digit stands for 1 of 12 possible pitches, where the first digit is C, then going chromatically up. A 1 means that the pitch that is represented by the digit is in the set, a 0 means it is not.

A set number is just the decimal representation of a chroma:

C D EF G A B  = setNum
101011010101 = 2773
^

To find more about scale representations, be sure to check out The Exciting Universe of Music Theory. Unfortunately, the chromas and set numbers are reversed, which does not seem right to me. Read these comments to find out more.

Chroma from Scale

To get the chroma for a given scale, we can do this:

PcSet.get(Scale.get('D dorian')).chroma; // 101011010101

You might wonder why we do not use this:

Scale.get('D dorian').chroma; // 101101010110

If you take a closer look at the chroma, you will notice that it represents C dorian, practially ignoring the "D", which is impractical for our purpose.

Why not Scale.get().chroma ?

Because it is always relative to C, ignoring the root of the scale:

const scaleProps = Scale.get('G major');

scaleProps.chroma;
// '101011010101' => ingores G

PcSet.get(scaleProps.notes).chroma;
// '101011010101' => relative to G => correct

Scale from Chroma

As the opposite of the above, we might also want the scale for a given chroma:

const chromaScale = (chroma, tonic, scaleTypes = Scale.names()) => {
  const type = scaleTypes.find((type) => scaleChroma(`${tonic} ${type}`) === chroma);
  if (type) {
    return `${tonic} ${type}`;
  }
  return '';
};
expect(chromaScale('101011010101', 'C')).toBe('C major');
expect(chromaScale('101011010101', 'D')).toBe('D dorian');
expect(chromaScale('101011010101', 'E')).toBe('E phrygian');
expect(chromaScale('101011010101', 'Eb')).toBe('');

Chroma from Chord

Of course, we can also represent a chord as a chroma:

C D EF G A B  = setNum
100010010000 = 2192
^

Set Concepts

Let's look at different concepts around pitch class sets.

Modes

These are the 7 modes of C major:

C majorCDbDEbEFGbGAbABbB
D dorianCDbDEbEFGbGAbABbB
E phrygianCDbDEbEFGbGAbABbB
F lydianCDbDEbEFGbGAbABbB
G mixolydianCDbDEbEFGbGAbABbB
A aeolianCDbDEbEFGbGAbABbB
B locrianCDbDEbEFGbGAbABbB
  • All of the above resemble the same set (same pitches)
  • Each set can be started at any contained pitch, which gives n modes for n pitch sets.

Transpositions / Rotations

Transposing a set leads to rotation. These are the 12 major scales:

C majorCDbDEbEFGbGAbABbB
Db majorCDbDEbEFGbGAbABbB
D majorCC#DEbEFF#GAbABbB
Eb majorCDbDEbEFGbGAbABbB
E majorCC#DD#EFF#GG#ABbB
F majorCDbDEbEFGbGAbABbB
F# majorCC#DD#EE#F#GG#AA#B
G majorCDbDEbEFF#GAbABbB
Ab majorCDbDEbEFGbGAbABbB
A majorCC#DEbEFF#GG#ABbB
Bb majorCDbDEbEFGbGAbABbB
B majorCC#DD#EFF#GG#AA#B

For some scales, there are less than 12 unique rotations, for example:

C whole toneCDbDEbEFF#GG#ABbB
Db whole toneCDbDEbEFGbGAbABbCb
D whole toneCDbDEbEFF#GG#AA#B
  • The above example shows that there are just 2 whole tone scales
  • After 2 rotations, we end up with D whole tone, which is a mode of C whole tone => same notes
  • All symmetric scales will have less than 12 unique rotations

Complements

A complement can be obtained by using the gaps of another set:

D majorCC#DEbEFF#GAbABbB
Ab pentatonicCDbDEbEFGbGAbABbB
  • Each set has exactly one complement

Reflections

The reflection of a set can be generated by flipping it around:

Flipping around the 1 / b5 will drop a major third down:

C majorCDbDEbEFGbGAbABbB
Ab majorCDbDEbEFGbGAbABbB

Flipping around the 5th / b2 gives us whole tone steps down:

C majorCDbDEbEFGbGAbABbB
Bb majorCDbDEbEFGbGAbABbB

Flipping around at the 2nd / b13 degree returns the same set:

C majorCDbDEbEFGbGAbABbB
C majorCDbDEbEFGbGAbABbB

Flipping around at the 6th / b3:

C majorCDbDEbEFGbGAbABbB
D majorCC#DEbEFF#GAbABbB

Flipping around at the 3rd / b7:

C majorCDbDEbEFGbGAbABbB
E majorCC#DD#EFF#GG#ABbB

Flipping around at 4th / 7:

C majorCDbDEbEFGbGAbABbB
Gb majorCDbDEbEFGbGAbABbCb

Negative Harmony Reflections

If we move the axis between the notes, we can get the "negative harmony":

C majorCDbDEbEFGbGAbABbB
C aeolianCDbDEbEFGbGAbABbB

Here, the C major scale is flipped around the axis between Eb/E and A/Bb.

Conclusion

This was just a broad overview of some things that can be done with pitch class sets. I will write about more concepts and some of the above in greater detail in future posts. Be sure to check out the links below:

  • clickable nodes to listen to scale, or hotkeys 1-9, or play button

  • be able to draw lines between nodes in connected circle (for negative harmony axis)

  • [x] get reflection programmatically

  • chromaSymbols(chroma) to scales, chords, intervals

  • show some chord reflections

  • fix order of rotation (wrong for non diatonic scales)

  • add relative switch => show intervals instead of pitch class names

  • coherent coloring: pitch classes should always have the same color (across both circles)

  • two level scale sorting: sort first after number of notes, only if same number after the above

  • different scale sortings: byScaleNum, byCenter, alphatbetically.

  • show scale properties: chroma, scaleNum, accidentals, related scales, supersets, subsets

  • show nearby scales: 1 altered note (1 added note, 1 removed note => already shown sub/supersets)

  • handle unnamed scales: allow rotation into scales that do not have a name

  • also allow chords + maybe intervals

  • curved lines

  • animation??

Felix Roos 2023