抛砖引玉:纯前端代码让手机变为一把吉他

  • 抛砖引玉:纯前端代码让手机变为一把吉他已关闭评论
  • 184 次浏览
  • A+
所属分类:Web前端
摘要

前段时间一时兴起想学一下吉他,但是一门乐器要演奏成“能听”的程度也不是一天两天的事情,对我这种音乐基础为 0 的人来说学习周期太长了,不想耗费太多时间在学习乐器上面,于是想找个取巧的方法。


前言

前段时间一时兴起想学一下吉他,但是一门乐器要演奏成“能听”的程度也不是一天两天的事情,对我这种音乐基础为 0 的人来说学习周期太长了,不想耗费太多时间在学习乐器上面,于是想找个取巧的方法。

最终方案就是做了个简单粗陋的微信小程序 Demo 去弹奏吉他乐,勉强算是成功吧,可以很简单地弹奏出乐曲。

大概一小时的学习周期(含学习简谱时间),可以弹出传统乐器学习一两个月的效果。

但是这个小程序有一个 BUG ,导致它也只能算是一个失败品。

文章最后会附上开源代码地址,且容我先抛出这块砖,希望能引来玉吧。

使用

这里贴出微信小程序的二维码,小程序的名字叫冒牌吉他手,大家可以体验一下。

抛砖引玉:纯前端代码让手机变为一把吉他

主界面

抛砖引玉:纯前端代码让手机变为一把吉他

本小程序有四个模式:自由模式、简单模式、灵魂模式和自动模式。

自由模式下,您可以按 1,2,3,4,5,6,7 等七个音符按键,分别对应 do(哆)、re(来)、mi(咪)、fa(发)、sol(唆)、la(拉)、si(西)。同时可以切换高低音和节拍按键来分别控制音高和音长。

简单模式下,程序会自动根据简谱识别出音高和音长,您只需要按七个音符按键即可。默认设置的简谱是《成都》。

灵魂模式下,程序会自动根据简谱识别出音高、音长和音符,您只需要按一个音符按键即可。

自动模式下,程序会自动根据简谱弹奏音乐,您无需操作。

编辑简谱时,会自动定位到简谱最末尾的位置,且只支持新增和删除。
删除:点击删除按钮会直接删除最末尾的简谱符号。

新增:按下相应的音符键,会结合当前的高低音和节拍按键,新增对应的简谱符号。

另外编辑模式下会多出来两个新的按键,分别是音符按键最左侧的“0”键和音符按键最右侧的“|”键。

“0”键代表简谱上的休止符。

“|”键表示表示简谱的分隔符,只用来标识,不输入也是可以的。

方案与原理

这个小程序完全是前端代码实现,无需服务端,并且不需要音频资源文件。

之所以做成这样,是因为微信小程序上面现在放资源文件是要给腾讯打钱的,而单纯的代码是不需要的 o(∩_∩)o

技术上的实现说起来也很简单,使用 AudioContext 来实现,音频文件是预先将 mp3 进行 base64 编码,使用时再转换成AudioContext的 buffer 数组来实现。

在做这个之前我对AudioContext一无所知,网上这类材料也很少,算是非常冷门了,主要是参考了webaudiofont这个项目来实现。

但是这里有个问题,微信小程序的AudioContext是自己实现的一套机制,与 web 标准的AudioContext不一样,而且微信小程序这里另外提供了一个WebAudioContext的,不过还是与 AudioContext 标准接口有些差异。

所以我这里也做了一些兼容上的处理。

顺便说一下,在代码中简单修改一下音源文件 0255_GeneralUserGS_sf2_file.js 为其他音源文件,也可以弹奏其他的乐器,比如钢琴唢呐之类的。

缺陷与失败的修复方案

这个小程序在自由模式、简单模式和灵魂模式下运行还算较好。

但是在真实手机上,自动模式是有问题的(在 PC 的开发者工具上自动模式没有问题)。

这个问题就是自动模式下,播放的声音有杂音。

自动模式尝试过两个方案:
一个方案使用的是 setTimeout,播放一个音调后再播放下一个音调,在 PC 上表现良好,在手机上会有延迟,杂音问题很小。
一个方案使用的是 queueWaveTable 自己的时间机制去播放,没有延迟,但是杂音问题严重。

由于这两套方案在开发者工具上都表现良好,只在真机上有问题,猜测只能是移动端性能不佳,或者是微信小程序的WebAudioContext实现有问题。

我实际发布的小程序采用的是第一种方案,不过第二种我也在代码中实现了,在代码中已注释。

其实我更倾向于第二种方案,因为 setTimeout 在真机上的延迟听起来像乱弹的,只是第二种的杂音问题实在太严重才不得不选第一种。

总的来说,在真机上,自动模式都不咋样。

总结

因为对这个方面实在没什么深入研究的欲望,随着兴趣减淡,也就偃旗息鼓了。

虽然自动模式确实存在问题,但是灵魂模式也不错了,也更好玩一点。

也算是做了一些东西的,如果有后来者可以解决这个问题,或者有感兴趣的可以在这个基础上再修复或者拓展吧。

这里给出开源的仓库地址:fake-guitarist