El sonido de las palabras

11

La gente ha escrito muchas cosas permitiendo que una cosa se visualice como otra. ¡Ahora propongo poder traducir letras a música! Es su trabajo escribir un programa que tome un archivo de texto y genere un archivo de sonido con cada letra convertida en una nota específica C3-C8.

Descargo de responsabilidad: en realidad no espero que la música suene bien, pero espero sorprenderme.

Especificaciones

  • Toma el nombre de un archivo como una cadena y el BPM (latidos por minuto) como int
  • Haces mayúsculas Apara ser la notaC3
  • Y sube medio paso para cada personaje después en este orden: ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'"abcdefghijklmnopqrstuvwxyz
  • Sí, no se usarán todos los caracteres, ya que eso abarca demasiadas octavas.
  • Traduces todos los caracteres del archivo de esta manera
  • Ponga las notas juntas en el BPM dado como notas negras
  • Guarde como un archivo de sonido (supongo que midi será el más fácil, pero todo está bien) o reprodúzcalo
  • Cualquier formato de entrada correcto está bien
  • No hay lagunas estándar
  • Este es el código de golf, por lo que gana el código más corto en bytes .

Bonos

  • Permitir transposición de salida - 50 bytes
  • Permitir que varias pistas se superpongan entre sí tomando múltiples archivos: 75 bytes
  • Une letras consecutivas en una nota más larga: 50 bytes

Editar: Wow, tenemos puntajes negativos. Voy a anunciar el ganador el sábado.

Maltysen
fuente
¿Cuándo decidirás el ganador?
LegionMammal978
¿Podemos suponer que la entrada no contendrá caracteres no listados? O, ¿qué debemos hacer cuando nos encontramos con personajes no listados?
apsillers
@apsillers en el instante ! respuesta, dijo que permitiría un comportamiento indefinido.
LegionMammal978
Subí una muestra; estabas bastante correcto, realmente no suena bien ...
Sanchises

Respuestas:

6

MATLAB, 159-50-50-75 = -16

Entrada de muestra

Salida de muestra

Genera ondas de sonido sinusoidales puras, muy funky (el diente de sierra también es posible, con una puntuación aún mejor, pero eso suena un poco ... demasiado funky). Funciona como una función, por lo que espera una matriz de caracteres ( ['abc';'def']) con una fila por 'pista'. Creo que está cubierto bajo 'cualquier formato de entrada sensato' , pero si el consenso general es que necesito leer un archivo, supongo que puedo cambiarlo. La entrada ies pistas de texto (de igual longitud), blatidos por minuto y ttransposición (suministro 0 para no transpuesta). Combina dos senos en uno al compensar la entrada sinusoidal, por lo que obtuve los tres bonos, lo que me dio una puntuación negativa.

function v(i,b,t)
s=0;for r=1:size(i)
o=[];for k=i(r,:)
o=cat(2,o,sin(55*pi*2^((k-28+t)/12)*(numel(o)/2^13+(0:1/2^13:60/b))));end
s=s+o;end
sound(s/max(s))
end

Versión usando el archivo de entrada: 211-175 = 36

El argumento de entrada iahora representa el nombre del archivo, otros parámetros sin cambios. Es posible que no funcione en versiones más recientes porque recibo una advertencia que textreadpronto puede quedar en desuso. EDITAR: textread aparentemente se divide automáticamente en espacios en blanco, así que lo arreglé. Además, creo que pude haber contactado accidentalmente a algunos alienígenas con los sonidos extraños que se hicieron durante las pruebas.

function v(i,b,t)
i=textread(i,'%s','whitespace','','delimiter','\n');s=0;for r=1:size(i)
o=[];for k=i{r,:}
o=cat(2,o,sin(55*pi*2^((k-28+t)/12)*(numel(o)/2^13+(0:1/2^13:60/b))));end
s=s+o;end
sound(s/max(s))
end

¿Qué versión prefieres? :)

Sanchises
fuente
Bueno, la especificación dice explícitamente tomar la entrada de un archivo ...
LegionMammal978
@ LegionMammal978 Si insiste: los .matarchivos tienen un formato de entrada sensato. Cree un archivo .mat con una variable 'i' que tenga su texto. Luego, agregue load(i);al comienzo de la línea 2 de la versión superior. Puntuación: -16 + 8 = -8. Haré esto cuando tu comentario reciba más votos positivos que el mío, o cuando el OP tenga una opinión :)
Sanchises
4

Snap ! - 401 - 75 = 326

Pruébelo en línea aquí.

Estoy usando este método de contar bytes para el programa.

ingrese la descripción de la imagen aquí

Agregué reproducir múltiples sonidos a la vez.

La estructura básica es la misma que la original (ver más abajo), pero con la adición de launch{}. launch{}comienza un nuevo hilo con el código dentro, permitiendo la concurrencia.

El código como texto es:

set[c v]to[ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'"abcdefghijklmnopqrstuvwxyz
set[l v]to(list>
ask[BPM]and wait
set tempo to(answer)bpm
repeat until<(answer)=[
ask[notes]and wait
add(answer)to(l
end
delete(last v)of(l
for each(i)of(l
launch{
repeat(length of(i))(#
play note(i(c)(letter(#)of(i)))for(0.25)beats

(i(h)(n))
report(call(JavaScript function ([h][n]) {[return h.indexOf(n)+48]})with inputs(h)(n

Código original, 308.

ingrese la descripción de la imagen aquí

Lucky Snap! tiene reproducción MIDI incorporada.;)

Desafortunadamente, no tiene una indexOffunción, así que tengo que hacer una llamada externa de JavaScript, lo cual es bastante costoso.

El repeat () (#)bloque proviene de la biblioteca de iteraciones.

El código se puede escribir como un texto como este, que es cómo obtengo 308 bytes:

set[c v]to[ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'"abcdefghijklmnopqrstuvwxyz
ask[BPM]and wait
set tempo to(answer)bpm
ask[notes]and wait
repeat(length of(answer))(#)
play note(i(c)(letter(#)of(answer)))for(0.25)beats

(i(h)(n))
report(call(JavaScript function ([h][n]) {[return h.indexOf(n)+48]})with inputs(h)(n
Scimonster
fuente
¿SNAP tiene una colección / vitrina a la que puede agregar estos como Scratch? Vincular directamente a una versión ejecutable sería útil IMO.
Geobits
Si. Agregué un enlace a mi proyecto. Buena idea. :)
Scimonster
¿Se ignora -1de indexOf? En este momento parece que si no está en la cadena, hace midi número 47.
Maltysen
@Maltysen La pregunta nunca dice qué hacer con la entrada fuera del rango adecuado.
Scimonster
Cierto. Quise ignorarlo, pero como supongo que es mi culpa por no ser lo suficientemente específico, lo permitiré.
Maltysen
4

Mathematica, 219-50-75-50 = 44

c=CharacterRange;d=Import;EmitSound[Function[b,Sound[Split@Characters@d@b/.a:{__String}:>SoundNote[StringPosition[c["A","Z"]<>" ()-,;.'\""<>c["a","z"],a[[1]]][[1,1]]+#3-12,60Length@a/#2],{0,60StringLength@d@b/#2}]]/@#]&

Toma la lista de archivos de entrada, BPM y la cantidad de medios pasos para transponer como entrada y reproduce el sonido (desde un piano, cualquier otro instrumento tomaría más bytes). ¡No suena tan mal!

LegionMammal978
fuente
1

JavaScript (ES6) 377-50-50-75 = 202

Primero, aquí hay un fragmento ejecutable que usa <input>campos en lugar de lecturas de archivos:

<b>BMP:</b> <input id="bpm" size=3 placeholder="BMP" value="120"> <b>Transpose:</b> <input size=3 id="transpose" placeholder="Transpose" value="0"><br/><br/><div id="tracks" style="float:left;padding-right:5px;"><input placeholder="Track" class="track"></div><button id="add">Add Additional Track</button><div style="clear:both; padding-top:5px;"></div><button id="play"><b>Play</b></button><script>f=function(s,b,z){C=new (window.AudioContext||window.webkitAudioContext);b=6e4/b;s.map(function(p){var o=C.createOscillator(t=setTimeout);o.connect(C.destination);o.start();p.split("").map(function(c,i){t(function(){o.frequency.value=440*Math.pow(2, ("ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'\"abcdefghijklmnopqrstuvwxyz".indexOf(c)-21+z)/12)},b*i)});t(function(){o.stop()},p.length*b)})};document.getElementById("play").onclick=function(){f([].map.call(document.getElementsByClassName("track"),function(e){return e.value;}),+document.getElementById("bpm").value,+document.getElementById("transpose").value);};document.getElementById("add").onclick=function(){var i=document.createElement("input");i.placeholder="Track";i.className="track";document.getElementById("tracks").appendChild(document.createElement("br"));document.getElementById("tracks").appendChild(i);};</script>

Y ahora, la entrada real:

f=(n,b,z)=>{C=new AudioContext;b=6e4/b;s=n.map(m=>(x=new XMLHttpRequest,x.open("GET",m,0),x.send(),x.responseText));s.map(p=>{var o=C.createOscillator(t=setTimeout);o.connect(C.destination);o.start();[...p].map((c,i)=>t(_=>o.frequency.value=440*Math.pow(2,("ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'\"abcdefghijklmnopqrstuvwxyz".indexOf(c)-21+z)/12),b*i)),t(_=>o.stop(),p.length*b)})}

Los tres argumentos son una serie de cadenas de ruta de archivo para reproducir simultáneamente, notas por minuto y número de medios pasos para transponer todas las entradas.

Con espacios en blanco y comentarios:

f=(n,b,z)=>{
    C=new AudioContext;
    b=6e4/b;

    // fill s with the contents of each file
    s = n.map(m=>(x=new XMLHttpRequest,x.open("GET",m,0),x.send(),x.responseText));

    // play each track
    s.map(p=>{
        var o=C.createOscillator(t=setTimeout);
        o.connect(C.destination);
        o.start();

        // queue up each note with setTimeout
        [...p].map((c,i)=>
            t(_=>
                o.frequency.value=440*
                    Math.pow(2,
                            ("ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'\"abcdefghijklmnopqrstuvwxyz".indexOf(c)-21+z)/12
                    ),
             b*i)
        );
        // queue up termination of those track
        t(_=>o.stop(),p.length*b)})
}

f(["file:///home/users/apsillers/notes.txt",
   "file:///home/users/apsillers/notes2.txt"],
  240, 5)
apsillers
fuente