将钢琴键盘用作计算机键盘

我有RSI问题,并尝试了30种不同的电脑键盘,这些键盘都给我带来了痛苦。弹钢琴不会给我带来痛苦。我弹钢琴大约20年了,没有任何疼痛问题。我想知道是否有一种方法可以从MIDI键盘捕获MIDI并输出键盘笔画。我对MIDI一无所知,但我想要一些关于如何将此信号转换为击键的指导。

86316 次浏览

实际上,我之前就做过这个,试图将摇滚乐队鼓输入捕获到我的计算机中(制作一个Java自制鼓模拟器)无论如何,我在这里问了一个问题,时间延迟问题(那里有轮询代码,以及我试图做的事情。)。如果我能找到我的程序,我可以给你代码,它使用第三方API(JInput)。

不管怎样祝你好运。

我没有做任何MIDI编程多年,但你的基本想法是非常健全的(没有双关语)。

MIDI是一个“事件”(或“消息”)流,其中两个最基本的是“note on”和“note off”,它们带有音符编号(0=C在中间C下方五个八度,通过127=G在中间C上方五个八度,以半音形式)。这些事件在速度敏感(“触摸敏感”)的键盘上携带一个“速度”数字,其力(你猜对了)在0到127之间。

在速度、和弦和踏板之间,我认为你可以为钢琴键盘想出一个相当好的“打字”界面。特别是和弦可能是一项非常强大的技术——正如我在评论中提到的,这就是为什么普通速记员可以使用速印机来跟上人们连续几个小时的谈话,而即使是顶级打字员也无法通过普通打字机风格的键盘进行任何时间。与机器速记一样,你需要一本和弦含义和和弦序列的“字典”。(你能看出我以前在机器速记的软件方面工作吗?)

要做到这一点,基本部分是:

  • 接收MIDI输入。不要尝试自己做这件事,使用库。编辑:显然,Java声音API支持midi,包括从MIDI控制器接收事件。酷。本页面也可能有用。
  • 将该数据转换为您要发送的击键,例如通过我上面提到的字典。
  • 将击键输出到计算机。

为了与软件最广泛地兼容,您必须将其编写为键盘设备驱动程序。这是操作系统的插件,用作键盘事件的源,与底层硬件(在您的情况下,钢琴键盘)通信。对于Windows和Linux,您可能需要使用C语言。

然而,由于你只是生成按键(不是试图拦截它们,这是我几年前试图做的),你可以使用操作系统用于发送人工击键的任何功能。Windows有一个接口可以做到这一点(可能有几个,我想的是SendInput,但我知道有一些“日志”接口可以做类似的事情),我相信其他操作系统也可以做到这一点。这可能足以满足你的目的——这就是我要开始的地方,因为设备驱动程序路线会很尴尬,你可能不得不使用与Java不同的语言。(我是Java的忠实粉丝,但是操作系统用来与设备驱动程序对话的接口往往更容易通过C和类似语言使用。


更新:更多关于击键和弦的“字典”:

基本上,字典是一个trie(谢谢,@Adam),我们使用最长前缀匹配进行搜索。详细信息:

在机器速记中,速记员通过同时按下速记机上的多个键,然后释放它们来写作。他们称之为键盘的“笔划”;就像在钢琴上弹奏和弦一样。笔划经常(但不总是)对应于口语的音节。就像音节一样,有时一个笔划(和弦)本身就有意义,有时它只有与以下笔划组合在一起的意义。(想想“好”与“好”之后的“再见”)。尽管他们会受到他们所就读的学校的严重影响,但每个速记员都有自己的“字典”,记录他们用什么笔画来表达什么意思,这是一本他们在工作生活中不断磨练的字典。字典中会有速记部分(简称“速记”)是一个笔画长或多个笔画长的条目。通常,会有几个条目具有相同的起始笔画,这些条目由它们的长度和随后的笔画区分。例如(我在这里不会使用真正的速记,只是占位符),可能有这些条目:

A     = alpha
A/B   = alphabet
A/B/C = alphabetic
A/C   = air conditioning
B     = bee
B/C   = because
C     = sea
D     = dog
D/D   = Dee Dee

(这些字母不是音符,只是抽象的标记。

请注意,A开始多个条目,还请注意,如何翻译C笔画取决于您之前是否见过AB,或者您正在重新开始。

另请注意(尽管在上面的小样本中没有显示),“演奏”同一个单词或短语可能有多种方法,而不仅仅是一种。速记员这样做是为了根据手的位置更容易从前一个单词流向下一个单词。那里有一个明显的音乐类比,你可以用它来使你的打字流程更类似于演奏音乐,以防止这对你的钢琴演奏产生负面影响,并最大限度地提高这实际上有助于RSI的可能性。

当将速记翻译成标准文本时,我们再次使用“最长前缀匹配”搜索:翻译算法从书写的第一笔笔画开始,并查找以该笔画开始的条目。如果只有一个条目,并且长一笔画,那么我们可以可靠地说“这是要使用的条目”,输出相应的文本,然后重新开始下一笔。但更有可能的是,该笔画开始了多个长度不等的条目。因此,我们查看下一笔,看看是否有条目以这两个笔画依次开头;依此类推,直到我们找到匹配。

所以在上面的字典中,假设我们看到了这个序列:

A C B B C A B C A B D

Here's how we'd translate it:

  1. A is the start of three entries of varying lengths; look at next stroke: C
  2. A/C matches only one entry; output "air conditioning" and start fresh with next stroke: B
  3. B starts two entries; look at next stroke: B
  4. B/B doesn't start anything; take the longest previous match (B) and output that ("bee")
  5. Having output B = "bee", we still have a B stroke in our buffer. It starts two entries, so look at the next stroke: C
  6. B/C matches one entry; output "because" and start fresh with the next stroke: A
  7. A starts three entries; look at the next stroke: B
  8. A/B starts two entries; look at the next stroke: C
  9. A/B/C only matches one entry; output "alphabetic" and start fresh with the next stroke: A
  10. A starts three entries; look at next stroke: B
  11. A/B starts two entries; look at next stroke: D
  12. A/B/D doesn't match anything, so take the longest previous match (A/B) and use it to output "alphabet". That leaves us with D still in the buffer.
  13. D starts two entries, so we would normally look at the next stroke — but we've processed all the strokes, so consider it in isolation. In isolation, it translates as "dog" so output that.

Aspects of the above to note:

  • You have a buffer of strokes you've read but haven't translated yet.
  • You always want to match the most strokes against a single entry that you can. A/B should be translated as "alphabet", not "alpha" and "bee".
  • (Not shown above) You may well have sequences of strokes that you can't translate, because they don't match anything in the dictionary. (Steno people use the noun "untranslate" -- e.g., with our dictionary, the strokes E would be an "untranslate".)
  • (Not shown above) Some theories of steno allow the same set of strokes to mean more than one thing, based on a broader context. Steno people call these "conflicts". You probably want to disallow them in your project, and in fact when steno used to be translated manually by the stenographer, conflicts were fine because they'd know just by where in the sentence they were what the right choice was, but with the rise of machine translation, conflict-free theories of steno arose specifically to avoid having to go through the resulting translated text and "fix" conflicts.
  • Translating in real time (which you'd be doing) means that if you receive a partial match, you'll want to hold onto it while waiting for the next chord — but probably only up to a timeout, at which point you'd translate what you have in the buffer as best you can. (Or maybe you don't want a timeout; it's your call.)
  • Probably best to have a stroke that says "disregard the previous stroke"
  • Probably best to have a stroke that says "completely clear the buffer without outputting anything"

一个很好的库。NET具有完整的midi支持(BASS),请转到http://www.un4seen.com

对于另一部分,将键盘midi音符转换为按键等,我会选择AutoItX,将ActiveX/COM和DLL接口转换为autoIt。信息和下载,转到http://www.autoitscript.com/site/autoit/

无需编写键盘驱动程序。

考虑在硬件上做一些模拟usb(或ps/2?)键盘的事情。您将不再依赖于特定的操作系统或特定的操作系统API。硬件解决方案将经得起时间的考验。当其他人都在运行Windows 11时,不要被困在Windows 7中使用旧的API!arduino很容易学习。

Arduino有大量的信息和帮助。这是一个为新手构建的硬件黑客平台。现在谷歌正在推动Arduino。只会变得更大

编辑:虚拟USB键盘软件硬件

有一个叫做GlovePIE的程序。你可以用简单的脚本语言对它进行编程,我相信它支持MIDI。我不确定这是否属于“Java”类别,但它仍然是一个很棒的程序。我用它来控制机器人使用ps3控制器。它非常强大。

您可以使用Teenys微控制器快速破解自己的USB键盘。

事实上,他们有关于如何制作USB键盘的示例代码。

您可以通过两种方式处理此问题:

  1. 找架旧钢琴,把开关直接连接到小钢琴上

  2. 添加额外的逻辑连接到MIDI端口和必要的解码。

在Java,您可以使用JMF(JavaMedia框架)转换MIDI信号。 键盘设计的基础是易于使用,即用户交互界面;并将常用的字符/符号放在手边。

Java声音资源:示例:数字信号处理(DSP)中的示例代码和API有助于了解如何处理信号。

更多参考资料:

我在大学学习钢琴演奏,然后进入交互设计,编程和使用Vim,所以我实际上花了很多时间制作这样的原型。

您可以通过使用多媒体艺术家的图形化编程语言“纯数据”以及alexandre的x11key外部在Linux中快速完成这项工作。

在Mac上,你可以使用MidiStroke。我相信Windows上的一种方法涉及MidiOxAutoHotKey工具。还有一次,我有一个版本使用Max/MSP的Java插件。我相信Patrice Colet为Pure Data制作了一个外部窗口,也可以工作,但我似乎无法再定位它了。此外,还有用于MaxMSP的外部可以在Windows上做到这一点。最后,非免费但很棒的提升者可以做你想做的事情-参见功能页面。

当我让它工作时,我从来没有坚持过它,因为我无法停止使用布局工具。不过,把我的显示器放在我的电子键盘上很酷!祝你好运。

许多键盘都有一个串行端口(RS-232)连接器来向计算机发送MIDI信号。我使用一个名为大梁的程序将串行端口通信转换为键盘笔画。

Girder具有“映射”功能,可让您将每个键逐个映射到相应的击键。

这可能是您正在寻找的简单解决方案!

关于MIDI

你说你“对MIDI一无所知”。一旦你掌握了MIDI技术,它是相当直接的,但一开始可能会令人困惑。对我理解MIDI基础(如果你想编写MIDI交互程序,这当然是必要的)非常有帮助的资源之一是一本名为MIDI为技术恐惧症的书。这是一本容易阅读的书,非常有帮助。


纯数据和最大

在我开发交互式多媒体的经验中,我遇到了两个非常相似的程序,它们有助于连接和映射来自任何设备的信号/输入。

这些是用于Mac环境的最大和用于PC环境的纯数据。两者都有大量的在线留档和YouTube教程。视频Max/MSP教程1-使用您的计算机键盘作为midi键盘(ableton样式)演示了一个用Max构建的程序,该程序将计算机键盘映射到MIDI键盘的输入(这基本上与您尝试的完全相反)。您可以通过使用相同的模式来获得预期的结果,但颠倒信号/映射。


AutoHotKey

AutoHotKey是一个免费的Windows开源实用程序,允许您将设备上的键和按钮重新映射到宏。它原生支持QWERTY键盘、操纵杆和鼠标宏。

但是,我能够找到一个支持您正在寻找的特定映射的实现。这两个线程解释了这个过程:

  1. AutoHotkey中的MIDI IN支持,用例的讨论。作者正在寻找可以检测MIDI IN输入并将其转换为按键的程序

  2. MIDI输入库,作者问题的解决方案和AutoHotKey的发布代码/补丁,实际实现了您的预期结果。

基本上,看起来AutoHotKey以及该用户的自定义补丁将提供您创建从MIDI键盘到QWERTY键盘输入信号的映射所需的确切内容。您所要做的就是安装、配置和定义您的映射。


还有别的吗?

一般来说,其他一些答案已经为您提供了有关MIDI和MIDI编程的更广泛的信息,但正如您的post所述,这似乎不是您正在寻找的。如果可能的话,我想帮助您更多,但是如果您可以更具体地了解您正在寻找的信息类型,那就更容易了。例如,您是对如何将MIDI键盘的输入信号转换为QWERTY键盘的信号更感兴趣,还是您的主要兴趣找到一个开箱即用的解决方案与您的特定问题有关?您正在寻找哪些尚未解决的问题?

在我看来,你不是在寻求关于如何自己构建它的建议,而是在询问已经有哪些资源来完成你想要的。根据您的操作系统,有很多方法可以实现这一目标,而无需从头开始编写自己的程序:

MIDI笔画

免费。适用于Mac OS X 10.3及以上。这个特别附带“使用任何MIDI键盘作为完全成熟的计算机键盘替代品的能力”。

Bome的MIDI翻译器

免费/Postcardware(这有点奇怪)。对于Windows 2000及以上,以及Mac OS X。它最初似乎更适合AutoHotkey类型的使用,但进一步观察,我认为它可以很好地做你想要的。

最大和aka.keyboard

免费。对于macosx。不完全是一个“开箱即用”的解决方案,但如果您对基本的设备配置感到满意,它应该不会太糟糕。

看看MAME街机游戏。他们已经建立了硬件设备,允许来自任何数量的不同项目的输入。例如,iPac将输入设备的信号转换为USB,然后计算机可以用它来模拟按键。你可以使用任何排列方式的输入设备组合,不需要疯狂的编程逻辑——因为解释输入的软件已经完成并经过了良好的测试。

我见过飞行模拟器驾驶舱输入,自定义信息亭,以及用这种方法构建的投票系统……而且价格合适!

尝试Bome的MIDI翻译器

它可以跨平台工作,可以轻松地将任何MIDI输入转换为键盘,快速设置和配置,并且可以免费供个人使用。

有一个教程,快速提示:MIDI翻译-MIDI到击键,如何轻松设置它:

基本上,你可以做的事情有无限的可能性,包括和弦和修改键。我用它来制作我的现场音频装备,用我的钢琴控制我的daw,从来没有遇到过问题。

通过声卡播放任何外部MIDI键盘作为控制器,您将获得更好、更快乐的结果(无论您喜欢使用什么操作系统和/或daw程序)。然后将其路由到您的GB软件(或其他什么)中,并实时生成他们以这种方式提供给您的许多声音。

如果您的声卡不支持MIDI I/O(输入/输出 /thrus),那不是问题。您可以考虑研究和投资外部MIDI桌面转换器。许多都配备了进一步将MIDI输出转换为USB 2.0(完全绕过现有声卡)。

例如:通过使用计算机键盘和铅笔工具的Z和X更改键选项获得“类似人类”的恩典音符结果非常困难。相反,当您自己的手指可以使用MIDI键盘从自己的物理八度寄存器范围播放时-立即!

我知道可能会涉及预算限制。但是,这些看似便宜的“卡西欧”型5倍频程键盘中的一些在Radio Shack以低于100美元(*或更低)的价格出售,这就是您所需要的(此外,他们的一些板载声音补丁和音序器模块的声音和处理效果也非常好)。

RadioShack MIDI键盘选项

至于现有声卡的外部MIDI转换器,我为您运行了一些google搜索,如下所示,并特别考虑了Mac平台:

很多这种外部MIDI转换信息起初可能对你来说很麻烦,所以我把事情分解成“用户友好”的考虑和预算:

当使用daw时,像VST一样促进虚拟键盘没有错。他们有自己的位置。

但是,你听起来像一个有成就的键盘手。那么,为什么不考虑我刚才提到的外部MIDI转换/键盘选项呢?

祝你好运,我希望这能给你一些可以为你工作的想法!

使用. NET DirectSound接口挂钩到MIDI设备应该相当容易。您需要识别您的目标MIDI设备,然后获取监听传入消息的代码(有关于通过Google执行此操作的文章)。

由于您将MIDI用作键盘,因此基本上只有两条MIDI消息需要检测,即音符打开和音符关闭。MIDI消息是三个数据字节,用于指定命令、音符和速度。音符关闭只是音符编号(有时“坏”MIDI堆栈以零速度发送音符,这也是您所期望的)。

一旦您有消息翻译它们,键盘输出应该相当简单。NET。

在其他答案中有很多关于技术细节的建议;我只是想给你一个实际的MIDI消息的想法。祝你好运!

您可以使用源代码示例访问硬件。NET在MIDI DotNet中。

作为创建MIDI笔记数据流的源代码的完整工作示例位于VB 5/6-Tipp 0521: MIDI-Töne erzeugen(Visual Basic 6.0,某处是. NET版本)

模拟键盘笔触的一种方法是在VB 5/6-Tipp 0155: TastatureReignisse simulieren(Visual Basic 6.0,某处也是. NET版本)中

而识别击键是在提示上传:VB.NET0266: Globaler KeyHook中描述的。

在此处输入图像描述

然后,只需为钢琴演奏者使用一个好的工作矩阵 Timo Boehmewww.goldengel.ch

在钢琴上,当你是一个好的球员时,你可以在键盘上有10个手指,如果矩阵可用,你可以比我认为的任何计算机键盘用户更快。:-)

这样的话,如果我没理解错你的问题,应该不是什么大事。

你可以看看弦键盘。它们的优点是,在使用它们之前,你不需要为它们编写驱动程序,有些类似于钢琴键盘的布局。

您可以使用简单的AutoIt脚本来读取MIDI事件,请参阅MIDI输入

您还需要MIDI UDF模拟按键

阅读MIDI事件应该很容易,但是不同的MIDI控制器(乐器)具有不同的功能。首先尝试找出您的MIDI钢琴可以做什么,然后看看如何最好地将这些功能映射到模拟的QWERTY键盘按下。

如果你愿意,你可以在屏幕上或托盘中有一些东西来帮助你看到你在做什么(即ShiftCtrlAlt模拟)。

要解决这个问题,你需要几件事:

  1. 一种从键盘捕获MIDI数据的方法。根据接口:MIDI接口(经典)或USBMIDI接口(现代)最可能的接口是计算机,因为它提供了最多的选项。USB主机微控制器并不像仅仅使用计算机那么简单。

  2. 将MIDI数据转换为击键的方案。就像一位用户指出的那样,和弦是可行的方法,因为键的数量不依赖于钢琴键的数量。

  3. 一种将键注入操作系统的方法。这将需要一个低级驱动程序才能准确。我已经在Windows 7中将键盘和鼠标数据注入应用程序的应用程序中玩过,它可能是片状的,取决于应用程序当前是否处于焦点。这是接口中最难的部分。可能起作用的是创建一个HIDUSB键盘微控制器,也有串行接口。

串行接口将创建一个虚拟串行端口。读取MIDI数据并产生击键的软件可以向虚拟串行端口发送串行消息。微控制器将发送击键,使其看起来像标准键盘输入。这将允许连接MIDI端口和USB MIDI键盘。

嗯,使用这种类型的界面,您还可以模拟鼠标并使用一些钢琴键设置鼠标轴和按钮。压力可用于确定鼠标指针速度。因此您也可以消除鼠标。这种方法的另一个好处是您连接的任何类型的输入设备都可以与虚拟串行端口通信以产生键盘和鼠标事件。因此,如果您想添加其他硬件,例如鼓踏板或操纵杆,只需调整与串行接口通信的程序即可。

上面的另一个想法是像上面发布的一些使用Arduino,但也包括来自Sparkfuns的USB主机屏蔽来处理基于USB的音乐键盘。这允许Arduino被编程为引导加载器芯片中的键盘或键盘鼠标组合,并允许设备为基于USB的音乐键盘充当usb主机。那么你就可以涵盖这两种类型。尽管如此,我仍然认为虚拟串行端口方法更灵活,从长远来看更容易编程。Arduino设备将比桌面程序或服务更难更改。

还有另一种可能: 合唱单手键盘已经存在。我看过他们的视频,但你必须确定那些是否伤害你的手。

学习速记!

从你的所有讨论中可以清楚地看出,从技术的角度来看,你不想重新发明任何轮子。但是,一旦你建立了联系(这个问题所问的),并开始工作,你还有大部分工作要做:你必须训练你的大脑。你必须发明最聪明、最有效的方法来做到这一点——一个完全脱离计算机技术人员的设计问题。你或我们中的任何一个人都会失败。

幸运的是,经过几个世纪的成熟,这个问题已经得到了解决和磨练。

学习速记!

是的,这会让你倒退一些。但是几百个小时的时间有什么价值,最后,一个不太好的结果?此外,速记维基百科文章说,“它看起来更像钢琴键盘”。

除非,当然,你想有一个杂耍效果。我不得不承认,我从来没有想过这种可能性,看到有人从钢琴键盘上弹出一个文本,这将是真的娱乐!

您可以从带触摸板的USB键盘开始(或者指示棒会更符合人体工程学?),使用船体来翻译它(我相信它可以配置为让非字母键保留其功能,因为它们对于编程至关重要),或者,按照Re: P的键盘线程滚动您自己的USB速记键盘,或者,购买速记型

祝你好运!

我同意Brian O'Dell的回答——如果这是我的项目,我会用硬件来做。它的优点是独立于平台和硬件——你的盒子取代了对MIDI-USB接口和PC API的需求。

mbed是一个非常容易学习的快速原型设计平台,与Arduino IMHO(在线编译器,512 KB闪存,96 MHz,C++语言)相比具有多种优势。它为您预先编写了usb键盘接口USB Midi接口

社区非常友好,愿意提供帮助,并且有很多现有的项目同时使用MIDI和USB hid仿真-在YouTube上搜索“mbedMIDI”或类似内容。

如果你知道Java编码,你可以这样使用:

首先,使用send(..)方法实现javax.sound.midi.Receiver,该方法将“Note on”事件映射到您想要的击键。

您需要使用其getMessage方法获取MidiMessage的内容并以您的方式将其插入。消息字节的含义可以在MIDI消息中找到。

在接收到某个键盘键的“note on”或“note off”后,您可以通过为其分配KeyEvent类的常量将其映射到您喜欢的键,例如C#4->KeyEvent.VK_A等。然后,java.awt.Robot的keyPress和keyRelease方法可以使用此键代码将击键实际发送到操作系统,从而发送到其他应用程序。

如果您使用Linux请访问软脚

它应该正是你正在寻找的-如果你调整MIDI音高到你喜欢的键映射…

我从没想过这对任何人都有用,除了我;o)

如果你不想自己做任何编程,只是想解决问题,你可以买一个USB-MIDI键盘,在那里你可以重新分配任何键来发送QWERTY键盘输出信号,而不是MIDI输出,例如M-Audio Axiom Pro

此方法适用于任何操作系统和任何支持标准USB键盘的计算机,因为MIDI键盘将自己标识为标准QWERTY键盘。

尝试使用基于微控制器的系统,例如arduino

这不会太难。

我假设你在windows上,但不确定。我用普通的C++编写了一个MIDI音序器,http://pianocheetah.com,它允许你使用钢琴键盘运行命令。没有任何理由你不能做同样的事情来按键 进入键盘输入流。

但是现在来吧。你还记得你花了多长时间才学会 首先是键盘,对吧? 你愿意再经历一次吗? 你愿意污染你受祝福的键盘吗 上面有一堆愚蠢的关键符号?

你需要至少使用26个字母,10个数字,11个标点符号, 以及至少12个功能键及其移位状态。 所以这是60个键加上转换状态。 这会烧掉整整5个八度的钥匙。 你会做钢琴“跳”=所有=时间。 “跟打字说再见吧!”

你可以从RSI中拯救自己,但你创造了另一个 给你自己不同类型的噩梦。

祝你好运,让你的老板在工作中给你买一个MIDI键盘。

如果你真正学会了弹钢琴,你就学会了 如何玩无压力。在QWERTY键盘上这样做。 没有紧张。慢慢开始。