Mainkan suara Pi

15

Yup, Anda membaca judulnya dengan benar. mainkan suara pi.

Lebih khusus lagi, untuk setiap digit pi dalam 1000 pertama, petakan ke not musik dan output melodi yang dihasilkan ke file.

Pada dasarnya, setiap digit berubah menjadi catatan pada skala C Major (pada dasarnya skala normal). jadi 1 berbelok ke Middle C, 2 berbelok ke D4, 3 berbelok ke E4, 9 berbelok ke D5 dan seterusnya.

Aturan

  • Setiap nada harus tepat 0,5 detik.
  • Melodi harus berisi 1000 digit pi pertama, termasuk 3 awal.
  • 1 hingga 7 mewakili C Tengah ke B4, 8 adalah C5, 9 adalah D5 dan 0 adalah E5
  • Semua format file yang didukung dengan baik diizinkan, asalkan dibuat sebelum tantangan ini.
  • Mungkin tidak ada jeda di mana pun dalam file, termasuk awal dan akhir.
  • Instrumen yang dimainkan tidak masalah. Itu bisa berupa piano, gelombang sinus, apa saja, asalkan suara yang benar mudah didengar.
  • Ini tidak boleh mengambil input dan tidak menghasilkan output kecuali untuk file. Membaca dari file lain tidak diizinkan.
  • Celah standar dilarang.

Contoh kode mathematica:

(*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];

Contoh melodi menampilkan 100 digit pertama: http://vocaroo.com/i/s0cfEILwYb8M

Untuk kewarasan Anda, Daftar nada untuk setiap not dan apa not yang mewakili setiap digit:

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
sagiksp
sumber
5
9 belokan ke D5 Anda harus mengklarifikasi bahwa not-not lainnya ada di 4oktaf -th. Selain itu, di tabel Anda apakah angka 0datang terakhir ( E5)?
Luis Mendo
1
@LuisMendo Ya, benar. Saya akan membuatnya lebih jelas.
sagiksp
1
Bisakah kita menganggap 'format yang didukung dengan baik' berarti sesuatu yang dapat dibuka oleh vlc?
Pavel
@Pavel Cukup banyak
sagiksp
Bisakah saya mengeluarkan nama catatan (mis. 3.14 -> ECF) jika bahasa saya tidak mendukung suara atau menulis ke file suara?
FinW

Jawaban:

10

Mathematica, 107 87 byte

Terima kasih kepada Martin Ender karena telah menghemat 20 byte!

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

#&@@RealDigits[Pi,10,1000]memberikan daftar 1000 digit pertama π. SoundNote[⌊12Mod[#,10,1]/7⌋-1menghasilkan angka pitch yang benar (di mana 0 adalah C tengah secara default) dari angka. Kemudian SoundNote[...,.5]&/@ubah nama nada itu menjadi objek suara berdurasi 1/2 detik, yang Sounddikumpulkan menjadi potongan audio yang sebenarnya. Akhirnya "t.au"~Export~ekspor ke file Format Audio Unix, sebagian besar karena ekstensi adalah yang paling pendek didukung, tetapi juga karena kita bisa membuat nama file tamparan di wajah untuk π !

Pengajuan sebelumnya:

"t.au"~Export~Sound[StringSplit["E5 C D E F G A B C5 D5"][[#+1]]~SoundNote~.5&/@#&@@RealDigits[Pi,10,1000]]
Greg Martin
sumber
10

Python 2, 182 byte

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`akan menghasilkan 31415926...20198L. Trailing Ldigunakan untuk menghasilkan byte pesan saluran akhir, melalui pemetaan ~ord(i)%29.

Menghasilkan satu file Midi Tipe 1 trek, dinamai p.midke direktori kerja saat ini.

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
primo
sumber
1
Cukup terlambat, tetapi jika Anda bertanya-tanya rumus pi apa yang digunakan, ini merupakan variasi pada Formula 25 di mathworld.wolfram.com/PiFormulas.html .
Samuel Li
6

Gores , 530 byte

Terinspirasi oleh jawaban BookOwl .

Peragaan Online . Putar ulang akan segera dimulai, tekan spaceuntuk berhenti dan mengatur ulang. Klik kucing untuk memulai lagi.

Sunting: sedikit turun golf. Saya menemukan beberapa tips bermain golf di wiki resmi .

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

Grafis:

Menggunakan keran Rabinowitz Wagon untuk menghasilkan 4 digit sekaligus.

primo
sumber
3

R, 450 byte

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)

Menggunakan paket Rmpfruntuk mendapatkan presisi yang benar pada digit pi. Keluaran .wavfile.

Lekukan, dengan baris dan komentar baru:

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)
plannapus
sumber
0

C (gcc) 572 byte

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;}}}

Versi tidak disatukan:

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;
    }

  }     
}

Penjelasan:

  • play(float freq) rutin mengambil frekuensi sebagai parameter dari catatan (hardcoded) yang ingin Anda mainkan dan menyimpan gelombang sinus dalam buffer.
  • Dalam fungsinya f(), saya menyimpan frekuensi yang terkait dengan catatan mulai dari C4 hingga E5 dalam sebuah notesarray.
  • Menyimpan pinilai diikuti oleh 1000 digit dalam buffer. Untuk melakukan ini, saya menginstal pipaket pada mesin saya, dan digunakan popenuntuk membaca output pi 1000dan menyimpannya dalam charbuffer.
  • Menggunakan forloop dan switchsaya memanggil play()fungsi untuk menghasilkan catatan yang sesuai dengan setiap digit tunggal di pibuffer. ,

Penggunaan: ./binary_name.o | aplaypada distribusi Linux modern, pada distribusi lama Anda akan mengarahkannya kembali/dev/audio

Abel Tom
sumber
Sarankan mengganti keseluruhan switch(foo){...}dengan sesuatu seperti play(note[(foo-'1')%10]). Baca juga tips untuk bermain golf di C
ceilingcat