Transforme seu teclado em um teclado

10

Tarefa

Você deve escrever um programa que, quando um botão é pressionado, emite um som diferente para cada tecla.

As chaves que você usará são:

1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm

As notas começam às Ce cada tecla acima adiciona um semitom.

Vamos torná-lo um pouco mais fácil para você. Você pode escolher entre 2 tarefas semelhantes,

1) Emita uma nota diferente quando uma tecla é pressionada e continua até que outra tecla seja pressionada. Este programa é executado indefinidamente

2) Pegue uma string como entrada que contenha apenas os caracteres acima que produzirão cada nota por exatamente 1 segundo (variação de 0,05 segundo permitida)

Entrada

  1. Uma tecla sendo pressionada
  2. Uma única sequência contendo apenas os símbolos acima

Resultado

  1. Uma única nota musical que soa até que outra tecla seja pressionada
  2. Uma série de notas, cada uma com um segundo de duração

Notas

Letter | Note
-------+-------
   1   |  C
   !   |  C#
   2   |  D
   "   |  D#
   3   |  E
   4   |  F
   $   |  F#
   5   |  G
   %   |  G#
   6   |  A
   ^   |  A#
   7   |  B
   8   |  C
   *   |  C#
   9   |  D
   (   |  D#
   0   |  E
   q   |  F
   Q   |  F#
   w   |  G
   W   |  G#
   e   |  A
   E   |  A#
   r   |  B
   t   |  C    <-- middle C
   T   |  C#
   y   |  D
   Y   |  D#
   u   |  E
   i   |  F
   I   |  F#
   o   |  G
   O   |  G#
   p   |  A
   P   |  A#
   a   |  B
   s   |  C
   S   |  C#
   d   |  D
   D   |  D#
   f   |  E
   g   |  F
   G   |  F#
   h   |  G
   H   |  G#
   j   |  A
   J   |  A#
   k   |  B
   l   |  C
   L   |  C#
   z   |  D
   Z   |  D#
   x   |  E
   c   |  F
   C   |  F#
   v   |  G
   V   |  G#
   b   |  A
   B   |  A#
   n   |  B
   m   |  C

Regras

  • Você pode escolher entre as tarefas, mas diga qual delas na sua resposta
  • Você recebe uma variação de ± 0,05 segundo na tarefa 2
  • Cada símbolo aumenta o tom em 1 semitom.
  • As notas individuais são mostradas acima
  • Este é um então o código mais curto ganha

Foi originalmente tirada daqui com o consentimento de caird coinheringaahing

Jonathan Allan
fonte
Para abrir isso para idiomas que não possuem bibliotecas de áudio, recomendo um terceiro formato de saída: um arquivo WAV contendo a opção 2, gravada em stdout. Isso permitiria entradas em qualquer idioma que possa imprimir dados binários.
Ray

Respostas:

6

Python 3, 154 140 bytes

from winsound import*
for i in input():Beep(int(65.406*2**('1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.find(i)/12)),999)

Eu escolhi o segundo tipo de tarefa.

O loop passa por cada caractere e procura o índice desse elemento na string. Este índice é o número de semitons acima do Baixo C ('1'). O cálculo da frequência desejada é feito por esta fórmula .

PS Esta biblioteca funciona apenas no Windows.

-13 bytes graças a ovs.

-1 byte graças a Jonathan Allan.

Кирилл Малышев
fonte
11
Você provavelmente deve mencionar que isso só funciona no Windows.
totallyhuman
11
Golfeou para 141 bytes:from winsound import* for i in input():Beep(int(65.406*2**('1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.find(i)/12)),1000)
ovs 04/04/19
Mas a pergunta feita por um programa ....
Neil A.
A 0.05tolerância deve permitir que você use 999.
Jonathan Allan
3

JavaScript (ES6), 247 ou 230 bytes

Decidiu experimentar as duas opções.

Economizei alguns bytes graças a @darrylyeo por sugerir a withdeclaração.
Agradecemos a @ Кирилл Малышев por apontar um problema com .search().

Opção 1 - Entrada do teclado, 252 246 247 bytes

_=>{c=new AudioContext;q=1;with(c.createOscillator())connect(c.destination),I.oninput=_=>(~(i='1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.indexOf(I.value,I.value=""))&&(frequency.value=65.4*2**(i/12),q&&start(q=0)))}
<input id=I

Confia no elemento de entrada que recebe a letra digitada real, em vez de códigos de caracteres. O foco deve estar na caixa de entrada.

Opção 2 - Entrada de sequência , 234 229 230 bytes

s=>{c=new AudioContext;with(c.createOscillator())connect(c.destination),[...s].map((c,i)=>frequency.setValueAtTime(65.4*2**('1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.indexOf(c)/12),i)),start(),stop(s.length)}

Simplesmente pega a string como parâmetro de função.

Snippet combinado

Eu sugiro que abaixe o volume, pois isso pode estar alto. Para interromper a reprodução, o snippet exigia a adição de o=cada um with(c.createOscillator()).

f= // keyboard input
_=>{c=new AudioContext;q=1;with(o=c.createOscillator())connect(c.destination),I.oninput=_=>(~(i='1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.indexOf(I.value,I.value=""))&&(frequency.value=65.4*2**(i/12),q&&start(q=0)))}

g= // string input
s=>{c=new AudioContext;with(o=c.createOscillator())connect(c.destination),[...s].map((c,i)=>frequency.setValueAtTime(65.4*2**('1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.indexOf(c)/12),i)),start(),stop(s.length)}

swap=_=>{keyboard=!keyboard;A.innerHTML=keyboard?"Keyboard":"String";S.style.display=keyboard?"none":"inline";window.c&&c.close();window.o&&o.stop();keyboard?f():I.oninput=null;I.value="";}
keyboard=0;
swap();
<span id="A"></span> Input:<br>
<input id="I">
<button id="S" onclick="g(I.value)">Run</button><br>
<button onclick="swap()">Swap</button>

Justin Mariner
fonte
Você pode colocar o objeto oscilador em uma withdeclaração à golfe fora todas as instâncias o., como este:_=>{c=new AudioContext;with(c.createOscillator())connect(c.destination),I.oninput=_=>(~(i='1!2"34$5%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm'.search(I.value,I.value=""))&&(frequency.value=65.4*2**(i/12),r||(start(),r=1)))}
darrylyeo
11
@ Darrylyeo Obrigado, implementará a withdeclaração, mas ela quebra o último bit ( o.r||(o.start(),o.r=1)) desde que eu estava usando o fato de que não o.restava definido até esse momento, mas agora ele errou, pois rnão foi declarado. Acontece que foi mais curto declarar essa variável separada de qualquer objeto, então eu fiz isso.
Justin Mariner
Quando você insere o símbolo '$', uma frequência muito alta é produzida.
Кирилл Малышев
@ КириллМалышев Boa captura, isso é porque .search()trata a entrada como regex. Mudou para .indexOf().
Justin Mariner
1

AHK , 130 bytes

s=1!2"34$5`%6^78*9(0qQwWeErtTyYuiIoOpPasSdDfgGhHjJklLzZxcCvVbBnm
Loop,Parse,1
SoundBeep,55*2**((InStr(s,A_LoopField,1)-10)/12),999

Eu escolhi a opção 2.

Explicação:

Armazenar a string de pesquisa como a variável sera menor do que escapar dessa bagunça diretamente na SoundBeepfunção. Eu tive que escapar do sinal de porcentagem, pois esse é um caractere de escape para nomes de variáveis, mas o restante da string está OK como está.

Por padrão, a variável 1é o primeiro parâmetro de entrada. Alimentá-lo em um loop de análise sem especificar um delimitador resultará em cada caractere na cadeia de entrada sendo analisado individualmente.

SoundBeep capta uma frequência em Hz e uma duração em milissegundos e toca essa nota por tanto tempo.

A parte divertida foi descobrir as frequências certas. Referenciando a tabela de frequências tecla de piano da Wikipedia ea fórmula na mesma página, eu achei a codificação mais curto era usar um 1 como a nota de referência porque é a frequência é o círculo agradável 55 Hz. Como queremos começar em C 1 , temos que ajustar de A 1 (nota 13) para C 1 (nota 4). Isso, mais o fato de InStrser um indexado, é o motivo pelo qual subtraímos 10 do resultado da InStrfunção.

Engenheiro Toast
fonte