当前位置: 首页 > Web前端 > HTML5

程序+音乐:我的免费钢琴发展史

时间:2023-04-05 02:08:38 HTML5

原文链接讨厌996?ComeHere&Relax~最近用Vue+Tone.js做了一个钢琴web应用,命名为AutoPiano,生活就像音乐一样,欢快而自由。本文旨在作为项目的总结与分享~项目介绍AutoPiano是一款采用HTML5技术开发的在线钢琴应用,致力于提供一个优雅简洁的平台,让你在学习和工作之余享受钢琴与音乐之美.类似于Flash多年前开发的钢琴游戏,FreePiano只是改变了H5的技术,同时支持钢琴曲的自动播放功能。AutoPiano支持键盘按键和鼠标点击弹奏,按键上会有按键提示和音名提示。此外,AutoPiano还有教学功能,一种是快速上手,通过简单的乐谱按钮进行弹奏,另一种是弹奏范例,通过钢琴曲的自动播放达到示范的目的。目前这两个功能正在不断完善中,如下图所示:体验地址:http://crystalworld.gitee.io/...项目地址:https://github.com/WarpPrism/...像这样开发App需要乐理知识吗?当然。乐理基础知识还是要有的,比如CDEFGAB音名、五线谱、调式、节奏等等,还是要知道一点的。篇幅有限,这里就不展开讨论了。推荐两个网站:https://www.bilibili.com/vide...https://www.cnblogs.com/devym...剩下的就是编程知识,以及如何将乐理知识转化为程序逻辑。AutoPiano目前采用的技术架构是vue框架+tone.js。钢琴界面效果器是怎么写的?可以使用CSS或纹理。作者这里直接用css实现了。考虑到钢琴有黑键和白键,黑键和白键以7:5的比例有序排列,实现起来并不复杂。

=36&¬e.id<=40"@click="clickPianoKey($event,note.keyCode)">
.piano-wrap{宽度:90%;边距:20px自动;.piano-key-wrap{宽度:100%;背景:@dark;溢出:隐藏;位置:相对;.wkey{显示:内联块;宽度:2.775%;高度:100%;保证金:0自动;背景:线性渐变(白色10%,rgb(251、251、251)92%,rgb(220、220、220)93%,白色97%);边框:纯色1px@dark;边界半径:005px5px;位置:相对;&:active{背景:线性渐变(#eee10%,#ddd60%,#bbb93%,#ccc97%);}}.wkey-active{背景:线性渐变(#eee10%,#ddd60%,#bbb93%,#ccc97%);}.bkey-wrap{宽度:20%;高度:0;位置:绝对;顶部:0;}.bkey-wrap1{left:0;}.bkey-wrap2{left:19.5%;}.bkey-wrap3{left:39%;}.bkey-wrap4{left:58.3%;}.bkey-wrap5{left:77.7%;}.bkey{显示:内联块;宽度:10%;高度:70%;背景:线性渐变(#00010%,rgb(86、86、86)85%,#00090%);边界半径:003px3px;位置:绝对;顶部:0;溢出:隐藏;&:active{背景:线性渐变(rgb(86,86,86)10%,#00090%,#222100%);}}.bkey-active{背景:线性渐变(rgb(86、86、86)10%,#00090%,#222100%);}.bkey:nth-child(1){left:9%;}.bkey:nth-child(2){left:23%;}.bkey:nth-child(3){left:50%;}.bkey:nth-child(4){left:65%;}.bkey:nth-child(5){left:79%;}}}codepen上也有很多这样的例子可以参考,不一定要用上面的实现:https://codepen.io/search/pen...相信只要css变量和Value,能不能做一个更好的Piano界面如何实现单个音符的播放?实现音频播放最简单的方法是使用HTML5中的audio标签来触发音频的播放和暂停方法来控制音频。作者一开始就是这样认识的。////////为每个音符预先创建一个音频元素initAudioDom(){varvm=thisfor(leti=0;i`);}},//触发音频元素的播放playNote(url){varvm=thisif(!url||typeofurl!='string')return;varaudios=$('.audioEle');for(leti=0;i-1){varcloneAudioNode=audio.cloneNode()cloneAudioNode.play()cloneAudioNode.remove()中断;}}}以上是我的第一个实现,即不同的音符触发播放不同的音频。后来可能是出于好奇,尝试了Tone.js,通过Tone.js+内置采样器实现了对音频播放更有效的控制。当然,它提供的很多复杂功能还没有用到。..//初始化合成器this.synth=SmapleLibrary.load({instruments:"piano"}).toMaster()//合成器触发音频释放playNote(notename='C4',duration='2n'){if(!this.synth)returnthis.synth.triggerAttackRelease(notename,duration);}好了,代码现在符合音乐美学和代码美学了,开心。当然,笔者也希望Tone.js能够快速完善中文文档,否则上手会非常困难。感兴趣的朋友可以先去其官网学习一下。关于自动播放钢琴曲的部分应该是整个应用开发难度最大的部分,因为音乐或者说乐谱本身就相当复杂。根据百度百科的描述,五线谱起源于希腊,经过几千年的完善才成为现在的五线谱。乐谱标准。编号符号的出现要晚得多,但它仍然很完整。可以说写法并不简单。作者的实现思路是以乐谱格式为载体,将乐谱转换成程序可以识别的格式,然后导入到程序中进行播放。这个可识别的格式如下,也是目前使用的:{name:'LittleStar',step:'C',speed:'100',playState:'',mainTrack:['1(1)','1(1)','5(1)','5(1)','6(1)','6(1)','5(2)','4(1)','4(1)','3(1)','3(1)','2(1)','2(1)','1(2)','5(1)','5(1))','4(1)','4(1)','3(1)','3(1)','2(2)','5(1)','5(1)','4(1)','4(1)','3(1)','3(1)','2(2)','1(1)','1(1)','5(1)','5(1)','6(1)','6(1)','5(2)','4(1)','4(1)','3(1)'、'3(1)'、'2(1)'、'2(1)'、'1(2)'、'1<(1)'、'1<(1)','5<(1)','5<(1)','6<(1)','6<(1)','5<(2)','4<(1)','4<(1)','3<(1)','3<(1)','2<(1)','2<(1)','1<(2)','5<(1)','5<(1)','4<(1)','4<(1)','3<(1)','3<(1)','2<(2)','5<(1)','5<(1)','4<(1)','4<(1)','3<(1)','3<(1)','2<(2)','1<(1))','1<(1)','5<(1)','5<(1)','6<(1)','6<(1)','5<(2)','4<(1)','4<(1)','3<(1)','3<(1)','2<(1)','2<(1)','1<(2)'],backingTrack:['1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','6>(0.5)','4>(0.5)','6>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','6>(0.5)','4>(0.5)','6>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','7>>(0.5)','5>(0.5)','2>(0.5)','5>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','3>(0.5)','5>(0.5)','1(0.5)','1>(0.5)','4>(0.5)','6>(0.5)','1(0.5)','1>(0.5)','3>(0.5)','5>(0.5)','1(0.5)','5>>(0.5)','7>>(0.5)','2>(0.5)','5>(0.5)','1>(0.5)','3>(0.5)','5>(0.5)','1(0.5)','1>(0.5)','4>(0.5)','6>(0.5)','1(0.5)','1>(0.5)','3>(0.5)','5>(0.5)','1(0.5)','5>>(0.5)','7>>(0.5)','2>(0.5)','5>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','6>(0.5)','4>(0.5)','6>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1>(0.5)','6>(0.5)','4>(0.5)','6>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','7>>(0.5)','5>(0.5)','2>(0.5)','5>(0.5)','1>(0.5)','5>(0.5)','3>(0.5)','5>(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75))','5(0.25)','3(0.5)','5(0.5)','1(0.75)','6(0.25)','4(0.5)','6(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75)','6(0.25)','4(0.5)','6(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','7>(0.75)','5(0.25)','2(0.5)','5(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75)','3(0.25)','5(0.5)','1<(0.5)','1(0.75)','4(0.25)','6(0.5)','1<(0.5)','1(0.75)','3(0.25)','5(0.5)','1<(0.5)','5>(0.75)','7>(0.25)','2(0.5)','5(0.5)','1(0.75)','3(0.25)','5(0.5)','1<(0.5)','1(0.75)','4(0.25)','6(0.5)','1<(0.5)','1(0.75)','3(0.25)','5(0.5)','1<(0.5)','5>(0.75)','7>(0.25)','2(0.5)','5(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75)','6(0.25)','4(0.5)','6(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','1(0.75)','6(0.25)','4(0.5)','6(0.5)','1(0.75)','5(0.25)','3(0.5)','5(0.5)','7>(0.75)','5(0.25)','2(0.5)','5(0.5)','1>(2)']}额,是不是很复杂臃肿。.它以简谱为载体,用特殊的符号标示音高和时长,从而生成mainTrack和backingTrack两条音轨,然后同步播放。这种实现方式虽然简单,但是却有很多致命的缺点:不兼容常见的计算机乐谱格式,比如musicxml,不能完全表现音乐的所有维度。例如,许多钢琴乐谱有两个以上的曲目,过于抽象和复杂,不切实际,难以制作这种可识别格式的音乐专业人士:你是什么?于是作者转而采用另一种实现思路,解析musicxml,但是这个过程费时费力。目前只完成了一半,部分细节还没有完全正确解决。如果读者有好的想法,可以在评论区留言讨论。欢迎投稿协作投稿码,直接PR投稿首页随机显示的歌词:https://github.com/WarpPrism/...投稿快速上手玩法:https://github.com/WarpPrism/…No想到短时间内有那么多星星(`·ω·′),吓得我晚上回去继续码字。..不过这个项目还不够完善,还在更新中,尤其是入门曲谱比较少,目前只有:小星星新年快乐因为爱看不见的翅膀蒲公英的约定主题曲《明天你好》青花瓷……”都是作者一一写的T_T,能力有限,知道的人就这么多,是时候见证社区的力量了。FORK时,请遵循GPL开源协议。最后贴出体验地址:http://crystalworld.gitee.io/...欢迎体验分享。解析musicxml的过程仍在进行中。如果有一天它成功了,将在样本表演中添加大量歌曲以供学习。如果失败了,那是因为生活阻碍了我的进步。..原创不易,转载分享请注明出处~