Playing piano with prime numbers
Last weekend, I decided to turn prime numbers into a mini piano and see what kind of music math could make.
Generating prime numbers
The simplest method is to check divisibility of each number by all small numbers. But it is inefficient for large datasets due to its complexity: O(n√n)
for (let i = 2; i <= Math.sqrt(n); i++) {
if (n % i === 0) return false;
}
We'll use the Sieve of Eratosthenes here, as it's better (Time complexity: O(nloglogn)). Think of it like a game to cross out numbers that aren't prime until only the prime ones are left. Using count * Math.log(count) * 1.5
, it estimates how many numbers it needs to look to find the required prime numbers (count is the number of primes we want).
const sieve = new Array(maxEstimate).fill(true);
sieve[0] = sieve[1] = false;
for (let i = 2; i * i < maxEstimate; i++) {
if (sieve[i]) {
for (let j = i * i; j < maxEstimate; j += i) {
sieve[j] = false;
}
}
}
Mapping strategy
Once we have the prime list, we need to map them to convert the primes into frequencies for sound. By mapping our primes to MIDI arrays, we can play single notes or complex chords.
// Alternates each prime's MIDI note up or down by its offset
// creating a mirrored pattern around middle C.
primes.map((p, i) => {
const offset = p % 24;
return i % 2 === 0 ? clampMidi(60 + offset) : clampMidi(60 - offset);
...
clampMidi
keeps a MIDI note within the piano's playable range (21-108).
Producing sound
Here, each prime becomes a MIDI number.
From here, we can use a soundfont library like soundfront-player
which contains packaged mp3 samples for each note in a single JS file.
Unlike synthesizing tones using oscillators, each note is a real piano sample stored as an MP3, giving a natural sound.
Playback is handled with precise scheduling using AudioContext
, so sequences of primes or chords remain in sync. By timing each note correctly, we can make the primes “playable” like a piano piece.
Final thoughts
Overall, this was a fun little project to play with prime numbers and the piano. I played around with various mapping techniques, e.g. using continuous ranges so higher primes produce higher pitches.
It's also interesting to see patterns emerge when listening. This project shows how math and sound can intersect in creative ways, and it can be a starting point for more generative music experiments in the future.
See the complete code on Github