自己打造的一个电脑钢琴

  怎么用电脑键盘来弹钢琴?其实这种电脑钢琴软件很多,比如我之前接触过EveryOnePiano,比较出名的还有FreePiano。当然我们也可以自己做一个类似的东西,我的在线钢琴没有取名字,Github仓库名称我索性用了EveryOnePiano的缩写EOP。

这里是链接,点开即玩(ie浏览器是不可能支持滴!)

  大致的使用方法可以在点开后的菜单条的“?”查看(不详细,最好还是看本文后面给的例子哦),点击键盘,屏幕上会显示一个虚拟电脑键盘,上面将标出每个键的音名、唱名或功能(按住Ctrl、Shift、Alt后会有对应的功能快捷组合键)。本文也有一部分的使用说明,但侧重记录我对它的想法与实现过程。
  对了,如果你是手机用户,点击键盘可以模拟电脑键盘,再点一次键盘可以模拟钢琴键盘,类似“完美钢琴”那种手机App哦!

电脑键盘如何弹钢琴

  下面重点说说电脑用户。问题是,电脑键盘与钢琴键盘不一样,怎么布局才最合理?我看到过用电脑键盘上ABCDEFG直接对应do re mi fa sol la si的,这种布局导致原音阶顺序完全打乱,不可取,一般采用这种键盘的游戏跟练打字没啥区别。还有更离谱的下图这样黑白交错的键盘,这简直是对钢琴的侮辱!我打死也不会用这种键盘!

这简直是对钢琴的侮辱!我打死也不会用这种键盘!
而EveryOnePiano采用的是这样的布局:
EveryOnePiano默认键盘布局
这种布局才是正确的音阶思维方式,但它都还有缺点:无法弹奏半音阶。电脑键盘没有真正的钢琴键盘那么长,如果我们交替在键盘上像钢琴那样安排黑键的位置,虽然这种布局是最接近真实钢琴的,但你几乎别指望用它左右手演奏完整乐曲,因为键位不够,音域会非常狭窄。但有半音(调外音)的曲子很多,为此EveryOnePiano支持设置每个键对应什么音,你可以根据曲子自己把需要的半音安排上去。这种方法在演奏中效果是非常好的,而且通过设置每个键盘的声部,还可以做到伴奏与旋律(左右手)拥有不同力度,甚至Free piano可以把鼠标放在脚下踩当踏板,可以说已经挖掘到到电脑键盘的极限潜力了。

  但我还是不满意。

即兴自由演奏

  最先我的在线钢琴只是弹奏、记录弹奏音符、回放这些功能。后来我发现它可以辅助作曲、编曲。说实话,我的演奏技术并不好,所以我从来不追求什么演奏效果,我的兴趣在于作曲、编曲。我需要更加灵活的输入半音的方式(哪怕不太方便快速输入)所以我决定不在我的钢琴里面加入每个键位的修改设置,取而代之,通过很多方法来设置调号的升降记号和临时变音记号。我琢磨了很多方案,升降调输入方式的演变是这样的:

  • 首先要有移调功能,这样就不用弹很多半音(黑键)。但这个只适合真的变调,不适合临时变音记号。
  • 最原始的想法是通过按住空格键的方式来使所有的音升高半音,这样就解决了所有音都能够在一个键盘上弹出来了。之所以选空格键是因为它长,手从哪里都能很快够到它方便。
  • 然而当你弹和弦的时候很致命,比如同时弹2 #4 6,按住空格键所有音都会升高。因此我给方向键引入了#1、#4、#5、#6来解决这个问题:按下一次后即升对应的音,除非按shift键才能还原清除。所以遇到小调里的#5就不用怕了。按方向键#5后就可以弹了,但需要注意的是要弹还原sol之前一定要按shift还原。
  • 由于存在要按shift还原的问题还是不太好用。我又想到了一个奇招:如果同时弹的音只有一个音要升半音,那我还不如稍微提前一点点弹下它来跟其他音区分。我决定还是用空格键实现这个功能:如果你按住空格键不弹没弹其他音就松开了,系统将会等待你弹下一个音把它升高。这样通过微妙控制时间差可以摆脱方向键跟Shift键的束缚。
  • 后来我发现我的键盘还有瑕疵:没有#2(♭3)。我又规定了:按住Shift+方向键可以临时变♭2、♭3、♭5、♭6。后来发现每次按shift也不方便,干脆加了一个升/降快捷键Ctrl+~来交替升/降操作的地位:比如切换到降调模式后按空格键会把所有音降半音而不是默认的升,且方向键直接能临时降四个音,按住Shift反而是临时升。
  • 我也不是只即兴,有时也会去找五线谱弹。虽然可以用移调来弹任何谱子,但这种方法总是很笨拙,也不利于培养绝对音感。我于是又设计了Ctrl+数字的快捷键设置调号:数字代表#的个数(比如A大调#1 #4 #5就按Ctrl+3)。如果是♭记号,则用Ctrl+~+数字(比如♭A大调♭2 ♭3 ♭6 ♭7就按Ctrl+~+4)。调号设置在于按Shift不会将它清除(清除调号单独用Ctrl+Q),这样可以放心用方向键临时变音了。
  • 至于小键盘,我完全没给它设置任何键位,一是要兼容笔记本,二是小键盘不是横排的,给它上面排上音也没什么逻辑性(比如在视奏时你发现小键盘就是灾难),所以干脆我就不管小键盘了,实际使用发现大键盘够用了。

  虽然这样做还是不能完全跟Midi键盘比,(比如半音阶上行、下行旋律演奏困难、键盘按键冲突)但体验确实好得多。这些操作其实是根据我自己的喜好定制的,现在让我用Everyone piano那种固定键位的来即兴反而不如我的在线钢琴顺手了。
  其实这里面可做的东西还很多。比如我之前尝试过用计算机来作曲(根本不会神经网络那些,直接在音阶内一定范围内Math.random()),电脑键盘模拟吉他可以按弦、扫弦(键位冲突太厉害,基本没法用)等,但比较失败。然后也加入了Freepiano那种踩鼠标当踏板的功能。(点击踏板按钮再点击锁尔后放到地上踩,以免脚移动误操作)

实操演练

  下面我放一个演奏的例子吧,周杰伦最近的新歌《最伟大的作品》。

  也可以点这里直接去B站看哦。
  下面解析一下:首先这首歌是g小调,跟♭B大调的调号一样,因为我习惯首调,所以直接按Alt+`两次移调(C大调下移两个半音就是♭B大调),如果你照简谱就跟我一样,找五线谱弹,要用固定调移调,具体做法见下面的谱。开头和弦的根音分别是6-5-4-3-6-5-4-3,但注意中间3那个和弦出现了音#5,我们需要在5与#5之择机按下箭头升高5,或在弹奏#5之前按空格键来临时升高。我这里采用的是第一段按空格键,第二段按方向键。进入到后面《Secret》穿越前的快节奏片段,这里面不再有5,只有#5,所以我们保持#5不变即可演奏完。注意最后旋律671#12#234361’76#566’中的#1 与#2我连按了两次空格来实现,这是全曲最难的部分了,我这里也录了很多遍才过。。
谱来源于 https://www.bilibili.com/read/cv17442054
  进入到主歌,我分别用了打击乐(Percussion)、贝斯(Bass)、弦乐(Strings)、吉他(Guitar)四轨来演奏。切换乐器在上面菜单的通道面板里添加四个通道完成,在第一个通道录完后,可以鼠标右键将定位线移到第一个音符处,点击播放,同时再演奏下一轨来叠加录制。
有颜色的是旋律轨道
  注意打击乐的键位有点特殊:Midi的标准规范是把打击乐器映射到键盘的白键黑键上,所以我们需要方便直接弹奏黑键的键盘,点击菜单“Eop”按钮将键盘模式切换到“Ki”模式,由于底鼓在钢琴键盘低音区(音符2..),我们连按Ctrl+F降低一个八度,“Ki”模式中才找得到底鼓音色。
  不要小看它的演奏能力哦,我可以用这种键盘演奏巴赫的《哥德堡变奏曲》中的第0、1、2、4、5(仅前半段)、7、10、30变奏哦,当然还是我技术太渣,比较流畅的只有1、4、30,说不定以后我可能会再出个展示视频(翻译:咕咕)。
  好像李斯特的钟在电脑键盘上难度要稍微降低一些(证明留作习题),但还没进入我的练习计划中(翻译:继续咕咕咕)。

变成Midi编辑器

  在没有MIDI键盘的情况下编曲必须靠鼠标一个一个画音符,速度慢还容易出错。我用的编曲软件Cubase也提供了键盘钢琴输入的功能,但键位很少,并不实用。很可惜javascript不可能与编曲软件通信,但我可以先在这个在线钢琴里面编辑好,然后再导出成midi文件,这样就可以导入到编曲软件进行后加工了。所以我又给在线钢琴加入了导入导出midi文件的功能。其实早在最先我就设计过保存文件,但是当时被定为于用于给好友发音乐片段交流用,所以我自己设计了用4096个汉字对二进制编码的base4096格式。后来由于有跟其他编曲软件互通的需求,我遗弃了这种格式转到midi文件格式。正好又发现cubase占用声卡驱动后会让其他应用无法发声,就算后台释放资源后也得重新开一遍,所以我更加倾向于在我写的在线钢琴上完成,特别是像扒谱前期听音记音的这种工作。我陆续加入了音量、力度、bpm(速度)调节、多通道加载多音色等功能,已经能够大概播放网上下载的各种midi文件了。
一些按钮功能分布
  由于我本来演奏能力就很菜,加上电脑键盘更不方便,所以实时录音符的时值来编曲也是不太现实的。所以我又制作了特殊的编辑模式,可以自动等待输入音符等。然后就是一些修修补补了,如果时不时有了新想法我也会偶尔更新一下。(ps.看到屎山代码很可能不想动了,等以后重构2.0版吧)

技术细节 && 开始的想法

我开始这个想法是看到了一个叫Midi.js的库,它使用了Html5的新标准Web Audio来播放音频片段,其初衷是为了让Midi文件在浏览器Html5 audio上直接播放出来。Midi文件不同于一般的mp3、wav文件,它不是记录声音的波形,而是记录音符的音高、时值等信息来播放音乐,所以它的文件较小,是非智能手机时代铃声常用的格式。
  用MIDI.js很容易就能自己写出一个键盘钢琴程序(会点基础Javascript就行,就是直接添加键盘事件来播放指定的声音文件)而且演奏音符几乎无延迟!我以前用Flash也做过电脑钢琴,但延迟太大。(按下一个键要等将近半秒才发声)在Safari及不同版本Chrome下都能发声,但Edge浏览器好像一直没声音。这主要取决于浏览器对Web audio的支持情况。
  本着什么轮子都自己造,锁尔乱七八糟的库的原则,我自己去下载了音色,抛弃MIDI.js,自己写了一个键盘钢琴程序。而且我发现后来MIDI.js这个项目不再更新了,取而代之的是一个叫tone.js的库,这个库更加强大:它可以支持一些简单的合成器与效果器!感觉浏览器都有往编曲软件发展的潜力了。但我还是没有用tone.js,只是借鉴了它的部分源码,比如通过在小范围内调整播放速度改变音高可以减少加载2倍的音色音乐片段!这对提高音色下载速度有重大意义。