Below is a list of digits in the primes, and when they were discovered. (https://primes.utm.edu/notes/by_year.html)
%%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
In the pre-computer times, before 1950.
# Load python libaries
import numpy as np
import matplotlib.pyplot as plt
import IPython.display as ipd
from midiutil.MidiFile3 import MIDIFile
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')
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')
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()
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
# 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
%%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
ipd.Audio('audio/song127.mp3')
%%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
# 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")
%%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
ipd.Audio('audio/eulerPrime.mp3')
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.
%%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
print("Download digits")
ipd.FileLink("digits.dat")
# 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")
%%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
print("Download midi file")
ipd.FileLink("audio/digits.midi")
ipd.Audio('audio/digits.mp3')
Det næste er at jeg vil lave er måske en video med ciffrene, der kan køre sammen med lyden.