我有RSI问题,尝试了30种不同的电脑键盘,都让我很痛苦。弹钢琴不会给我带来痛苦。我已经弹钢琴20年了,没有任何疼痛问题。我想知道是否有一种方法可以从MIDI键盘捕获MIDI并输出键盘敲击。我对MIDI一无所知,但我想要一些关于如何将这个信号转换成按键的指导。
当前回答
我同意Brian O'Dell的回答——如果这是我的项目,我会用硬件来做。它的优点是与平台和硬件无关——你的盒子取代了对MIDI-USB接口和PC API的需求。
mbed是一个非常容易学习的快速原型平台,与Arduino IMHO相比具有多种优势(在线编译器,512 KB闪存,96 MHz, c++语言)。它有一个USB键盘接口和一个预先为您编写的USB Midi接口。
社区是非常友好和愿意帮助的,有很多现有的项目同时使用MIDI和USB隐藏仿真-搜索Youtube“mbed MIDI”或类似的。
其他回答
实际上,我在这个工作了一段时间前,试图捕捉摇滚乐队鼓输入到我的计算机(做一个小Java自制鼓模拟器)无论如何,我问了一个问题在这里,时间延迟问题(有轮询代码在那里,以及我试图做的事情。)如果我能找到我的程序,我可以给你的代码,它使用第三方API (JInput)。
祝你好运。
以MAME街机游戏为例。他们已经建立了硬件设备,允许输入任意数量的不同项目。例如,iPac将输入设备的信号转换为USB,然后计算机可以使用USB来模拟按键。您可以使用任意组合的输入设备,只要不需要疯狂的编程逻辑就可以,因为解释输入的软件已经完成并经过了良好的测试。
我见过飞行模拟器座舱输入,自定义亭,和投票系统建立在这种方法.....而且价格也很合理!
许多键盘都有一个串行端口(RS-232)连接器,向计算机发送MIDI信号。我使用一个名为“梁”的程序将串口通信转换为键盘敲击。
“梁”有一个“映射”功能,允许您将每个键一个接一个地映射到相应的击键。
这可能是你正在寻找的简单解决方案!
我已经很多年没有做过任何MIDI编程了,但是你的基本想法非常合理(没有双关语)。
MIDI是一连串的“事件”(或“信息”),其中最基本的两个是“开启”和“关闭”,它们都带有音符号(0 = C中C低5个八度,到127 = G中C以上G高5个八度,为半音)。这些事件在速度敏感(“触摸敏感”)的键盘上携带一个“速度”数字,其力度(你猜对了)在0到127之间。
Between velocity, chording, and the pedals, I'd think you could come up with quite a good "typing" interface for the piano keyboard. Chording in particular could be a very powerful technique — as I mentioned in the comments, it's why rank-and-file stenographers can use a stenotype machine to keep up with people talking for hours in a row, when even top-flight typists wouldn't be able to for any length of time via normal typewriter-style keyboards. As with machine stenography, you'd need a "dictionary" of the meanings of chords and sequences of chords. (Can you tell I used to work in the software side of machine stenography?)
要做到这一点,基本的部分是:
接收MIDI输入。不要尝试自己去做,使用一个库。编辑:显然,Java Sound API支持MIDI,包括从MIDI控制器接收事件。酷。本页也可能有用。 将数据转换为你想要发送的击键,例如通过我上面提到的字典。 输出击键到计算机。
为了最广泛地与软件兼容,您必须将其作为键盘设备驱动程序编写。这是操作系统的一个插件,用作键盘事件的源,与底层硬件(在您的例子中是钢琴键盘)通信。对于Windows和Linux,你可能会想要使用C语言。
However, since you're just generating keystrokes (not trying to intercept them, which I was trying to do years ago), you may be able to use whatever features the operating system has for sending artificial keystrokes. Windows has an interface for doing that (probably several, the one I'm thinking of is SendInput but I know there's some "journal" interface that does something similar), and I'm sure other operating systems do as well. That may well be sufficient for your purposes — it's where I'd start, because the device driver route is going to be awkward and you'd probably have to use a different language for it than Java. (I'm a big fan of Java, but the interfaces that operating systems use to talk to device drivers tend to be more easily consumed via C and similar.)
更新:更多关于和弦到按键的“字典”:
基本上,字典是一个trie(谢谢,@Adam),我们用最长前缀匹配进行搜索。细节:
In machine stenography, the stenographer writes by pressing multiple keys on the stenotype machine at the same time, then releasing them all. They call this a "stroke" of the keyboard; it's like playing a chord on the piano. Strokes frequently (but not always) correspond to a syllable of spoken language. Like syllables, sometimes one stroke (chord) has meaning all on its own, other times it only has meaning combined with following strokes. (Think "good" vs. "good" followed by "bye"). Although they'll be heavily influenced by the school at which they studied, each stenographer will have their own "dictionary" of what strokes they use to mean what, a dictionary they will continuously hone over the course of their working lives. The dictionary will have entries where the stenographic part ("steno", for short) is one stroke long, or multiple strokes long. Frequently, there will be several entries with the same starting stroke which are differentiated by their length and by the subsequent strokes. For instance (and I won't use real steno here, just placeholders), there may be these entries:
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笔画取决于您之前是否看过A、B,或者您正在从头开始。
Also note that (although not shown in the very small sample above), there may be multiple ways to "play" the same word or phrase, rather than just one. Stenographers do that to make it easier to flow from a preceding word to the next depending on hand position. There's an obvious analogy to music there, and you could use that to make your typing flow more akin to playing music, in order to both prevent this from negatively affecting your piano playing and to maximize the likelihood of this actually helping with the RSI.
When translating steno into standard text, again we use a "longest-prefix match" search: The translation algorithm starts with the first stroke ever written, and looks for entries starting with that stroke. If there is only one entry, and it's one stroke long, then we can reliably say "that's the entry to use", output the corresponding text, and then start fresh with the next stroke. But more likely, that stroke starts multiple entries of varying lengths. So we look at the next stroke and see if there are entries that start with those two strokes in order; and so on until we get a match.
根据上面的字典,假设我们看到了这个序列:
A C B B C A B C A B D
我们是这样翻译的:
A is the start of three entries of varying lengths; look at next stroke: C A/C matches only one entry; output "air conditioning" and start fresh with next stroke: B B starts two entries; look at next stroke: B B/B doesn't start anything; take the longest previous match (B) and output that ("bee") Having output B = "bee", we still have a B stroke in our buffer. It starts two entries, so look at the next stroke: C B/C matches one entry; output "because" and start fresh with the next stroke: A A starts three entries; look at the next stroke: B A/B starts two entries; look at the next stroke: C A/B/C only matches one entry; output "alphabetic" and start fresh with the next stroke: A A starts three entries; look at next stroke: B A/B starts two entries; look at next stroke: D 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. 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.
以上各方面要注意:
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"
你可以看看和弦键盘。它们的优点是在使用它们之前不需要为它们编写驱动程序,有些类似于钢琴键盘的布局。