Spielen Sie den Sound von Pi

15

Ja, Sie haben den Titel richtig gelesen. spiele den Klang von pi.

Genauer gesagt, ordnen Sie jede Ziffer von pi in den ersten 1000 einer Musiknote zu und geben Sie die resultierende Melodie in eine Datei aus.

Grundsätzlich wird jede Ziffer zu einer Note auf der C-Dur-Tonleiter (im Grunde die normale Tonleiter). 1 dreht sich zu Mitte C, 2 dreht sich zu D4, 3 dreht sich zu E4, 9 dreht sich zu D5 und so weiter.

Regeln

  • Jede Note sollte genau 0,5 Sekunden lang sein.
  • Die Melodie sollte die ersten 1000 Stellen von pi enthalten, einschließlich der ersten 3.
  • 1 bis 7 stehen für Mitte C bis B4, 8 für C5, 9 für D5 und 0 für E5
  • Alle gut unterstützten Dateiformate sind zulässig, sofern sie vor dieser Herausforderung erstellt wurden.
  • Die Datei enthält möglicherweise keine Pausen, auch nicht Start- und Endpunkt.
  • Das gespielte Instrument spielt keine Rolle. Es könnte ein Klavier sein, eine Sinuswelle, alles, was wirklich ist, solange der richtige Klang leicht zu hören ist.
  • Es darf keine Eingabe und keine Ausgabe außer für die Datei erzeugen. Das Lesen aus anderen Dateien ist nicht zulässig.
  • Standardlücken sind verboten.

Beispiel für einen 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];

Beispielmelodie mit den ersten 100 Stellen: http://vocaroo.com/i/s0cfEILwYb8M

Eine Tabelle mit Tonhöhen für jede Note und für welche Note steht jede Ziffer:

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
quelle
5
9 Drehungen zu D5 Sie sollten klarstellen, dass die anderen Noten in der 4-ten Oktave sind. Kommt in Ihrer Tabelle auch die Ziffer 0zuletzt ( E5)?
Luis Mendo
1
@ LuisMendo Ja, das tut es. Ich werde das auch klarer machen.
Sagiksp
1
Können wir annehmen, dass 'gut unterstützte Formate' alles bedeuten, was von VLC geöffnet werden kann?
Pavel
@Pavel Ziemlich viel
sagiksp
Kann ich die Notennamen (zB 3.14 -> ECF) ausgeben, wenn meine Sprache keinen Ton unterstützt oder in Audiodateien nicht schreibt?
FinW

Antworten:

10

Mathematica, 107 87 Bytes

Vielen Dank an Martin Ender für die Einsparung von 20 Bytes!

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

#&@@RealDigits[Pi,10,1000]gibt die Liste der ersten 1000 Stellen von π an. SoundNote[⌊12Mod[#,10,1]/7⌋-1Erzeugt aus einer Ziffer die richtige Tonhöhenzahl (wobei 0 standardmäßig für Mittel-C steht). Dann SoundNote[...,.5]&/@dreht sich , dass die Tonhöhe in ein Klangobjekt der Dauer 1/2 Sekunde, die SoundRaffungen in ein tatsächliches Audio Schnipsel. Schließlich wird "t.au"~Export~in eine Datei im Unix-Audioformat exportiert, hauptsächlich, weil die Erweiterung die kürzeste unterstützte ist, aber auch, weil der Dateiname ein Schlag ins Gesicht nach π ist !

Vorherige Einreichung:

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

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`wird produzieren 31415926...20198L. Das Trailing Lwird verwendet, um das letzte Kanalnachrichtenbyte über das Mapping zu erzeugen ~ord(i)%29.

Gibt eine einzelne Spur-Typ-1-Midi-Datei aus, die p.midim aktuellen Arbeitsverzeichnis gespeichert ist .

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
quelle
1
Ziemlich spät, aber wenn Sie sich fragen, welche Pi-Formel verwendet wird, handelt es sich um eine Variante der Formel 25 unter mathworld.wolfram.com/PiFormulas.html .
Samuel Li
6

Scratch , 530 Bytes

Inspiriert von der Antwort von BookOwl .

Online-Demonstration . Die Wiedergabe beginnt sofort. Drücken Sie space, um die Wiedergabe zu stoppen und zurückzusetzen. Klicken Sie auf die Katze, um erneut zu starten.

Bearbeiten: leicht nach unten Golf gespielt. Ich habe einige Golftipps im offiziellen Wiki gefunden .

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

Grafisch:

Verwendet den Rabinowitz Wagon-Zapfen, um jeweils 4 Ziffern zu erzeugen.

primo
quelle
3

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)

Verwendet package Rmpfr, um die richtige Genauigkeit für Pi-Ziffern zu erhalten. Gibt eine .wavDatei aus.

Mit neuen Zeilen und Kommentaren eingerückt:

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
quelle
0

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

  }     
}

Erläuterung:

  • play(float freq) Die Routine nimmt die Frequenz als Parameter der Note (fest codiert), die Sie spielen möchten, und speichert eine Sinuswelle in einem Puffer.
  • In der Funktion f()speicherte ich die Frequenzen, die Noten von C4 bis E5 entsprechen, in einem notesArray.
  • Speichern Sie den piWert, gefolgt von 1000 Ziffern, in einem Puffer. Dazu habe ich das piPaket auf meinem Computer installiert und verwendet popen, um die Ausgabe von zu lesen pi 1000und in einem charPuffer zu speichern .
  • Mit einer forSchleife habe switchich die play()Funktion aufgerufen , um Noten zu erzeugen, die jeder einzelnen Ziffer im piPuffer entsprechen. ,

Verwendung: ./binary_name.o | aplayAuf modernen Linux-Distributionen würden Sie auf ältere Distributionen umleiten/dev/audio

Abel Tom
quelle
Schlagen Sie vor, das Ganze durch so switch(foo){...}etwas wie zu ersetzen play(note[(foo-'1')%10]). Lesen Sie auch Tipps zum Golfen in C
ceilingcat