What is this about?

Recursive just intonation is a novel toy-tuning system that I came up with during my high school physics classes, It’s very easy to predict why it won’t become popular. That said I find it interesting and both mathematically and musically beautiful, so I decided to write this blogpost (listening examples further below).

Equal Temperament vs Just Intonation

Equal temperament gives us one frequency table. Every C# is the same C#, every G is the same G, and every semitone is the same distance from the last one. That is very convenient, at the cost of slightly altering almost every interval. The intervals are close enough to simple ratios that they work, but all of them are not exact.

Just intonation goes the other way. It treats notes as relationships to a root, then builds those relationships from simple frequency ratios:

  • octave: 2/1
  • perfect fifth: 3/2
  • major third: 5/4
  • major chord: 4:5:6, or 1/1, 5/4, 3/2

Those ratios sound still and locked-in because their waveforms repeat against each other quickly. In a just major chord, the consonance comes directly from the exact 4:5:6 relationship.

12-TET

In 12-tone equal temperament, the ratio between adjacent semitones is:

2^(1/12) = 1.059463...

The frequency of a note n semitones above some reference note is:

frequency(n) = reference * 2^(n/12)

The nice property is composability:

2^(1/12) * 2^(1/12) = 2^(2/12)

Going up two semitones one step at a time lands at the same frequency as jumping up two semitones directly. This is why transposition is easy in equal temperament. There is only one global grid.

Just Intonation

The annoying part is that just intonation normally needs a root. A 5/4 major third above C is E. A 5/4 major third above E is G#/Ab. Those two facts cannot both fit into one fixed 12-note keyboard unless we allow the same pitch name to mean different frequencies in different harmonic contexts.

For a C-based just-intonation scale, the usual 12 pitch classes are the five-limit ones. Every ratio in the table is made of octaves (2), perfect fifths (3/2) and major thirds (5/4), so no prime above 5 appears in it:

pitchratio from Cbuilt fromfrom 12-TET
C1/110.0¢
C#/Db16/154/3 ÷ 5/4+11.7¢
D9/83/2 × 3/2 ÷ 2+3.9¢
D#/Eb6/53/2 ÷ 5/4+15.6¢
E5/45/4-13.7¢
F4/32 ÷ 3/2-2.0¢
F#/Gb64/4516/15 × 4/3+9.8¢
G3/23/2+2.0¢
G#/Ab8/52 ÷ 5/4+13.7¢
A5/34/3 × 5/4-15.6¢
A#/Bb16/94/3 × 4/3-3.9¢
B15/83/2 × 5/4-11.7¢
C2/120.0¢

This already makes a C major chord exact:

C = 1/1
E = 5/4
G = 3/2

But an E major chord on the same fixed C just keyboard has a problem:

E      = 5/4
G#/Ab  = 8/5
B      = 15/8

Relative to E, the G#/Ab is:

(8/5) / (5/4) = 32/25 = 1.28

A just major third should be 5/4 = 1.25. So the E major chord has a fifth that works and a third that is too high by about 41.1 cents. That is not a tiny rounding error. It is enough to make the chord feel tense.

The table’s G#/Ab is an Ab: a major third below C. From E, an Ab is a diminished fourth, not a major third. The G# that E major needs is a major third above E, and a fixed 12-note keyboard has no key left for it.

What The Waves Look Like

Nice mathematical ratios are pleasant to our ears. x + 2*x, where x is some frequency, sounds nice because it has a short period:

A tone and its octave: two sine waves at a base frequency f and 2f. The whole pattern repeats every 1/f seconds, so the ear can lock onto it easily.

While, for example, x + 13/12*x has a much longer period:

A tone and a narrow nearby step: two sine waves at f and 13/12 f. The combined wave needs 12/f seconds to repeat, so it takes much longer to settle than the octave example.

A just major chord is 4:5:6, or 1:1.25:1.5. In 12-TET, the same chord is closer to 500:630:749, or 1:1.260:1.498.

Two major chords: the just version uses exact 4:5:6 ratios, while the 12-TET version uses the familiar piano/guitar approximation. They are close, but the 12-TET peaks do not quite return to the same places.

12 Just Pianos | Recursive Just Intonation

Here is what I call recursive just intonation:

Keep the roots on a C-based just-intonation keyboard, but give every chord root its own just-intonated keyboard.

I think of it as 12 pianos: one just piano rooted on C, one on C#/Db, one on D, and so on. The root of each piano is taken from the original C just-intonation scale. Once a chord chooses a root, all of its notes come from the piano rooted on that note.

This is “recursive” in the simple algorithmic sense: use a just-ratio table to choose the chord root, then use the same ratio table again inside that root.

For an E major chord:

E      = C * 5/4
G#/Ab  = E * 5/4 = C * 25/16
B      = E * 3/2 = C * 15/8

Now the E major chord is internally just:

E : G# : B = 1 : 5/4 : 3/2 = 4 : 5 : 6

The cost is that G#/Ab is no longer globally stable. Fixed-C just intonation puts G#/Ab at 8/5 from C. Recursive just intonation puts the G#/Ab inside E major at 25/16 from C.

fixed C just G#/Ab    = 8/5   = 1.6
recursive E-major G#  = 25/16 = 1.5625

Those are different frequencies sharing the same name.

The general formula is:

recursive_frequency(root, degree) =
    C_frequency * J[root] * J[degree]

where J[x] is the just-ratio table above, with octave correction whenever the index crosses C again.

The table below is the “12 pianos” idea written out as frequencies. To keep the numbers concrete, I set the C root to 130.813 Hz.

How to read it:

  • The left column chooses the chord root, or “which piano” you are using.
  • The top row chooses the interval above that root. These are ratios, not note names.
  • The cell tells you the frequency to play for that local interval.
  • The color and small label inside the cell show the resulting pitch name. Cells with the same pitch name share a color.
  • The cents line shows how far that frequency is from 12-TET for the same pitch name.

For example, an E major chord uses the E row and the 1/1, 5/4, and 3/2 columns. That gives 163.516 Hz, 204.395 Hz, and 245.274 Hz. In another octave, multiply or divide the whole row by 2.

local rootCC#/DbDD#/EbEFF#/GbGG#/AbAA#/BbB
C130.813 Hz0.000 cents139.534 Hz11.731 cents147.164 Hz3.910 cents156.975 Hz15.641 cents163.516 Hz-13.686 cents174.417 Hz-1.955 cents186.045 Hz9.776 cents196.219 Hz1.955 cents209.300 Hz13.686 cents218.021 Hz-15.641 cents232.556 Hz-3.910 cents245.274 Hz-11.731 cents
C#/Db261.626 Hz0.000 cents139.534 Hz11.731 cents148.836 Hz23.463 cents156.975 Hz15.641 cents167.440 Hz27.373 cents174.417 Hz-1.955 cents186.045 Hz9.776 cents198.448 Hz21.508 cents209.300 Hz13.686 cents223.254 Hz25.418 cents232.556 Hz-3.910 cents248.060 Hz7.821 cents
D261.626 Hz0.000 cents275.933 Hz-7.821 cents147.164 Hz3.910 cents156.975 Hz15.641 cents165.560 Hz7.820 cents176.597 Hz19.551 cents183.955 Hz-9.776 cents196.219 Hz1.955 cents209.300 Hz13.686 cents220.747 Hz5.865 cents235.463 Hz17.596 cents245.274 Hz-11.731 cents
D#/Eb261.626 Hz0.000 cents279.067 Hz11.731 cents294.329 Hz3.910 cents156.975 Hz15.641 cents167.440 Hz27.373 cents176.597 Hz19.551 cents188.370 Hz31.283 cents196.219 Hz1.955 cents209.300 Hz13.686 cents223.254 Hz25.418 cents235.463 Hz17.596 cents251.161 Hz29.328 cents
E261.626 Hz0.000 cents272.527 Hz-29.328 cents290.695 Hz-17.596 cents306.592 Hz-25.418 cents163.516 Hz-13.686 cents174.417 Hz-1.955 cents183.955 Hz-9.776 cents196.219 Hz1.955 cents204.395 Hz-27.373 cents218.021 Hz-15.641 cents232.556 Hz-3.910 cents245.274 Hz-11.731 cents
F261.626 Hz0.000 cents279.067 Hz11.731 cents290.695 Hz-17.596 cents310.075 Hz-5.865 cents327.032 Hz-13.686 cents174.417 Hz-1.955 cents186.045 Hz9.776 cents196.219 Hz1.955 cents209.300 Hz13.686 cents218.021 Hz-15.641 cents232.556 Hz-3.910 cents248.060 Hz7.821 cents
F#/Gb264.597 Hz19.553 cents279.067 Hz11.731 cents297.672 Hz23.463 cents310.075 Hz-5.865 cents330.746 Hz5.866 cents348.834 Hz-1.955 cents186.045 Hz9.776 cents198.448 Hz21.508 cents209.300 Hz13.686 cents223.254 Hz25.418 cents232.556 Hz-3.910 cents248.060 Hz7.821 cents
G261.626 Hz0.000 cents279.067 Hz11.731 cents294.329 Hz3.910 cents313.951 Hz15.641 cents327.032 Hz-13.686 cents348.834 Hz-1.955 cents367.911 Hz-9.776 cents196.219 Hz1.955 cents209.300 Hz13.686 cents220.747 Hz5.865 cents235.463 Hz17.596 cents245.274 Hz-11.731 cents
G#/Ab261.626 Hz0.000 cents279.067 Hz11.731 cents297.672 Hz23.463 cents313.951 Hz15.641 cents334.881 Hz27.373 cents348.834 Hz-1.955 cents372.090 Hz9.776 cents392.438 Hz1.955 cents209.300 Hz13.686 cents223.254 Hz25.418 cents235.463 Hz17.596 cents251.161 Hz29.328 cents
A261.626 Hz0.000 cents272.527 Hz-29.328 cents290.695 Hz-17.596 cents310.075 Hz-5.865 cents327.032 Hz-13.686 cents348.834 Hz-1.955 cents363.369 Hz-31.283 cents387.593 Hz-19.551 cents408.790 Hz-27.373 cents218.021 Hz-15.641 cents232.556 Hz-3.910 cents245.274 Hz-11.731 cents
A#/Bb261.626 Hz0.000 cents279.067 Hz11.731 cents290.695 Hz-17.596 cents310.075 Hz-5.865 cents330.746 Hz5.866 cents348.834 Hz-1.955 cents372.090 Hz9.776 cents387.593 Hz-19.551 cents413.433 Hz-7.820 cents436.043 Hz-15.641 cents232.556 Hz-3.910 cents248.060 Hz7.821 cents
B261.626 Hz0.000 cents275.933 Hz-7.821 cents294.329 Hz3.910 cents306.592 Hz-25.418 cents327.032 Hz-13.686 cents348.834 Hz-1.955 cents367.911 Hz-9.776 cents392.438 Hz1.955 cents408.790 Hz-27.373 cents436.043 Hz-15.641 cents459.889 Hz-23.463 cents245.274 Hz-11.731 cents

We now have a chord-contextual tuning system. Pitch classes split according to harmonic function.

What It Sounds Like

I picked a progression that visits chords where fixed-C just intonation has audible trouble. In the recursive version, each chord retunes around its own root.

The twelve-chord progression, written on a treble staffCEAbCFADG7CEFC

The first two columns use the same progression: once as pure sine waves, then again with a simple harmonic timbre. The third keeps a sustained C underneath the progression, so the tradeoff between a global reference pitch and chord-local purity becomes easier to hear.

tuning systemsine wave progressionharmonic timbre progressionC drone progression
12-TET
Stable pitch classes, heard without extra harmonics.
Stable pitch classes, compromised intervals.
The equal-tempered progression against a fixed C reference.
fixed C just intonation
C sounds pure; remote chords are noticeably out of tune.
C sounds pure; the added harmonics make the mistuning of remote chords easier to hear.
Fixed-C tuning remains consistent with the drone as the harmony moves to other keys.
recursive just intonation
Each chord retunes around its own C-derived root.
Chord-local roots with the simple harmonic timbre.
The drone makes it audible when chord-local roots diverge from global C.

What If The Roots Come From 12-TET?

Another way to build the 12 pianos is to take the row roots from 12-TET, then build a just-intoned scale on top of each one:

hybrid_frequency(root, degree) =
    C_frequency * 2^(root / 12) * J[degree]

So the root grid keeps equal temperament’s transposition symmetry, while each row still has just local intervals. The tradeoff is that the row roots no longer come from the original C-based just scale; they are the familiar piano frequencies with just chords built on them.

12-TET roots with just-intoned chord tones on each root.

There is also a stripped-down example that alternates a fixed-C pitch with its recursive chord-local version, then plays both at once so the beating is easier to hear:

Each split pitch written three times: fixed, recursive, and both togetherE major G#/Abfixed +0.000crecursive-41.059ctogether+0.000c / -41.059cA major C#/Dbfixed +0.000crecursive-41.059ctogether+0.000c / -41.059cD major F#/Gbfixed +0.000crecursive-19.553ctogether+0.000c / -19.553cD major Afixed +0.000crecursive+21.506ctogether+0.000c / +21.506c
The stripped-down pitch split demo: fixed C just intonation first, recursive just intonation second, then both together with the recursive offset marked in cents.
Pitch-name splits: same nominal note, different chord context.

more audio examples:

mozarts dies irae.
some composition I came up with for this blog post.

Some split points:

chord contextnotefixed C JIrecursive JIdifference
E majorG#/Ab209.300 Hz204.395 Hz-41.059 cents
A majorC#/Db279.067 Hz272.527 Hz-41.059 cents
D majorF#/Gb186.045 Hz183.955 Hz-19.553 cents
D majorA218.021 Hz220.747 Hz+21.506 cents

Why This Is Nice

The nice part is that every major chord can be made into a clean 4:5:6 relationship, even if the chord root is not C. E major does not inherit C’s G#/Ab; it gets its own G#/Ab. D major does not inherit C’s A; it gets its own A, a syntonic comma (81/80) higher.

That lines up with how I hear harmony. When a chord arrives, the ear can accept the chord root as a local center. Recursive just intonation uses that local center instead of constraining every chord to one global keyboard.

It is also a useful programming model. A chord can be rendered as:

root_frequency = base_frequency * global_just_ratio[root]
note_frequency = root_frequency * local_just_ratio[chord_degree]

The same pure function works for any root.

Why This Is Bad

The bad part shows up as soon as the chord changes: the same note name can move.

In 12-TET, G#/Ab is one frequency per octave. In fixed C just intonation, G#/Ab is also one frequency per octave, just a different one. In recursive just intonation, G#/Ab depends on why you are playing it.

A few consequences of that:

  • A melody can shift pitch if a held note is reinterpreted by the next chord.
  • Enharmonic spelling starts to matter, but a 12-key interface usually hides it.
  • Modulation requires balancing smooth voice-leading against pure local chords.
  • Instruments with fixed frets, keys, or holes cannot do this without pitch bending or multiple samples per pitch class.

So this is not a replacement for equal temperament. Equal temperament is still the practical compromise that lets every key share one physical instrument.

Practical Uses

One day I will make a keyboard on which with your left hand you can determine the current key/context and with your right hand you play notes that are dynamically retuned according to the table, until then the practical applications remain few.

My Other Music Work

Visualize and Listen to Polyrhythms in a Shader