Give each of two notes its own axis, let a single dot be pushed by both, and a fifth draws a neat loop while a semitone draws a dense tangle. Slow the notes down far enough and the same ratio becomes a rhythm you can tap along to. I built Interval Shapes to see and hear that at the same time.

I started studying music theory recently, mostly to understand how the guitar works and to play it better. When I saw a video on Instagram of something like this, I wanted to build my own version to learn more.

The pictures are a good way to see what a frequency ratio is and what piano tuning does to it. They don't explain why a fifth sounds good. Some of their tidiest numbers depend on which ratio you choose to call an interval, a piano's fifth sounds fine with a curve that never closes, and the research on consonance points to overtones, which these curves don't draw at all.

A note on each axis

A note is a vibration, and its frequency is how many times a second it repeats, measured in hertz (Hz). Middle C is 261.63 Hz. An interval is the distance between two notes, and the ear hears that distance as a ratio rather than a difference: 220 to 330 Hz and 440 to 660 Hz are 110 and 220 Hz apart, but both are 2 : 3, and both sound like a fifth. Ratios here are written lower note first, as the app shows them: C : G = 2 : 3 means G vibrates 3 times while C vibrates twice.

A Lissajous curve is what you get when steady oscillations act at right angles on the same point. Nathaniel Bowditch studied them in 1815 with a compound pendulum. Jules Antoine Lissajous, working independently, published his in 1857, reflecting light off mirrors on two vibrating tuning forks. The figures were later used to calibrate tuning forks, so they have been tied to musical pitch for a long time.

The app makes each note one of those oscillations. Time t is counted in cycles of the lowest note, C, and r is each note's frequency divided by C's:

x(t) = sin(2π · r₁ · t)
y(t) = sin(2π · r₂ · t)
z(t) = sin(2π · r₃ · t)

One note draws a plain wave against time, two draw a flat curve, and three draw a curve through a cube that you can rotate. The whole model is that formula in a loop:

const omegas = ratios.map((r) => 2 * Math.PI * r);
for (let i = 0; i < count; i++) {
  const t = t0 + (span * i) / (count - 1);
  for (let d = 0; d < omegas.length; d++) out[i * stride + d] = Math.sin(omegas[d] * t);
}

What the intervals draw

The curve closes when every wave is back where it started at the same moment. If the ratio in lowest terms is a : b, that takes a cycles of the lower note, while the upper note does b. Small numbers make a short loop, and large ones make a long path that crosses itself many times first.

The octave, 1 to 2: a figure of eight on its side
Octave, 1 : 2
The fifth, 2 to 3: a closed loop with three lobes along the top and two down the side
Fifth, 2 : 3
The major third, 4 to 5: a busier closed knot with five lobes along the top
Major third, 4 : 5
The major sixth, 3 to 5: an open path with two free ends that folds back over itself
Major sixth, 3 : 5
The semitone, 15 to 16: a dense woven mesh that nearly fills the square
Semitone, 15 : 16
The tritone, 32 to 45: a mesh so dense that it fills the square
Tritone, 32 : 45

You can read a ratio off a flat curve: count where it touches the top edge and where it touches a side edge. The fifth touches the top three times and the side twice. The exception is when both numbers are odd, as in the major sixth: with every wave starting at zero, the path folds back over itself into an open path with two free ends, so some of the touches land on top of each other.

Here is every interval from C, using the app's ratios. A cent is a hundredth of a semitone, and the last column shows how far a piano sits from each ratio, where + means the piano is sharp.

Interval Ratio Closes every (cycles of C) Piano, in cents
Minor 2nd 15 : 16 15 −11.7
Major 2nd 8 : 9 8 −3.9
Minor 3rd 5 : 6 5 −15.6
Major 3rd 4 : 5 4 +13.7
Perfect 4th 3 : 4 3 +2.0
Tritone 32 : 45 32 +9.8
Perfect 5th 2 : 3 2 −2.0
Minor 6th 5 : 8 5 −13.7
Major 6th 3 : 5 3 +15.6
Minor 7th 5 : 9 5 −17.6
Major 7th 8 : 15 8 +11.7

Three notes work the same way. A major triad is 4 : 5 : 6 and closes every 4 cycles of C. A minor triad is 10 : 12 : 15 and takes 10.

Hearing the ratio as a rhythm

The real notes realign far too fast to follow: a fifth's two waves line up about 131 times a second. The app slows everything down about 260 times, so that at its default tempo C completes one cycle a second, and gives each note a short pluck at the start of each of its own cycles. The ratio turns into a rhythm:

Interval Plucks a minute Land together every
Octave, 1 : 2 60 : 120 1 second
Fifth, 2 : 3 60 : 90 2 seconds
Major third, 4 : 5 60 : 75 4 seconds
Major triad, 4 : 5 : 6 60 : 75 : 90 4 seconds
Semitone, 15 : 16 60 : 64 15 seconds

The rhythm is the same arithmetic as the curve: the notes land together exactly when the shape closes. A fifth is a two-against-three polyrhythm, and a semitone drifts slowly out of step and back. An optional metronome ticks on C's beat, with a louder tick each time the shape closes, so you can count it.

Be careful what this shows, though. It's a demonstration of the ratio, not of what you hear when the interval is played: at full speed those realignments happen hundreds of times a second and merge into a single sound. The pitch of each pluck is real, but the rhythm exists only because of the slowing down.

The app also has a glide. Drag the upper note smoothly from C up an octave, and the curve tangles and then snaps into a clean loop each time you pass a simple ratio. The slider catches on each one, and buttons step one cent off it, which is enough to watch the loop start to come apart.

Some of these numbers are choices

That interval table looks like a ranking of how good intervals sound, and the fifth at 2 and the tritone at 32 fit the story neatly. It deserves less trust than it appears to.

The ratios aren't facts of nature. Tuning an interval to whole numbers is called just intonation, and it offers more than one answer. By default the app uses 5-limit ratios, built only from the primes 2, 3 and 5, which gives the tritone 32 : 45 and a 32-cycle tangle. A tritone of 5 : 7 is a simpler answer, 17.5 cents below a piano's rather than 9.8, and it closes in 5. The diminished triad then goes from 160 : 192 : 225, closing every 160 cycles, to 5 : 6 : 7, closing every 5. The impressive number comes from a choice of ratio, so the app has a switch between the two.

Closing time is a rough measure. It only sees the lower note's number. The major 2nd and major 7th both close every 8 cycles, and the minor 3rd and minor 7th every 5, yet nobody would call them interchangeable.

The shape depends on where the waves start. The app starts every wave at zero, which a real instrument wouldn't. Start one wave late and the curve changes, while how often it repeats doesn't. Two notes in unison draw a diagonal line or a circle depending only on that offset, and a fifth started an eighth of a cycle late folds into an open path, just as the major sixth does. So the picture isn't a fingerprint of the interval. The closing time is what belongs to the ratio.

A unison with both waves in step: a straight diagonal line
Unison, in step
A unison with one wave a quarter of a cycle late: a circle
Unison, a quarter cycle late
A fifth with the upper wave an eighth of a cycle late: an open path with two free ends that folds back over itself
Fifth, an eighth of a cycle late

What piano tuning does to the curve

A piano has to play in every key, so it can't use ratios that only work from one root. Equal temperament, the tuning pianos use, splits the octave into 12 identical steps, each a factor of 21/12 (about 1.0595). Every interval except the octave then becomes an irrational number, so the curve never closes. It drifts instead.

A piano's major third, four cycles from the start
Piano major third, first 4 cycles
The same interval's four cycles starting 6 cycles later: the knot has rolled over
4 cycles, starting 6 later
The same interval's four cycles starting 12 cycles later: the knot has rolled further
4 cycles, starting 12 later

This is where the picture connects to something you can hear. Instruments don't play pure waves: a note also contains overtones at 2, 3, 4 or more times its frequency. When two nearly equal frequencies sound together they go in and out of step, and you hear a slow wobble in loudness called beating. In a piano's intervals, the overtones that a just ratio would line up exactly come out slightly apart:

Piano interval from middle C Overtones that nearly meet Beats Curve's drift repeats every
Fifth, C to G C × 3 = 784.89 Hz, G × 2 = 784.00 Hz 0.89 a second about 295 cycles of C
Major third, C to E C × 5 = 1,308.15 Hz, E × 4 = 1,318.52 Hz 10.38 a second about 25 cycles of C

The two right-hand columns are the same number in different units: 261.63 cycles of C a second divided by 295 is 0.89, and divided by 25.2 is 10.38. So the curve's drift runs at the rate of the beating. A third drifts visibly because its beating is fast, and a fifth barely moves because its beating is slow.

At the app's default tempo of one cycle of C a second, the fifth's drift would take about five minutes to come back around. So the app's Compare mode draws just and piano tuning side by side and exaggerates the piano's mistuning until its drift turns over in a few seconds. Kept over several loops, the just curve retraces one line while the piano curve fans out into a band. The exaggeration is only in the picture: the sound, and the ratios printed above each plot, keep the real piano values.

Pure sine waves, which are what the curves draw, have no overtones, so this beating is hard to hear from them. The app's organ voice has the overtones and makes it much easier to hear.

What the curves don't explain

The tempting conclusion is that simple shapes sound good because they're simple. Your ear doesn't draw this curve, and the evidence points elsewhere.

  • Pure tones don't follow the ratios. In 1965, Plomp and Levelt had people judge pairs of pure tones. Consonance depended on how far apart the frequencies were relative to the ear's critical bandwidth (the range within which two tones interfere with each other), and not on small whole-number ratios. Their account builds on Helmholtz's: real instruments sound rough when neighbouring overtones beat against each other. Simple ratios matter because that's where overtones line up, so the shape and the sound share a cause, but one doesn't produce the other.
  • The curve ignores register. A 4 : 5 draws the same shape at any pitch, but a major third that sounds clear in the middle of a piano turns muddy near the bottom.
  • The curve is all or nothing, and the ear isn't. A piano's fifth is 2 cents from 2 : 3. Its curve never closes, yet it sounds like a fifth to almost everyone.
  • Some of the preference is learned. A 2016 study in Nature found that the Tsimane', an Amazonian group with little exposure to Western music, rated consonant and dissonant chords about equally pleasant. The study doesn't say that ratios are irrelevant to hearing, but the leap from "tidy shape" to "sounds nice" isn't universal.

So the curves show the arithmetic that consonance sits on, not the experience of it.

How it's built

It's a static site with no backend, like this one.

  • The 2D plot is a plain <canvas> with its own animation loop, which reads its settings through a ref so that changing them never restarts the loop.
  • The 3D plot uses three.js through react-three-fiber. That's about 250 KB gzipped, so it's only loaded when you pick a third note.
  • The sound is a small synth on the browser's own Web Audio API: envelopes, an FM electric piano, an organ built from overtones, reverb and a limiter. On iOS the audio has to be created and resumed directly inside the tap handler, or it stays silent.
  • Keeping sound and picture together. The plot's animation clock places every note. Each frame it checks which notes start a new cycle within the next tenth of a second and schedules them on the audio clock, which is far more precise than a timer. In testing, each note landed within about 20 ms of the dot. Notes due together are scheduled from a single reading of the audio clock: reading it once per note split a chord by up to 9 ms.
  • Checking the pitch can't rely on listening in an automated test, so the checks route the output into an analyser and compare the loudest frequencies with the expected ones.

Try it at music-viz.rrjamal.ca. Pick a fifth and press Play to hear the rhythm, then pick a major third and choose Compare to watch the piano's version drift. Its How it works section goes from what a note is to piano tuning in six short steps.