15
\$\begingroup\$

Yup, you read the title right. play the sound of pi.

More specifically, for every digit of pi in the first 1000, map it to a musical note and output the resulting melody to a file.

Basically, each digit turns to a note on the C Major scale (basically the normal scale). so 1 turns to Middle C, 2 turns to D4, 3 turns to E4, 9 turns to D5 and so on.

Rules

  • Each note should be exactly 0.5 seconds long.
  • The melody should contain the first 1000 digits of pi, including the starting 3.
  • 1 to 7 represent Middle C to B4, 8 is C5, 9 is D5 and 0 is E5
  • All well supported file formats are allowed, as long as they were created before this challenge.
  • There may be no pauses anywhere in the file, including the start and end.
  • The instrument played does not matter. It could be a piano, sine wave, anything really, as long as the correct sound is easily hearable.
  • It must take no input and produce no output except for the file. Reading from other files is disallowed.
  • Standard loopholes are forbidden.

Example mathematica code:

(*please forgive me for this horrible, horrible mess of code*)
digits = RealDigits[Pi, 10, 1000][[1]] /. {0 -> 10};
weights = {0, 2, 4, 5, 7, 9, 11, 12, 14, 16}; 
melody = {};
For[i = 1, i < 1001, i++, melody = {melody , Sound[SoundNote[weights[[digits[[i]]]], 0.5]]}]
final = Sound[Flatten[melody]];
Export["C:\\Mathematica Shenanigans\\pi.wav", final];

Example melody showing first 100 digits: http://vocaroo.com/i/s0cfEILwYb8M

For your sanity, A table of pitches for each note and what note does each digit represent:

Digit 1: C: 261.63 Hz
Digit 2: D: 293.66 Hz
Digit 3: E: 329.63 Hz
Digit 4: F: 349.23 Hz
Digit 5: G: 392.00 Hz
Digit 6: A: 440.00 Hz
Digit 7: B: 493.88 Hz
Digit 8: C5: 523.25 Hz
Digit 9: D5: 587.33 Hz
Digit 0: E5: 659.25 Hz
\$\endgroup\$
9
  • 5
    \$\begingroup\$ 9 turns to D5 You should clarify that the other notes are in the 4-th octave. Also, in your table does digit 0 come last (E5)? \$\endgroup\$
    – Luis Mendo
    Jan 17, 2017 at 22:11
  • 1
    \$\begingroup\$ @LuisMendo Yes it does. I'll make these too more clear. \$\endgroup\$
    – sagiksp
    Jan 18, 2017 at 4:57
  • 1
    \$\begingroup\$ Can we assume 'well supported formats' to mean anything openable by vlc? \$\endgroup\$
    – Pavel
    Jan 18, 2017 at 6:14
  • \$\begingroup\$ @Pavel Pretty much \$\endgroup\$
    – sagiksp
    Jan 18, 2017 at 8:58
  • \$\begingroup\$ Can I output the note names (e.g. 3.14 --> ECF) if my language does not support sound or writing to sound files? \$\endgroup\$
    – FinW
    Jan 18, 2017 at 19:42

5 Answers 5

10
\$\begingroup\$

Python 2, 182 bytes

x=p=6637
while~-p:x=p/2*x/p+2*10**999;p-=2
s="MThd\0\0\0\6\0\1\0\1\342\4MTrk\0\0\13\301\0\220"
for i in`x`:s+="JHGECA@><L\260"[~ord(i)%29]+'{<'
open('p.mid','w').write(s+"\0\377/\0")

`x` will produce 31415926...20198L. The trailing L is used to produce the final channel message byte, via the mapping ~ord(i)%29.

Outputs a single track Type 1 Midi file, named p.mid to the current working directory.

0000: 4d 54 68 64 00 00 00 06  MThd....  # Midi header, 6 bytes to follow
0008: 00 01 00 01              ....      # Type 1, 1 track
000c: e2 04                    â.        # (-)30 ticks per beat, 4 beats per second

000e: 4d 54 72 6b 00 00 0b c1  MTrk...Á  # Track header, 3009 bytes to follow
0016: 00 90 40 7b              ..@{      # Wait  0 ticks, play E4 (3), 97% volume
001a: 3c 3c 7b                 <<{       # Wait 60 ticks, play C4 (1), 97% volume
001d: 3c 41 7b                 <A{       # Wait 60 ticks, play F4 (4), 97% volume
0020: 3c 3c 7b                 <<{       # Wait 60 ticks, play C4 (1), 97% volume
0023: 3c 43 7b                 <C{       # Wait 60 ticks, play G4 (5), 97% volume
...
0bcf: 3c b0 7b 3c              <°{<      # Wait 60 ticks, all notes off
0bd3: 00 ff 2f 00              .ÿ/.      # End of track marker
\$\endgroup\$
1
9
\$\begingroup\$

Mathematica, 107 87 bytes

Thanks to Martin Ender for saving 20 bytes!

"t.au"~Export~Sound[SoundNote[⌊12Mod[#,10,1]/7⌋-1,.5]&/@#&@@RealDigits[Pi,10,1000]]

#&@@RealDigits[Pi,10,1000] gives the list of the first 1000 digits of π. SoundNote[⌊12Mod[#,10,1]/7⌋-1 produces the correct pitch number (where 0 is middle C by default) from a digit. Then SoundNote[...,.5]&/@ turns that pitch name into a sound object of duration 1/2 second, which Sound gathers into an actual audio snippet. Finally "t.au"~Export~ exports to a Unix Audio Format file, mostly because the extension is the shortest supported one, but also because we get to make the filename a slap in the face to π!

Previous submission:

"t.au"~Export~Sound[StringSplit["E5 C D E F G A B C5 D5"][[#+1]]~SoundNote~.5&/@#&@@RealDigits[Pi,10,1000]]
\$\endgroup\$
0
6
\$\begingroup\$

Scratch, 530 bytes

Inspired by BookOwl's answer.

Online Demonstration. Playback will begin immediately, press space to stop and reset. Click the cat to start again.

Edit: golfed down slightly. I found some golfing tips on the official wiki.

when gf clicked
set[c v]to[4e3
repeat(c
add[2e3]to[f v
end
repeat(250
set[b v]to(c
set[h v]to((d)mod(1e4
change[c v]by(-16
repeat(b
set[d v]to(((d)*(b))+((1e4)*(item(b)of[f v
set[g v]to(((2)*(b))-(1
replace item(b)of[f v]with((d)mod(g
set[d v]to(((d)-((d)mod(g)))/(g
change[b v]by(-1
end
change[h v]by(((d)-((d)mod(1e4)))/(1e4
repeat(4
add((h)mod(10))to[a v
set[h v]to(((h)-((h)mod(10)))/(10
end
repeat(4
say(item(last v)of[a v
play note((round((((item(last v)of[a v])-(1))mod(10))*(1.78)))+(60))for(0.5)beats
delete(last v)of[a v

Graphical:

Uses the Rabinowitz Wagon spigot to produce 4 digits at a time.

\$\endgroup\$
3
\$\begingroup\$

R, 450 bytes

N=261.63*(2^(1/12))^c(16,0,2,4,5,7,9,11,12,14);S=44100;s=unlist(sapply(el(strsplit(as(Rmpfr::Const("pi",1e5),"character"),""))[c(1,3:1001)],function(x)sin(0:(0.5*S-1)*pi*2*N[(x:1)[1]+1]/S)));c=32767*s/max(abs(s));a=file("p.wav","wb");v=writeChar;w=function(x,z)writeBin(as.integer(x),a,z,e="little");v("RIFF",a,4,NULL);w(36+S*10,4);v("WAVEfmt ",a,8,NULL);w(16,4);w(c(1,1),2);w(S*1:2,4);w(c(2,16),2);v("data",a,4,NULL);w(2*length(s),4);w(c,2);close(a)

Uses package Rmpfr to get the correct precision on pi digits. Outputs a .wav file.

Indented, with new lines and comments:

N=261.63*(2^(1/12))^c(16,0,2,4,5,7,9,11,12,14) # Frequency of each notes
S=44100 #Sampling rate
s=unlist(sapply(el(strsplit(
                   as(Rmpfr::Const("pi",1e5),"character"), #get pi correct digits as a character string
                   ""))[c(1,3:1001)], #Grabs first 1000 digits
                function(x)sin(0:(0.5*S-1)*pi*2*N[(x:1)[1]+1]/S))) #Wave function
c=32767*s/max(abs(s)) #Normalize to range [-32767;32767] as per wav 16-bit standard
a=file("p.wav","wb")
v=writeChar
w=function(x,z)writeBin(as.integer(x),a,z,e="little")
v("RIFF",a,4,NULL)     #ChunkID
w(36+S*10,4)           #Chunksize
v("WAVEfmt ",a,8,NULL) #Format, followed by SubChunk1ID
w(16,4)                #SubChunk1Size
w(c(1,1),2)            #AudioFormat & NumChannels
w(S*1:2,4)             #SampleRate & ByteRate
w(c(2,16),2)           #BlockAlign & BitsPerSample
v("data",a,4,NULL)     #SubChunk2ID
w(2*length(s),4)       #Subchunk2Size
w(c,2)                 #Actual data
close(a)
\$\endgroup\$
0
\$\begingroup\$

C (gcc) 572 bytes

p(float f){i;char b[10000];p=3.14;for(i= 0;i<5000;i++){b[i]=35*sin(f*(2*p*i)/10000);putchar(b[i]);}} f(){i;FILE *f;char p[1001];float n[10];n[0]= 261.63;for(i=1;i<=6;i++){if(i==3)n[i]=349.23;else n[i]=1.12231*n[i-1];}for(i=7;i<=9;i++)n[i]=2*n[i-7];f=popen("pi 1000","r");fgets(p,sizeof(p)-1,f);for(i=0;i<999;i++){switch(p[i]){case'1':p(n[0]);break;case'2':p(n[1]);break;case'3':p(n[2]);break;case'4':p(n[3]);break;case'5':p(n[4]);break;case'6':p(n[5]);break;case'7':p(n[6]);break;case'8':p(n[7]);break;case'9':p(n[8]);break;case'0':p(n[9]);break;default:p(n[0]);break;}}}

Ungolfed version:

void play(float freq)
{
    char buffer[10000];
    float pi=3.14;
    for(int i = 0; i<5000; i++)
    {
       buffer[i] = 35*sin(freq*(2*pi*i)/10000 );
       putchar(buffer[i]);
    }
}

void f()
{
    FILE *fp;
    char pi[1001];
    float note[10];
    note[0]= 261.63;

    for(int i=1;i<=6;i++)     
    {
       if(i==3)
         note[i]=349.23;
       else
         note[i]=1.12231*note[i-1]; 
    }      

    for(int i=7;i<=9;i++)
      note[i]=2*note[i-7];

   fp=popen("pi 1000","r" );
   fgets(pi, sizeof(pi)-1, fp);  

   for(int i=0;i<1001;i++)
   {
    switch(pi[i])
    {   
        case '1': play(note[0]);break;
        case '2': play(note[1]);break;
        case '3': play(note[2]);break;
        case '4': play(note[3]);break;
        case '5': play(note[4]);break;
        case '6': play(note[5]);break; 
        case '7': play(note[6]);break;
        case '8': play(note[7]);break;
        case '9': play(note[8]);break;
        case '0': play(note[9]);break;
        default : play(note[0]);break;
    }

  }     
}

Explanation:

  • play(float freq) routine takes in the frequency as a parameter of the note (hardcoded) you want to play and stores a sine wave in a buffer.
  • In the function f(), i stored the frequencies corresponding to notes ranging from C4 to E5 in a notes array.
  • Store the pi value followed by 1000 digits in a buffer.In order to do this, I installed the pi package on my machine, and used popen to read the output of pi 1000 and store it in a char buffer.
  • Using a for loop and switch I called the play() function to produce notes that correspond to every single digit in the pi buffer. ,

Usage: ./binary_name.o | aplay on modern Linux distributions, on older distributions you would redirect it to /dev/audio

\$\endgroup\$
1
  • \$\begingroup\$ Suggest replacing the entire switch(foo){...} with something like play(note[(foo-'1')%10]). Also, read tips for golfing in C \$\endgroup\$
    – ceilingcat
    Feb 8, 2017 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.