使您的键盘变成键盘


10

任务

您应该编写一个程序,当按下按钮时,它会为每个键输出不同的声音。

您将使用的密钥是:

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

音符从处开始,C上方的每个键添加一个半音。

让我们稍微简化一下。您可以选择2个类似的任务,

1)按下一个键时输出一个不同的音符,直到另一个键被按下为止。该程序无限期运行

2)以一个仅包含上述字符的字符串作为输入,它将在每个音符中准确输出1秒钟(允许0.05秒钟的变化)

输入值

  1. 按键被按下
  2. 仅包含上述符号的单个字符串

输出量

  1. 单个音符一直响到按下另一个键
  2. 一系列音符,每个音符长1秒

笔记

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

规则

  • 您可以在任务中选择一个,但请说出答案中的哪一个
  • 您在任务2中获得了±0.05秒的变化
  • 每个符号沿音调增加1个半音。
  • 上面显示了各个注释
  • 这是一个因此最短的代码胜出

这原本是经过凯尔德·科阿林加·阿欣的同意后从这里取出的


要将其开放给没有音频库的语言,我建议使用第三种输出格式:包含选项2输出的WAV文件,该文件已写入stdout。这将允许使用任何可以打印二进制数据的语言进行输入。

Answers:


6

Python 3,154140字节

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

我选择了第二种任务类型。

循环遍历每个字符,并在字符串中查找此元素的索引。该索引是从Low C('1')开始向上的半音数。通过该公式可以计算出所需的频率。

PS此仅在Windows中有效。

-13字节归功于ovs。

-1字节感谢乔纳森·艾伦。


1
您可能应该提到这仅适用于Windows。
6

1
高尔夫球至141字节: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

但是问题要求节目....
尼尔·A,

0.05公差应允许你使用999
乔纳森·艾伦,


3

JavaScript(ES6),247或230字节

决定尝试两种选择。

感谢@darrylyeo建议了该with语句,节省了一些字节。
感谢@КириллМалышев指出的问题.search()

选项1 -键盘输入,252个 246 247字节

_=>{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

依靠输入元素接收键入的实际字母,而不是字符代码。焦点必须在输入框上。

选项2 -字符串输入,234个 229 230字节

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

只需将字符串作为函数参数。

合并摘要

我建议调低正在运行的音量,它可能会很大。为了停止播放,该片段需要o=在每个片段中添加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>


您可以将振荡器对象放入with语句中,以找出所有的实例o.,例如:_=>{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

1
@darrylyeo谢谢,将执行该with语句,但是o.r||(o.start(),o.r=1)由于我使用的o.r是直到那时r仍未定义的事实,所以它使最后一位()中断,但是现在由于未声明而出错。事实证明,将变量声明为与任何对象分开要短一些,所以我做到了。
贾斯汀·马里纳

当输入符号“ $”时,会产生很高的频率。
КириллМалышев

@КириллМалышев不错,因为这.search()会将输入视为正则表达式。切换到.indexOf()
贾斯汀·马里纳

1

AHK,130字节

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

我选择了选项2。

说明:

将搜索字符串存储为变量s比直接将乱码转义到SoundBeep函数中要短。我必须对百分号进行转义,因为这是变量名的转义字符,但是字符串的其余部分仍然可以。

默认情况下,变量1是第一个输入参数。在不指定定界符的情况下将其送入解析循环将导致单独分析输入字符串中的每个字符。

SoundBeep 以Hz为单位输入频率,以毫秒为单位输入持续时间,并持续播放该音符。

有趣的部分是找出正确的频率。参照维基百科上的钢琴键频率表和同一页上的公式,我发现最短的编码是使用A 1作为参考音符,因为它的频率大约是55 Hz。因为我们要从C 1开始,所以我们必须从A 1(第13个音符)调整为C 1(第4个音符)。那,加上InStr一个索引的事实,就是为什么我们从InStr函数的结果中减去10 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.