O som das palavras

11

As pessoas escreveram muitas coisas, permitindo que uma coisa fosse visualizada como outra. Agora, proponho poder traduzir letras para música! É seu trabalho escrever um programa que pega um arquivo de texto e gera um arquivo de som com cada letra convertida em uma nota específica C3-C8.

Disclaimer - Na verdade, não espero que a música pareça boa, mas espero ser surpreendida.

Especificações

  • Você pega o nome de um arquivo como uma string e o BPM (batimentos por minuto) como um int
  • Você faz maiúsculas Apara ser a notaC3
  • E suba um meio passo para cada personagem depois nesta ordem: ABCDEFGHIJKLMNOPQRSTUVWXYZ ()-,;.'"abcdefghijklmnopqrstuvwxyz
  • Sim, nem todos os personagens serão usados, já que isso abrange muitas oitavas.
  • Você traduz todos os caracteres no arquivo dessa maneira
  • Coloque as notas juntas no BPM fornecido como semínimas
  • Salvar como um arquivo de som (acho que o midi será o mais fácil, mas tudo está bem) ou reproduzi-lo
  • Qualquer formato de entrada são
  • Sem brechas padrão
  • Isso é código-golfe, então o código mais curto em bytes vence!

Bónus

  • Permitir transposição da saída - 50 bytes
  • Permita que várias trilhas sejam sobrepostas, pegando vários arquivos - 75 bytes
  • Junte letras consecutivas em uma nota mais longa - 50 bytes

Edit: Uau, temos pontuações negativas. Anunciarei o vencedor no sábado.

Maltysen
fonte
Quando você estará decidindo o vencedor?
amigos estão
Podemos assumir que a entrada não conterá caracteres não listados? Ou, o que devemos fazer quando encontramos caracteres não listados?
Apsillers
@apsillers Na pressão ! resposta, ele disse que permitiria um comportamento indefinido.
LegionMammal978
Enviei uma amostra; você era bastante correto, ele realmente não soa qualquer bom ...
Sanchises

Respostas:

6

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

Entrada de amostra

Saída de amostra

Gera ondas senoidais puras, muito descoladas (dente de serra também é possível, com uma pontuação ainda melhor, mas isso soa um pouco ... descolado demais ). Funciona como uma função, portanto, espera uma matriz de caracteres ( ['abc';'def']) com uma linha por 'faixa'. Eu acho que isso é coberto por 'qualquer formato de entrada sã' , mas se o consenso geral é que eu preciso ler um arquivo, acho que posso alterá-lo. A entrada ié faixas de texto (de igual comprimento), bbatidas por minuto e ttransposição (fornecimento 0 para não transposto). Ele combina dois senos em um, compensando a entrada de seno, então recebi os três bônus, obtendo uma pontuação 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

Versão usando o arquivo de entrada: 211-175 = 36

O argumento de entrada iagora representa o nome do arquivo, outros parâmetros inalterados. Talvez não funcione em versões mais recentes porque estou recebendo um aviso que textreadpoderá ser preterido em breve. EDIT: textread aparentemente automaticamente se divide em espaços em branco, então eu consertei isso. Além disso, acho que acidentalmente entrei em contato com alguns alienígenas com os sons estranhos emitidos durante o teste.

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

Qual versão você prefere? :)

Sanchises
fonte
Bem, a especificação diz explicitamente para pegar a entrada de um arquivo ... #
7894
@ LegionMammal978 Se você insistir: os .matarquivos têm um formato de entrada sensato. Crie um arquivo .mat com uma variável 'i' que tenha seu texto. Em seguida, adicione load(i);no início da linha 2 da versão superior. Pontuação: -16 + 8 = -8. Eu vou fazer isso quando o seu comentário recebe mais upvotes que a minha, ou quando o OP tem uma opinião :)
Sanchises
4

Snap ! - 401 - 75 = 326

Experimente online aqui.

Estou usando esse método de contagem de bytes para o programa.

insira a descrição da imagem aqui

Eu adicionei a reprodução de vários sons ao mesmo tempo.

A estrutura básica é igual à original (veja abaixo), mas com a adição de launch{}. launch{}inicia um novo thread com o código interno, permitindo a simultaneidade.

O código como texto é:

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.

insira a descrição da imagem aqui

Lucky Snap! tem MIDI tocando embutido.;)

Infelizmente, ele não tem uma indexOffunção, então eu tenho que fazer uma chamada JavaScript externa, o que é bastante caro.

O repeat () (#)bloco vem da biblioteca de iteração.

O código pode ser escrito como texto como este, e é assim que obtenho 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
fonte
O SNAP tem uma coleção / vitrine que você pode adicionar como o Scratch? Vincular diretamente a uma versão executável seria útil para o IMO.
Geobits
Sim. Eu adicionei um link para o meu projeto. Boa ideia. :)
Scimonster 07/04
Ignora -1de indexOf? Agora parece que se não na cadeia, ele faz midi número 47.
Maltysen
@ Maltysen A pergunta nunca diz o que fazer com a entrada fora da faixa adequada.
Scimonster
Verdadeiro. Eu pretendia que isso fosse ignorado, mas, como acho que é minha culpa por não ser suficientemente específico, permitirei.
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}]]/@#]&

Leva a lista de arquivos de entrada, BPM e o número de meias etapas para transpor como entrada e reproduz o som (de um piano, qualquer outro instrumento levaria mais bytes.) Não parece tão ruim!

LegionMammal978
fonte
1

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

Primeiro, aqui está um trecho executável que usa <input>campos em vez de leituras de arquivo:

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

E agora, a 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)})}

Os três argumentos são uma matriz de strings do caminho do arquivo para tocar simultaneamente, notas por minuto e número de meias etapas para transpor todas as entradas.

Com espaço em branco e comentários:

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
fonte