Reproduce el sonido de Pi

15

Sí, leíste bien el título. reproduce el sonido de pi.

Más específicamente, por cada dígito de pi en los primeros 1000, asigne una nota musical y envíe la melodía resultante a un archivo.

Básicamente, cada dígito se convierte en una nota en la escala C mayor (básicamente la escala normal). entonces 1 gira al Medio C, 2 vueltas a D4, 3 vueltas a E4, 9 vueltas a D5 y así sucesivamente.

Reglas

  • Cada nota debe durar exactamente 0,5 segundos.
  • La melodía debe contener los primeros 1000 dígitos de pi, incluidos los 3 iniciales.
  • 1 a 7 representan C central a B4, 8 es C5, 9 es D5 y 0 es E5
  • Se permiten todos los formatos de archivo compatibles, siempre que se hayan creado antes de este desafío.
  • Es posible que no haya pausas en ningún lugar del archivo, incluidos el inicio y el final.
  • El instrumento tocado no importa. Podría ser un piano, una onda sinusoidal, cualquier cosa, siempre y cuando el sonido correcto sea ​​fácilmente escuchable.
  • No debe recibir ninguna entrada y no producir ninguna salida, excepto el archivo. La lectura de otros archivos no está permitida.
  • Las lagunas estándar están prohibidas.

Ejemplo de código matemático:

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

Ejemplo de melodía que muestra los primeros 100 dígitos: http://vocaroo.com/i/s0cfEILwYb8M

Para su cordura, una tabla de tonos para cada nota y qué nota representa cada dígito:

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
fuente
55
9 vueltas a D5 Debe aclarar que las otras notas están en la 4octava octava. Además, en su tabla, ¿el dígito es el 0último ( E5)?
Luis Mendo
1
@LuisMendo Sí, lo hace. Haré esto también más claro.
sagiksp
1
¿Podemos asumir que 'formatos bien soportados' significan cualquier cosa que pueda abrir vlc?
Pavel
@Pavel Bastante
sagiksp
¿Puedo mostrar los nombres de las notas (por ejemplo, 3.14 -> ECF) si mi idioma no admite sonido o escritura en archivos de sonido?
FinW

Respuestas:

10

Mathematica, 107 87 bytes

¡Gracias a Martin Ender por guardar 20 bytes!

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

#&@@RealDigits[Pi,10,1000]da la lista de los primeros 1000 dígitos de π. SoundNote[⌊12Mod[#,10,1]/7⌋-1produce el número de tono correcto (donde 0 es C central por defecto) a partir de un dígito. Luego SoundNote[...,.5]&/@convierte ese nombre de tono en un objeto sonoro de duración 1/2 segundo, que se Soundreúne en un fragmento de audio real. Finalmente se "t.au"~Export~exporta a un archivo de formato de audio Unix, principalmente porque la extensión es la más corta admitida, ¡pero también porque podemos hacer que el nombre de archivo sea una bofetada a π !

Presentación previa:

"t.au"~Export~Sound[StringSplit["E5 C D E F G A B C5 D5"][[#+1]]~SoundNote~.5&/@#&@@RealDigits[Pi,10,1000]]
Greg Martin
fuente
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` Producirá 31415926...20198L . El seguimiento Lse utiliza para producir el byte del mensaje del canal final, a través de la asignación ~ord(i)%29.

Emite un archivo Midi Tipo 1 de una sola pista, nombrado p.midal directorio de trabajo actual.

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
fuente
1
Muy tarde, pero si se pregunta qué fórmula pi se usa, es una variación de la Fórmula 25 en mathworld.wolfram.com/PiFormulas.html .
Samuel Li
6

Rasguño , 530 bytes

Inspirado por la respuesta de BookOwl .

Demostración en línea . La reproducción comenzará de inmediato, presionespace para detener y restablecer. Haz clic en el gato para comenzar de nuevo.

Editar: golfed ligeramente hacia abajo. Encontré algunos consejos de golf en la wiki oficial .

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

Gráfico:

Utiliza la espita Rabinowitz Wagon para producir 4 dígitos a la vez.

primo
fuente
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)

Utiliza el paquete Rmpfrpara obtener la precisión correcta en los dígitos pi. Emite un .wavarchivo.

Sangrado, con nuevas líneas y comentarios:

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

Versión sin golf:

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

  }     
}

Explicación:

  • play(float freq) La rutina toma la frecuencia como un parámetro de la nota (codificada) que desea reproducir y almacena una onda sinusoidal en un búfer.
  • En la función f(), almacené las frecuencias correspondientes a las notas que van desde C4 a E5 en unnotes matriz.
  • Almacene el pivalor seguido de 1000 dígitos en un búfer. Para hacer esto, instalé el pipaquete en mi máquina y solía popenleer el resultado pi 1000y almacenarlo en un charbúfer.
  • Usando un forbucle y switchllamé a la play()función para producir notas que corresponden a cada dígito en el pibúfer. ,

Uso: ./binary_name.o | aplayen las distribuciones modernas de Linux, en las distribuciones más antiguas lo redirigiría a/dev/audio

Abel Tom
fuente
Sugerir reemplazar todo switch(foo){...}con algo como play(note[(foo-'1')%10]). Además, lea los consejos para jugar golf en C
ceilingcat