Enharmonic Isomorphic Keyboard Layouts

Background: Algebraic Structure Of Musical Intervals And PitchesFrom Notated Music to Audible Sounds

You can use the octave and the perfect fifth, (P5, P8), as a vector basis to generate all the other intervals of a rank-2 musical temperament. That's one of the insights behind Pythagorean tuning. Here are some quick examples of rank-2 intervals and their associated numerical tuples in the (P5, P8) basis:

(-7, 4): d1
(0, 0): P1
(7, -4): A1
(-12, 7): d2
(-5, 3): m2
(2, -1): M2
(9, -5): A2
(-10, 6): d3
(-3, 2): m3
(4, -2): M3
(11, -6): A3
(-8, 5): d4
(-1, 1): P4
(6, -3): A4
(-6, 4): d5
(1, 0): P5
(8, -4): A5
(-11, 7): d6
(-4, 3): m6
(3, -1): M6
(10, -5): A6
(-9, 6): d7
(-2, 2): m7
(5, -2): M7
(12, -6): A7
(-7, 5): d8
(0, 1): P8
(7, -3): A8

It also happens to be the case that you can reach all the rank-2 musical intervals using integer multiples of (P5, P8). So not only is (P5, P8) a vector basis in R^2 (i.e. pairs of real numbers), it's a vector basis in N^2 (i.e. pairs of integers). Pretty cool. This also means that you can put pitches on a 2D isomorphic keyboard with the pitches separated by P8 in one direction and P5 in the other and the resulting layout is enharmonic; use a keyboard with enough keys, and you can get any weird rank-2 interval you want between pitches, like a four-times-diminished tenth (dddd10). It happens to be 31 keys away from P1 in one direction and 19 keys away in another direction, since (-31, 19) = dddd10.

Intervals and interval bases exist prior to the choice of any tuning system, but the N^2 bases have a neat property with respect to tuning systems that is not shared by the larger set of R^2 bases: if you take an N^2 basis and map the basis intervals to rational values for their frequency ratios, then the N^2 coefficients become integer powers in the tuning system, and a product of rational numbers raised to integer powers is still rational, so all of the intervals in the rank-2 interval space get associated to rational values for their frequency ratios. In short, not only do N^2 bases define isomorphic keyboard layouts that are enharmonic (i.e. they span rank-2 interval space), N^2 bases can also be used to define just-intonation tuning systems.

Here are 35 pairs of intervals that form N^2 bases for rank-2 temperaments, some of which might be convenient layouts for composing or playing music on an isomorphic grid keyboard: (A1, A2), (A2, A3), (M2, A1), (M2, A2), (M2, A3), (M2, A8), (M2, M7), (M6, M2), (M6, M7), (M7, A8), (P4, M2), (P4, P5), (P5, M2), (P5, M6), (P8, P4), (P8, P5), (d1, A2), (d1, M2), (d1, m2), (d2, A1), (d2, d1), (d2, m2), (d4, m2), (d4, m3), (d6, d4), (d6, m3), (d8, m3), (d8, m6), (m2, A1), (m2, M2), (m2, m3), (m3, M2), (m3, P4), (m6, P4), (m6, m3).

Those 35 pairs are all the N^2 bases that can be made from combinations of the rank-2 intervals with short names: [d1, P1, A1, d2, m2, M2, A2, d3, m3, M3, A3, d4, P4, A4, d5, P5, A5, d6, m6, M6, A6, d7, m7, M7, A7, d8, P8, A8]. I suppose 9ths would also have short 2-character names, but I didn't use them. Short names and small ordinals.

Those 35 pairs are not all created equal. For example, the (d2, A1) basis is particularly good for music pedagogy, and it's used to good effect in ejlflop's "Algebraic structure of musical intervals and pitches".

Which N^2 basis is the best for music performance though? Not (P5, P8) or (d2, A1). When you lay out the short-name intervals on a grid according to a basis, they lie on a diagonal. Here's (P5, P8): 


It's not very good for playing music, I think; it's too spread out. The bases of (P5, M2), (m3, P4), (P4, M2), and (m3, M2) seem to be the most compact ones, by which I mean that the intervals with short names will all fit on small keyboards. And that's nice for music performance; it's good to be able to reach a M3 and a d7 and so on with one hand.

Here's the last one, (m3, M2). Its diagonal is so thick, it's almost a diamond.




At a glance, it's easy to see that common musical chords will be easy to play on this. If it's not already named, I'd like to call this the Fitzgibbon basis.

How do you use the Fitzgibbon basis to make audible music? All of these bases and intervals exist prior to the choice of any tuning system. If you choose Pythagorean tuning, then the tuning map T() from intervals to their frequency ratios gives: 
T(m3) = 2^(2) * (3/2)^(-3) = 32/27 ~ 1.185185
T(M2) = (3/2)^(2) * 2^(-1) = 9/8 = 1.125
.
If you choose quarter-comma meantone tuning, then
T(m3) = 2^(1/2) * (5/4)^(-3/4) ~ 1.196279
T(M2) = (5/4)^(1/2) * 2^(0) ~ 1.118034
.
If you choose the 31-EDO generated by tempering out dddd3, then
T(m3) = 2^(8/31) ~ 1.195873
T(M2) = 2^(5/31) ~ 1.118287
.

Tuning system in hand, now you just fix the frequency of P1 to whatever number you like, perhaps 440 hertz, and then repeatedly multiply or divide it by T(m3) and T(M2) to traverse the keys of the lattice. The multiplication of frequency ratios corresponds to the addition of intervals.

I was surprised to find that Euler's tonnetz isn't an enharmonic isomorphic keyboard layout. It's based on (P5, M3), which is a rank-2 basis in R^2, but not in N^2: no number of additions and subtractions of (P5) and (M3) can take you from P1 to the 2nds, 4ths, 6ths, 8ths, or other even-ordinal intervals. You'll also hear people talk about arranging their isomorphic keyboards using the (M3, m3) basis, but that's a shear transformation of Euler's tonnetz basis, and again it doesn't generate the even-ordinal intervals. This is fine if you're playing in 12-TET where an Eb is a D#, or maybe if you have an instrument that collapses octaves (like a thing that only plays Shepard tones), but it doesn't cut the mustard for microtonal music. For that, try the Fitzgibon basis.

Well, hang on a minute. An R^2 basis still spans the rank-2 interval space, just not with integer coordinates, so there should be a way to organize rank-2 intervals or pitches in 2D space using such a basis. What happens if you try to arrange a 2D isomorphic keyboard according to an R^2 basis that isn't N^2? Well, the keys are separated by fractional amounts instead of integer amounts, so the keys overlap and you lose your nice grid. Here are some intervals represented in the quarter-comma mean-tone basis (M3, P8):
(0, 0): P1
(-5/4, 1/2): m2
(1/2, 0): M2
(-3/4, 1/2): m3
(1, 0): M3
(-1/4, 1/2): P4
(1/4, 1/2): P5
(-1, 1): m6
(3/4, 1/2): M6
(-1/2, 1): m7
(5/4, 1/2): M7
(0, 1): P8
If we use tuples like those as coordinates for the placement of our keyboard keys, we get this mess (now with vector graphics):


Can't tell what's going on. I tried doubling the spacing, and look what emerged:
.


You can see in the vertical direction, we go from P1 to M2, and in the horizontal direction we go from P1 to .... halfway between P4 and P5. And this makes total sense! Because 
    2 * M2 = M3 
(This is a fact of the algebra of rank-2 intervals, but you can verify it by looking at the tuples for M2 and M3 above in the (P5, P8) basis or the (P8, M3) basis.), and
    2 * (P4 + P5)/2 = P8.
We got back to (M3, P8)!

So if you have your heart set on using an R^2 basis to organize your isomorphic keyboard, you can sort of do it, but you have to scale everything to avoid overlap and then the intervals between one key and the next won't actually be your basis intervals, so what's the point? One possible point is that maybe one of these scaled R^2 things is more compact than the N^2 things; I haven't checked. I doubt it will be much more compact though: it seems like the layout of a scaled R^2 basis will be just one of the N^2 bases shifted by a fraction in one direction or the other or both. Honestly, I'm not going to check: even if some scaled R^2 basis gives a slightly more compact layout, it still won't be as beautiful as Fitzgibbon.

You may notice that I haven't told you how to find N^2 bases. That's because I didn't know how! The R^2 bases are just made up of linearly independent intervals, and there are lots of ways to test that, like seeing if your matrix of basis vectors is rank 2 (refresher: to find the rank of a matrix, transform it to row echelon form and count the number of non-zero rows) or if it's invertible. I found the 35 pairs in an ugly brute force way, but I just discovered that they're exactly the set that have determinant 1 or -1! Amazing. What an absolute unit.

As discussed in the last post, there's a commonly used extension of the Pythagorean basis (P5, P8) for for rank-3 intervals, namely (P8, P5, P3), and ejlilley also gives us an extension of (A1, d2) for rank-3 intervals, namely (Ac1, A1, d2). Is there interval we can add to the Fitzgibbon basis (M2, m3) to extend it to rank-3 intervals? Yes: we can add any one of (d1, A1, m2, M3). I think {A1} is the best of those on the grounds of the aesthetics of the interval names: that way we have (A1, M2, m3), which has a 1st, a 2nd, and a 3rd right in a row, and also it has intervals with successively diminished qualities (i.e. diminishing Aug gives Maj, and diminishing Maj gives a Min). Also, the subset (A1, M2) is also an N^2 basis, so we could pretend that we started with a 1st, and then added a 2nd, and then added a 3rd, ... and now we must wonder, is (A1, M2, m3, d4) an N^4 basis? If we add a {dd5}, do we get an N^5 basis? Wouldn't that be amazing? It would be amazing, but I haven't figured out an algebra for rank-4 intervals or higher, so that's a fantasy for now.

Suppose I want to play rank-3 music, and in particular, 5-limit just intonation, using an 2D isomorphic layout. Too bad, can't be done. Suppose I accept that and decide that I'll be happy if I can just play a subset of 5-limit pitches that have rank-2 names, i.e. no graves or acutes. Can that be done?  Still no.  The algebra for rank-3 intervals is a little different from that for rank-2 intervals, and, consequently, the 28 simple rank-2 intervals (d1 P1 A1 d2 m2 M2 A2 d3 m3 M3 A3 d4 P4 A4 d5 P5 A5 d6 m6 M6 A6 d7 m7 M7 A7 d8 P8 A8) don't lie on a 2d-subspace of rank-3 interval space, or at least they can't be reached using integer coordinates from two interval bases. The intervals with 2-limit names *and* odd-ordinals do however lie on a 2d-subspace of rank-3 intervals space, so you can hit all of [d1 P1 A1 d3 m3 M3 A3 d5 P5 A5 d7 m7 M7 A7] using a degenerate rank-3 basis like (P8, M3, P1), where the P1 isn't doing any work.

Small Intervals in 5-Limit Just Intonation

I've never seen two tables give all the same names for intervals in 5-limit just intonation. The Xenharmonic wiki differs from Wikipedia differs from Anatomy Of An Octave. So of course I'm adding another system to the mix. It is ejlilley's system (Haskell code here) except that he uses historical names for some of the 2nd intervals ("lesser major seconds", "greater major seconds", and variations of those) where I'm just going for straight simplicity, unencumbered by historical names. Tremendous praise to ejlilley for his work. No one has ever explained just intonation to me in words a tenth as well as he did in code.

Motivation: 5-limit just intonation is a rank-3 tuning system (i.e. represented by vectors with three component numbers), and the interval names should naturally extend those of rank-2 tuning system (the naming system and algebra for which I also learned from ejlilley). In particular, all of the intervals here either have rank-2 names, or they have rank-2 names preceded by "Grave" or "Acute" (or repetitions of one of those, like "Grave grave diminished second"). In this system, we don't need a random mix of extra adjectives like narrow, wide, semi-augmented, semi-diminished, Pythagorean, classic, greater, or lesser. We also don't need extra nouns like diesis, comma, and limma. It's so nice and tidy.

Here's the general structure of names: An interval has zero or more "Grave"s and "Acute"s at the front, but not both. Then the interval has zero or more "diminished"s and "augmented"s, but not both. Then the interval has one of three sonorities (Major, Minor, or Perfect), and finally there's an ordinal number (First, Second, Third, Fourth, ...). The Perfect and Minor sonorities are omitted for brevity when preceded by a diminution. The Perfect and Major sonorities are also omitted when preceded by an augmentation. The Perfect sonority is also omitted when immediately preceded by an Acute or Grave. For even more brevity, we write "Acdd2" for "acute diminished diminished second" and "GrM6" for "grave major sixth" and "Acm6" for "acute minor sixth" and so on.

Ejlilley's code shows the logic for assigning names to intervals represented in the (Ac1, A1, d2) basis, and this post is mostly just showing off how beautiful his system is. He walks you through building up all the intervals from the basis vectors, and then he condenses it all down and generalizes it in the jToQual function/switch-case thing. The only changes you need to make to jToQual so that the 2nd intervals are as regular and beautiful as the others is to replace Lesser with Maj on line 242, and then delete line 243. I didn't actually run his code ever, I just translated it line for line into Python. But it worked in Python.

The more common basis for representing 5-limit just intonation intervals is the [P8, P5, M3] basis. The square brackets around these basis vectors aren't doing anything different from the parentheses; I just like to distinguish the two bases that way. 

From knowing that a diminished fourth is [1, 0, -2] in the [P8, P5, M3] basis, and that the frequency ratios associated with the basis vectors in 5-limit just intonation are (2/1), (3/2), and (5/4) respectively, you can find d4's frequency ratio as (2/1)^(1) * (3/2)^(0) * (5/4)^(-2) = 32/25.

You can also calculate frequency ratios using the (Ac1, A1, d2) basis. The frequency ratios for the basis vectors are (81/80), (25/24), and (128/125) respectively, and you just raise those to the appropriate exponents and multiply together like before. The vector for the diminished fourth is (1, 4, 3) in the (Ac1, A1, d2) basis, so the frequency ratio is (81/80)^(1) * (25/24)^(4) * (128/125)^(3) = 32/25, just as before.

Below I give lots of intervals by their names, by their (Ac1, A1, d2) basis representations, by their [P8, P5, M3] basis representations, and by their frequency ratios. I've limited myself to intervals with small names, in the sense that they don't have repetitions of "grave"s, "acute"s, "diminished"s or "augmented"s.

Grd1 : (-1, -1, 0) :: [2, -3, -1] = 128/135
Gr1 : (-1, 0, 0) :: [2, -4, 1] = 80/81
Grd2 : (-1, 0, 1) :: [3, -4, -2] = 2048/2025
GrA1 : (-1, 1, 0) :: [2, -5, 3] = 250/243
Grm2 : (-1, 1, 1) :: [3, -5, 0] = 256/243
GrM2 : (-1, 2, 1) :: [3, -6, 2] = 800/729
GrA2 : (-1, 3, 1) :: [3, -7, 4] = 2500/2187
d1 : (0, -1, 0) :: [0, 1, -2] = 24/25
P1 : (0, 0, 0) :: [0, 0, 0] = 1/1
d2 : (0, 0, 1) :: [1, 0, -3] = 128/125
A1 : (0, 1, 0) :: [0, -1, 2] = 25/24
m2 : (0, 1, 1) :: [1, -1, -1] = 16/15
M2 : (0, 2, 1) :: [1, -2, 1] = 10/9
Grd3 : (0, 2, 2) :: [2, -2, -2] = 256/225
A2 : (0, 3, 1) :: [1, -3, 3] = 125/108
Grm3 : (0, 3, 2) :: [2, -3, 0] = 32/27
GrM3 : (0, 4, 2) :: [2, -4, 2] = 100/81
Grd4 : (0, 4, 3) :: [3, -4, -1] = 512/405
GrA3 : (0, 5, 2) :: [2, -5, 4] = 625/486
Gr4 : (0, 5, 3) :: [3, -5, 1] = 320/243
GrA4 : (0, 6, 3) :: [3, -6, 3] = 1000/729
Acd1 : (1, -1, 0) :: [-2, 5, -3] = 243/250
Ac1 : (1, 0, 0) :: [-2, 4, -1] = 81/80
Acd2 : (1, 0, 1) :: [-1, 4, -4] = 648/625
AcA1 : (1, 1, 0) :: [-2, 3, 1] = 135/128
Acm2 : (1, 1, 1) :: [-1, 3, -2] = 27/25
AcM2 : (1, 2, 1) :: [-1, 2, 0] = 9/8
d3 : (1, 2, 2) :: [0, 2, -3] = 144/125
AcA2 : (1, 3, 1) :: [-1, 1, 2] = 75/64
m3 : (1, 3, 2) :: [0, 1, -1] = 6/5
M3 : (1, 4, 2) :: [0, 0, 1] = 5/4
d4 : (1, 4, 3) :: [1, 0, -2] = 32/25
A3 : (1, 5, 2) :: [0, -1, 3] = 125/96
P4 : (1, 5, 3) :: [1, -1, 0] = 4/3
A4 : (1, 6, 3) :: [1, -2, 2] = 25/18
Grd5 : (1, 6, 4) :: [2, -2, -1] = 64/45
Gr5 : (1, 7, 4) :: [2, -3, 1] = 40/27
Grd6 : (1, 7, 5) :: [3, -3, -2] = 1024/675
GrA5 : (1, 8, 4) :: [2, -4, 3] = 125/81
Grm6 : (1, 8, 5) :: [3, -4, 0] = 128/81
GrM6 : (1, 9, 5) :: [3, -5, 2] = 400/243
GrA6 : (1, 10, 5) :: [3, -6, 4] = 1250/729
Acd3 : (2, 2, 2) :: [-2, 6, -4] = 729/625
Acm3 : (2, 3, 2) :: [-2, 5, -2] = 243/200
AcM3 : (2, 4, 2) :: [-2, 4, 0] = 81/64
Acd4 : (2, 4, 3) :: [-1, 4, -3] = 162/125
AcA3 : (2, 5, 2) :: [-2, 3, 2] = 675/512
Ac4 : (2, 5, 3) :: [-1, 3, -1] = 27/20
AcA4 : (2, 6, 3) :: [-1, 2, 1] = 45/32
d5 : (2, 6, 4) :: [0, 2, -2] = 36/25
P5 : (2, 7, 4) :: [0, 1, 0] = 3/2
d6 : (2, 7, 5) :: [1, 1, -3] = 192/125
A5 : (2, 8, 4) :: [0, 0, 2] = 25/16
m6 : (2, 8, 5) :: [1, 0, -1] = 8/5
M6 : (2, 9, 5) :: [1, -1, 1] = 5/3
Grd7 : (2, 9, 6) :: [2, -1, -2] = 128/75
A6 : (2, 10, 5) :: [1, -2, 3] = 125/72
Grm7 : (2, 10, 6) :: [2, -2, 0] = 16/9
GrM7 : (2, 11, 6) :: [2, -3, 2] = 50/27
Grd8 : (2, 11, 7) :: [3, -3, -1] = 256/135
GrA7 : (2, 12, 6) :: [2, -4, 4] = 625/324
Gr8 : (2, 12, 7) :: [3, -4, 1] = 160/81
GrA8 : (2, 13, 7) :: [3, -5, 3] = 500/243
Acd5 : (3, 6, 4) :: [-2, 6, -3] = 729/500
Ac5 : (3, 7, 4) :: [-2, 5, -1] = 243/160
Acd6 : (3, 7, 5) :: [-1, 5, -4] = 972/625
AcA5 : (3, 8, 4) :: [-2, 4, 1] = 405/256
Acm6 : (3, 8, 5) :: [-1, 4, -2] = 81/50
AcM6 : (3, 9, 5) :: [-1, 3, 0] = 27/16
d7 : (3, 9, 6) :: [0, 3, -3] = 216/125
AcA6 : (3, 10, 5) :: [-1, 2, 2] = 225/128
m7 : (3, 10, 6) :: [0, 2, -1] = 9/5
M7 : (3, 11, 6) :: [0, 1, 1] = 15/8
d8 : (3, 11, 7) :: [1, 1, -2] = 48/25
A7 : (3, 12, 6) :: [0, 0, 3] = 125/64
P8 : (3, 12, 7) :: [1, 0, 0] = 2/1
A8 : (3, 13, 7) :: [1, -1, 2] = 25/12
Acd7 : (4, 9, 6) :: [-2, 7, -4] = 2187/1250
Acm7 : (4, 10, 6) :: [-2, 6, -2] = 729/400
AcM7 : (4, 11, 6) :: [-2, 5, 0] = 243/128
Acd8 : (4, 11, 7) :: [-1, 5, -3] = 243/125
AcA7 : (4, 12, 6) :: [-2, 4, 2] = 2025/1024
Ac8 : (4, 12, 7) :: [-1, 4, -1] = 81/40
AcA8 : (4, 13, 7) :: [-1, 3, 1] = 135/64

Conversion between the (Ac1, A1, d2) and [P8, P5, M3] bases is straightforward if you know the representations of the basis vectors in the other system - in particular, if you know that:

    Ac1 = (1, 0, 0) :: [-2, 4, -1]
    A1 = (0, 1, 0) :: [0, -1, 2]
    d2 = (0, 0, 1) :: [1, 0, -3]

and that

    P8 = [1, 0, 0] =  (3, 12, 7)
    P5 = [0, 1, 0] = (2, 7, 4)
    M3 = [0, 0, 1] = (1, 4, 2)
.

If we call the components of a vector in the (Ac1, A1, d2) representation (m, n, o) and we call the components of a vector in the [P8, P5, M3] basis [p, q, r], then converting from (m, n, o) to [p, q, r] requires only:

p = -2*m + 0*n + 1*o
q = 4*m + -1*n + 0*o
r = -1*m + 2*n - 3*o

You can see that the columns of coefficients are just the (Ac1, A1, d2) basis vectors represented in the [P8, P5, M3] basis.

Likewise, to convert from [p, q, r] to (m, n, o), we only require:

m = 3*p + 2*q + 1*r
n = 12*p + 7*q + 4*r
o = 7*p + 4*q + 2*r

And likewise here, the columns are [P8, P5, M3] in the (Ac1, A1, d2) basis.


Let me say that another way: to convert from one basis to a second, you find the old basis vectors in the new basis, and then convert the rows of those vectors into columns in a little matrix function.

I have some other nice functions for playing with Just Intonation, like for finding [p, q, r] tuples from frequency ratios, but I think that's a good place to stop. I wanted to show you that there's a simple system for naming these things, and that everyone else looks ridiculous compared to the upright, shining example of ejlilley.