Phát âm thanh của Pi


15

Yup, bạn đọc tiêu đề đúng. chơi âm thanh của pi.

Cụ thể hơn, với mỗi chữ số pi trong 1000 đầu tiên, ánh xạ nó đến một nốt nhạc và xuất giai điệu kết quả thành một tệp.

Về cơ bản, mỗi chữ số chuyển sang một ghi chú trên thang đo C Major (về cơ bản là thang đo bình thường). vì vậy 1 chuyển sang Trung C, 2 chuyển sang D4, 3 chuyển sang E4, 9 chuyển sang D5 và cứ thế.

Quy tắc

  • Mỗi ghi chú nên dài chính xác 0,5 giây.
  • Giai điệu nên chứa 1000 chữ số đầu tiên của pi, bao gồm cả 3 bắt đầu.
  • 1 đến 7 đại diện cho Trung C đến B4, 8 là C5, 9 là D5 và 0 là E5
  • Tất cả các định dạng tệp được hỗ trợ tốt đều được cho phép, miễn là chúng được tạo trước thử thách này.
  • Có thể không có tạm dừng bất cứ nơi nào trong tệp, bao gồm cả bắt đầu và kết thúc.
  • Các nhạc cụ chơi không quan trọng. Nó có thể là một cây đàn piano, sóng hình sin, bất cứ thứ gì thực sự, miễn là âm thanh chính xác có thể dễ dàng phát ra.
  • Nó phải không có đầu vào và không tạo ra đầu ra ngoại trừ tệp. Đọc từ các tập tin khác là không được phép.
  • Sơ hở tiêu chuẩn bị cấm.

Ví dụ mã toán học:

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

Ví dụ giai điệu hiển thị 100 chữ số đầu tiên: http://vocaroo.com/i/s0cfEILwYb8M

Đối với sự tỉnh táo của bạn, Một bảng các nốt cho mỗi ghi chú và mỗi chữ số thể hiện ghi chú nào:

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

5
9 biến thành D5 Bạn nên làm rõ rằng các ghi chú khác nằm trong 4quãng tám thứ tám. Ngoài ra, trong bảng của bạn, chữ số 0có đứng cuối ( E5) không?
Luis Mendo

1
@LuisMendo Vâng, đúng vậy. Tôi sẽ làm cho những điều này quá rõ ràng.
sagiksp

1
Chúng tôi có thể giả sử 'định dạng được hỗ trợ tốt' có nghĩa là bất cứ điều gì có thể mở được bởi vlc không?
Pavel

@Pavel Khá nhiều
sagiksp

Tôi có thể xuất tên ghi chú (ví dụ: 3.14 -> ECF) nếu ngôn ngữ của tôi không hỗ trợ âm thanh hoặc ghi vào tệp âm thanh?
FinW

Câu trả lời:


10

Toán học, 107 87 byte

Cảm ơn Martin Ender đã tiết kiệm 20 byte!

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

#&@@RealDigits[Pi,10,1000]đưa ra danh sách 1000 chữ số đầu tiên của π. SoundNote[⌊12Mod[#,10,1]/7⌋-1tạo số sân chính xác (trong đó 0 là giữa C theo mặc định) từ một chữ số. Sau đó SoundNote[...,.5]&/@biến tên cao độ đó thành một đối tượng âm thanh có thời lượng 1/2 giây, Soundtập hợp thành một đoạn âm thanh thực tế. Cuối cùng "t.au"~Export~xuất thành tệp Unix Audio Format, phần lớn là do phần mở rộng là phần được hỗ trợ ngắn nhất, nhưng cũng vì chúng ta có thể biến tên tệp thành một cái tát vào mặt thành π !

Trình trước:

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

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`sẽ sản xuất 31415926...20198L. Các trailing Lđược sử dụng để tạo byte thông báo kênh cuối cùng, thông qua ánh xạ ~ord(i)%29.

Xuất ra một tệp Midi loại 1 theo dõi duy nhất, được đặt tên p.midcho thư mục làm việc hiện tại.

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

1
Khá muộn, nhưng nếu bạn đang tự hỏi công thức pi nào được sử dụng, thì đó là một biến thể của Công thức 25 tại mathworld.wolfram.com/PiForm Formula.html .
Samuel Li

6

Cào , 530 byte

Lấy cảm hứng từ câu trả lời của BookOwl .

Trình diễn trực tuyến . Phát lại sẽ bắt đầu ngay lập tức, nhấn spaceđể dừng và thiết lập lại. Nhấp vào con mèo để bắt đầu lại.

Chỉnh sửa: đánh golf xuống một chút. Tôi tìm thấy một số lời khuyên chơi golf trên wiki chính thức .

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

Đồ họa:

Sử dụng spigot Rabinowitz Wagon để tạo ra 4 chữ số cùng một lúc.


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)

Sử dụng gói Rmpfrđể có được độ chính xác chính xác trên chữ số pi. Xuất ra một .wavtập tin.

Được thụt lề, với các dòng và nhận xét mới:

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)

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

Phiên bản bị đánh cắp:

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

  }     
}

Giải trình:

  • play(float freq) thường trình lấy tần số làm tham số của ghi chú (mã hóa cứng) mà bạn muốn phát và lưu trữ một sóng hình sin trong bộ đệm.
  • Trong hàm f(), tôi lưu trữ các tần số tương ứng với các ghi chú nằm trong khoảng từ C4 đến E5 trong một notesmảng.
  • Lưu trữ pigiá trị theo sau 1000 chữ số trong bộ đệm. Để thực hiện việc này, tôi đã cài đặt pigói trên máy của mình và sử dụng popenđể đọc đầu ra pi 1000và lưu trữ trong charbộ đệm.
  • Sử dụng một forvòng lặp và switchtôi đã gọi play()hàm để tạo các ghi chú tương ứng với mỗi chữ số trong pibộ đệm. ,

Cách sử dụng: ./binary_name.o | aplaytrên các bản phân phối Linux hiện đại, trên các bản phân phối cũ hơn, bạn sẽ chuyển hướng nó đến/dev/audio


Đề nghị thay thế toàn bộ switch(foo){...}bằng một cái gì đó như play(note[(foo-'1')%10]). Ngoài ra, hãy đọc các mẹo để chơi gôn trong C
trần nhà
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.