← DEVLOG
Interactive2025.11.085 min read

Harmony — Kepler's Dream, Music Played by Planets

An interactive orchestra that converts the orbital periods of all 8 planets into pitch — Web Audio synthesis, scale quantization, and recording/playback

web-audiomusickeplerorbital-mechanicsrecording

The Idea — Musica Universalis

In 1619, Johannes Kepler argued in Harmonices Mundi that planetary orbital speeds form musical ratios. Faster orbits produce higher notes; slower ones, lower notes.

This page brings that idea to life. From Mercury to Neptune, actual orbital period ratios are converted to Hz, assigning each planet a musical tone.


From Orbital Periods to Frequencies

Shorter orbital periods map to higher pitches. Mercury (88 days) gets C5 (523Hz); Neptune (60,190 days) gets C2 (65Hz).

// Real orbital periods → frequency mapping (inverse-period scaling)
const PLANETS = [
  { id: 'mercury', orbitalPeriodDays: 88, baseFrequency: 523.25, waveform: 'triangle' },
  { id: 'venus', orbitalPeriodDays: 225, baseFrequency: 392.0, waveform: 'triangle' },
  { id: 'earth', orbitalPeriodDays: 365, baseFrequency: 329.63, waveform: 'triangle' },
  // ...
  { id: 'neptune', orbitalPeriodDays: 60190, baseFrequency: 65.41, waveform: 'sine' },
];

Inner planets (Mercury through Mars) use triangle waveforms for a bright, clear timbre. Outer planets (Jupiter through Neptune) use sine waveforms for a deeper, smoother sound — larger bodies carrying more fundamental vibrations.


Scale Quantization

Playing each planet's raw frequency would produce dissonance. The quantizeToScale function snaps each frequency to the nearest note in the selected scale.

function quantizeToScale(freq: number, scale: ScaleConfig): number {
  const semitonesFromA4 = 12 * Math.log2(freq / 440);
  let relativeSemitone = ((Math.round(semitonesFromA4) % 12) + 12) % 12;

  // Find the closest scale degree
  let bestInterval = 0;
  let bestDist = Infinity;
  for (const interval of scale.intervals) {
    const dist = Math.abs(relativeSemitone - (interval % 12));
    if (dist < bestDist) {
      bestDist = dist;
      bestInterval = interval % 12;
    }
  }

  return 440 * Math.pow(2, (octaveBase + bestInterval) / 12);
}

Three scales are available: major, minor, and pentatonic. The same planet combination sounds entirely different with each scale. Major feels bright and hopeful, minor is deep and dreamlike, pentatonic carries an Eastern melodic quality.


Recording and Playback

The sequence of toggling planets and switching scales is captured as timeline events.

interface CompositionEvent {
  time: number; // ms from recording start
  type: 'planet' | 'scale';
  planetId?: string;
  action?: 'on' | 'off';
  scaleIdx?: number;
}

During playback, each event is scheduled via setTimeout while requestAnimationFrame drives real-time timeline progress updates. Up to three compositions can be saved in localStorage.


Orbital View

Eight concentric orbits radiate from a central sun. Each planet appears as a dot on its orbit, and when activated, the orbital ring lights up in the planet's signature color.

.orbit {
  border: 1px solid rgba(var(--js2-primary), 0.12);
  transition:
    border-color 0.4s,
    box-shadow 0.4s;
}
.orbitActive {
  border-color: var(--orbit-color);
  box-shadow:
    0 0 8px color-mix(in srgb, var(--orbit-color) 30%, transparent),
    inset 0 0 8px color-mix(in srgb, var(--orbit-color) 15%, transparent);
}

Orbit spacing ensures even the largest planet (Jupiter, 50px) never overlaps an adjacent orbit ring. With minR=40 and maxR=250, a 30px gap between each orbit is maintained.


Closing Thoughts

Kepler could never hear the music of the planets. In the 17th century, there was no way to render the sounds of space.

Four hundred years later, the browser's Web Audio API makes his imagination tangible. When Mercury's bright triangle waveform sounds alongside Neptune's deep sine wave, what emerges sits somewhere between science and music.

Turn on the planets, one by one. The universe begins to play.

Content related to this post

Try it yourself

Guestbook

Leave a short note about this post

0 / 140

Loading...