Mersenne prime music

by Ulf R. Pedersen, http://urp.dk [ulf@urp.dk]

The history of prime numbers

Below is a list of digits in the primes, and when they were discovered. (https://primes.utm.edu/notes/by_year.html)

In [1]:
%%writefile primeHistory.csv
2.1038037209559568 -300
3.9133369259326232 1456
5.7195690892638664 1588
9.3319298653811824 1772
12.50561547977515 1867
39 1876
79 1951
157 1952
183 1952
386 1952
664 1952
687 1952
969 1957
1332 1961
2917 1963
2993 1963
3376 1963
6002 1971
6533 1978
6987 1979
13395 1979
25962 1982
39751 1983
65050 1985
65087 1989
227832 1992
258716 1994
378632 1996
420921 1996
895932 1997
909526 1998
2098960 1999
4053946 2001
6320430 2003
7235733 2004
7816230 2005
9152052 2005
9808358 2006
12978189 2008
17425170 2013
22338618 2016
23249425 2017
Overwriting primeHistory.csv

In the pre-computer times, before 1950.

In [2]:
# Load python libaries
import numpy as np
import matplotlib.pyplot as plt
import IPython.display as ipd
from midiutil.MidiFile3 import MIDIFile
In [3]:
data=np.loadtxt(fname='primeHistory.csv',delimiter=' ')

plt.plot(data[:,1],np.log10(data[:,0]),'.--')
plt.xlim(1400,2050)
plt.ylim(0,8)
plt.title("Digits in largest known prime")
plt.ylabel("$log_{10}$(#digits)")
plt.xlabel('year')
Out[3]:
<matplotlib.text.Text at 0x7f6a99a4e160>
In [4]:
data=np.loadtxt(fname='primeHistory.csv',delimiter=' ')

plt.plot(data[:,1],np.log10(data[:,0]),'.--')
plt.xlim(1400,1950)
plt.ylim(0,2)
plt.title("Primes checked by hand.")
plt.ylabel("$log_{10}$(#digits)")
plt.xlabel('year')
Out[4]:
<matplotlib.text.Text at 0x7f6a9794e9e8>
In [5]:
plt.plot(data[:,1],np.log10(data[:,0]),'.--')
plt.xlim(1940,2020)
plt.ylim(0,9)
plt.title("Computer aided checkes.")
plt.ylabel("$log_{10}$(#digits)")
plt.xlabel('year')
plt.show()

Prime from acient times

Example to work with midi files (python/linux)

In the following have code snipps for how to convert data into music.

First, I will use the Python library MIDIUtil to write a midifile. Here is an example.

I will use the larges prime that it is believed was know in acient times: 127

In [6]:
# create your MIDI object
mf = MIDIFile(1)     # only 1 track
track = 0   # the only track

time = 0    # start at the beginning
mf.addTrackName(track, time, "song127")
mf.addTempo(track, time, 120)

# add some notes
channel = 0
volume = 100

pitch = 61           # 0=C4 (middle C)
time = 0             # start on beat 0
duration = 1.5       # 1 beat long
mf.addNote(track, channel, pitch, time, duration, volume)

pitch = 62           # 2
time = 2             # start on beat 2
duration = 2         # 1 beat long
mf.addNote(track, channel, pitch, time, duration, volume)

pitch = 67           # 7
time = 4             # start on beat 4
duration = 3         # 1 beat long
mf.addNote(track, channel, pitch, time, duration, volume)

# write it to disk
with open("audio/song127.midi", 'wb') as outf:
    mf.writeFile(outf)

Next, I will convert the midi file into a wave file using SoundFont synthesizer FluidSynth from the commandline

In [7]:
%%bash
settings="-C0 -R0 -r44100 -l -a alsa -o audio.alsa.device=plughw:0"
soundfont="/usr/share/sounds/sf2/FluidR3_GM.sf2"
midi="audio/song127.midi"
wav="audio/song127.wav"
fluidsynth $settings -i $soundfont -F $wav $midi
mp3="audio/song127.mp3"
rm $mp3
ffmpeg -loglevel error -i $wav -vn -ar 44100 -ac 2 -ab 192k -f mp3 $mp3
FluidSynth version 1.1.6
Copyright (C) 2000-2012 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of E-mu Systems, Inc.

Rendering audio to file 'audio/song127.wav'..
fluidsynth: warning: Failed to pin the sample data to RAM; swapping is possible.
In [8]:
ipd.Audio('audio/song127.mp3')
Out[8]:

The historical large prime of Euler

Next, lets look at the historically large prime 2147483647 dicovered in 1772 by Euler.

Convert a csv-files with note information into a song:

In [9]:
%%writefile eulerPrime.csv
62 0 1 100
61 1 1 90
64 1.5 2 100
67 3 2 90
64 4.0 1 100
68 4.5 2 90
63 6 4 100
66 7 4 90
64 8 4 80
67 9.5 2 90
Overwriting eulerPrime.csv
In [10]:
# load data-file
data=np.loadtxt(fname='eulerPrime.csv',delimiter=' ')
#pitch=data[:,0]
#time=data[:,1]
#duration=data[:,1]

# write midi
mf = MIDIFile(1)
track = 0
time = 0
mf.addTrackName(track, time, "eulerPrime")
mf.addTempo(track, time, 120)
channel=0
time=0
mf.addProgramChange(track, channel,time,6) # Change instrument
for d in data:
    pitch=int(d[0])
    time=d[1]
    duration=d[2]
    volume=int(d[3])
    mf.addNote(track, channel, pitch, time, duration, volume)

with open("audio/eulerPrime.midi", 'wb') as outf:
    mf.writeFile(outf)

print("done")
done
In [11]:
%%bash
settings="-C1 -R1 -r44100 -l -a alsa -o audio.alsa.device=plughw:0"
soundfont="/usr/share/sounds/sf2/FluidR3_GM.sf2"
midi="audio/eulerPrime.midi"
wav="audio/eulerPrime.wav"
fluidsynth $settings -i $soundfont -F $wav $midi
mp3="audio/eulerPrime.mp3"
rm $mp3
ffmpeg -loglevel error -i $wav -vn -ar 44100 -ac 2 -ab 192k -f mp3 $mp3
FluidSynth version 1.1.6
Copyright (C) 2000-2012 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of E-mu Systems, Inc.

Rendering audio to file 'audio/eulerPrime.wav'..
fluidsynth: warning: Failed to pin the sample data to RAM; swapping is possible.
In [12]:
ipd.Audio('audio/eulerPrime.mp3')
Out[12]:

Making a large Mersenne prime into music

The mersenne primes can be written in the form $$ M_n=2^n-1 $$ where only few $n$ values produce a prime numbers. These primes are interesting since they can have many digits, while it can stil be provent that they are primes. Values of $n$ that produces primes is the sequence A000668 in the OEIS, where the know values are:

n = 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657, 37156667, 42643801, 43112609, 57885161, 74207281, 77232917

In the following we will make the digits of one of the primes into sound. I will use the bc linux program to compute the digits of a Mersenne prime, and then the above method to make the sound.

In [13]:
%%bash
echo "2^521-1" | bc | tr -d '\\' \
| sed 's/.* //;s/\(.\)/\1 /g' \
| awk '{for(n=1;n<NF+1;n++){print $n}}' \
> digits.dat

head -n 5 digits.dat
echo ...
tail -n 5 digits.dat
wc digits.dat
6
8
6
4
7
...
5
7
1
5
1
157 157 314 digits.dat
In [14]:
print("Download digits")
ipd.FileLink("digits.dat")
Download digits
Out[14]:
In [15]:
# load data
data=np.loadtxt(fname='digits.dat',delimiter=' ')

# algorith to convert digit to note
def d2pitch(d=0):
    out=d+58
    return out

# write midi
mf = MIDIFile(1)
track = 0
time = 0
mf.addTrackName(track, time, "Track01")
mf.addTempo(track, time, 90)
channel=0
time=0
mf.addProgramChange(track, channel,time,90) # Change instrument
for d in data:
    pitch=d2pitch(int(d))
    time=time+1
    duration=2
    volume=100
    mf.addNote(track, channel, pitch, time, duration, volume)

with open("audio/digits.midi", 'wb') as outf:
    mf.writeFile(outf)

print("done")
done
In [16]:
%%bash
settings="-C0 -R0 -r44100 -l -a alsa -o audio.alsa.device=plughw:0"
soundfont="/usr/share/sounds/sf2/FluidR3_GM.sf2"
midi="audio/digits.midi"
wav="audio/digits.wav"
fluidsynth $settings -i $soundfont -F $wav $midi
mp3="audio/data.mp3"
rm $mp3
ffmpeg -loglevel error -i $wav -vn -ar 44100 -ac 2 -ab 192k -f mp3 $mp3
FluidSynth version 1.1.6
Copyright (C) 2000-2012 Peter Hanappe and others.
Distributed under the LGPL license.
SoundFont(R) is a registered trademark of E-mu Systems, Inc.

Rendering audio to file 'audio/digits.wav'..
fluidsynth: warning: Failed to pin the sample data to RAM; swapping is possible.
In [17]:
print("Download midi file")
ipd.FileLink("audio/digits.midi")
Download midi file
In [18]:
ipd.Audio('audio/digits.mp3')
Out[18]: