# Mersenne prime music¶

## 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

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.
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.
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")

Download midi file

Out[17]:
In [18]:
ipd.Audio('audio/digits.mp3')

Out[18]: