写在前面
最近听beyond乐队的《灰色轨迹》听上瘾了,300多遍,震惊!!尤其喜欢最后一分半钟的吉他solo,真可谓吉他没有酒,依然让我醉如老狗。。
翻了翻网上的视频,瞬间觉得单身20年的手速都望尘莫及~~
默默拿起尤克里里弹着儿歌《小星星》不禁老泪纵横。。我撅腚要学会首像样的曲子!
学什么好呢?琢磨半天灵光一闪,《士兵突击》中不是有段吉他弹奏的曲子,名字叫《前向きな乙女心》吗?
当初说了“如果学吉他也会是因为这首曲子吧”,想不到一语成谶,那就从它开始吧!!
上网搜关于这首曲的尤克里里四线谱,找不到,淘宝问客服客服说老师还没有录制关于这首的教学视频。。
我就听,这首时长1分42秒,觉得并不是很难,一边听一遍试,发现还是很简单的~~
3 3 4 5 2 1 5 1 3 3 2 1 2 5 3
3 3 4 5 2 1 5 1 3 5 4 3 2 1 1
到30秒后发现自己图样图森破,手速太慢试不出来了。。
怎么办呢?
第一个想到的是搜计算器,会发声的计算器,微博看到有人用5个相同的计算器弹《名侦探柯南》主题曲~太机智了~但是搜了一圈,已经快十点了,好多店铺客服都打卡下班了~
于是想网上有没有模拟音阶的软件呢?有,但是好多都是钢琴的,下载了一个貌似还带病毒,买了佛冷。并且钢琴和尤克里里音色还不大一样,就想能不能通过程序搞一些愉快的事情?
有人写了关于钢琴的程序,果然是一帮有理想的骚年,钢琴88键都能做出来,我这1234567i岂不是小儿科啊,说干就干!
步骤分解
1.一边弹一边用手机录音1234567i
没错,用手机。。音质差了点,不过听了一遍还在能忍受的范围。
2.音频截取
1234567i,8段短音频,每段大概2秒钟的样子,个别音长达4秒,不禁感叹这把琴的延音是真滴好,钱花哪哪值啊(¥2480 经费在燃烧.......)。
3.界面设计
界面两个框,上面一个框实时显示按键按下后的按键数值,下面框保留自己满意的音阶,clear按钮用于快速清除框内值
框下面1234567i按键阵列,先这样吧,丑是丑了点能用先。。
4.撸代码
采用HTML5,根据按键值,读取对应的音频文件
5.哦了
(这里有个问题, 播放按键由于js无法控制匀速, 播放暂时留了个bug, js如何实现sleep呢?欢迎留言)
置灰部分先忽略吧,搬完家抽时间再搞~
6.发布微信小程序
下一步准备将程序迁移至微信小游戏,之前是默认的“打飞机”,并未发布。这下把这个程序发布一下,手机上操作不是更方便吗?
微信小程序是js写,似乎更简单了~
按键图片
按键对应音频
编程,测试
发布小程序
关键代码
目录结构
index.html
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ukuleletitle>
<link rel="stylesheet" href="css/ukulele.css" />
<script type="text/javascript" src="js/ukulele.js" >script>
head>
<body>
<div align="center">
<h1>ukulele弹奏模拟器v1.0h1>
<table>
<tr>
<td align="right">
<textarea id="temp" class="textarea">textarea>
td>
<td align="left">
<input type="button" class="cls" onclick="resetTemp()" />
td>
tr>
<tr>
<td align="right">
<textarea id="replay" class="textarea">textarea>
td>
<td align="left">
<input type="button" class="cls" onclick="resetPlay()">
<input type="button" class="play" onclick="replay()" />
td>
tr>
table>
div>
<div align="center">
<h1>Key(1=do 2=re 3=mi 4=fa 5=so 6=la 7=xi 0=i)h1>
<audio src="mp3/1do.mp3" id="do" controls="controls" hidden="hidden">audio>
<audio src="mp3/2re.mp3" id="re" controls="controls" hidden="hidden">audio>
<audio src="mp3/3mi.mp3" id="mi" controls="controls" hidden="hidden">audio>
<audio src="mp3/4fa.mp3" id="fa" controls="controls" hidden="hidden">audio>
<audio src="mp3/5so.mp3" id="so" controls="controls" hidden="hidden">audio>
<audio src="mp3/6la.mp3" id="la" controls="controls" hidden="hidden">audio>
<audio src="mp3/7xi.mp3" id="xi" controls="controls" hidden="hidden">audio>
<audio src="mp3/ido.mp3" id="ido" controls="controls" hidden="hidden">audio>
<input type="button" class="key" id="97" onclick="press()" style="background-image: url(img/1.png);" />
<input type="button" class="key" id="98" onclick="press()" style="background-image: url(img/2.png);" />
<input type="button" class="key" id="99" onclick="press()" style="background-image: url(img/3.png);" />
<input type="button" class="key" id="100" onclick="press()" style="background-image: url(img/4.png);" />
<input type="button" class="key" id="101" onclick="press()" style="background-image: url(img/5.png);" />
<input type="button" class="key" id="102" onclick="press()" style="background-image: url(img/6.png);" />
<input type="button" class="key" id="103" onclick="press()" style="background-image: url(img/7.png);" />
<input type="button" class="key" id="96" onclick="press()" style="background-image: url(img/0.png);" />
div>
<div align="center">
<input type="button" class="demo" id="christmas" onclick="christmas()" style="background-image: url(img/christmas.png);" alt="圣诞歌"/>
<input type="button" class="demo" id="star" onclick="star()" style="background-image: url(img/star.png);" alt="小星星"/>
<input type="button" class="demo" id="bee" onclick="bee()" style="background-image: url(img/bee.png);" alt="小蜜蜂"/>
div>
body>
html>
ukulele.js
function press(){ var currentId = parseInt(event.currentTarget.id); ring(currentId); var yinjie = toYinjie(currentId); append(yinjie); } window.onkeydown = function(event){ var keyCode = event.keyCode; ring(keyCode); var arr = [97,98,99,100,101,102,103,96,49,50,51,52,53,54,55,48]; var boo = isInArray(arr, keyCode); if(boo){ var yinjie = toYinjie(keyCode); append(yinjie); } } function ring(value){ var targetId = toTargetId(value); var element = document.getElementById(targetId); keyDown(element); } function keyDown(element){ if(element!=null){ element.currentTime = 0; if(element.paused){ element.play(); } } } function resetTemp(){ document.getElementById("temp").value = ""; } function resetPlay(){ document.getElementById("replay").value = ""; } function append(value){ document.getElementById("temp").value += value; document.getElementById("replay").value += value; } function replay(){ var vals = document.getElementById("replay").value; // 自动演奏 间隔1s for(var i = 0; i < vals.length; i++){ var v = vals.charAt(i); var keycode = toKeycode(v); async function test(){ var temple=await sleep(1000); ring(parseInt(keycode)); return temple; } // ring(parseInt(keycode)); } } function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); } function isInArray(arr, value){ for(var i = 0; i < arr.length; i++){ if(value === arr[i]){ return true; } } return false; } function toKeycode(value){ var keycode = null; switch(value){ case "1": keycode = "97"; break; case "2": keycode = "98"; break; case "3": keycode = "99"; break; case "4": keycode = "100"; break; case "5": keycode = "101"; break; case "6": keycode = "102"; break; case "7": keycode = "103"; break; case "i": keycode = "96"; break; } return keycode; } function toYinjie(value){ var yinjie = null; switch(value){ case 49: case 97: yinjie = "1"; break; case 50: case 98: yinjie = "2"; break; case 51: case 99: yinjie = "3"; break; case 52: case 100: yinjie = "4"; break; case 53: case 101: yinjie = "5"; break; case 54: case 102: yinjie = "6"; break; case 55: case 103: yinjie = "7"; break; case 48: case 96: yinjie = "i"; break; } return yinjie; } function toTargetId(value){ var targetId = null; switch(value){ case 49: case 97: targetId = "do"; break; case 50: case 98: targetId = "re"; break; case 51: case 99: targetId = "mi"; break; case 52: case 100: targetId = "fa"; break; case 53: case 101: targetId = "so"; break; case 54: case 102: targetId = "la"; break; case 55: case 103: targetId = "xi"; break; case 48: case 96: targetId = "ido"; break; } return targetId; } // 圣诞歌 function christmas(){ } // 小星星 function star(){ } // 小蜜蜂 function bee(){ }
ukulele.css
h1{ color: blueviolet; } .textarea { width: 650px; height: 250px; background: rgba(255, 255, 255, 0); font-family: "arial, helvetica, sans-serif"; font-size: 48px; color: purple; border-color: pink; } .key{ width:100px; height:100px; background-size: 100% 100%; border-radius: 50px; background-color: pink; outline: none; } .cls , .play{ width: 86px; height: 86px; border-radius: 5px; background-color: deepskyblue; outline: none; } .cls{ background-image: url(../img/del.png); } .play{ background-image: url(../img/play.png); } .demo{ width: 130px; height: 100px; border-radius: 20px; background-color: pink; outline: none; } body { background-image: url(../img/bg.png); background-repeat: no-repeat; background-attachment: fixed; background-size: cover; }
代码已分别上传至github,喜欢的园友可以戳戳
简单感受一下~
https://xiguanchendian.github.io/ukulele/
以下是微信小程序识别码,欢迎试玩鸭~
感谢
-
java编写的钢琴键代码
-
HTML audio Element how to replay?
-
使用JS监听键盘按下事件(keydown event)
-
js控制html5 audio的暂停、播放、停止