一、编曲部分
1.1一丢丢乐理知识
简单普及下乐理哈,这样便于读谱
钢琴谱一行分两个部分
上面一行用右手弹(主奏);
下面一行用左手弹奏(伴奏)。
1.2 关于节奏
(1)、主奏与伴奏中支持输入的35个音符:
倍低音: “1--” ~ “7--”,
低 音 : “1-” ~ “7-”
中 音 : “1” ~ “7”
高 音 : “1+” ~ “7+”
倍高音: “1++” ~ “7++”
(2)、分别在主奏(.note)与伴奏(.accompaniments)中输入需要自动弹奏的音符
① 每个音符之间用空格隔开(任意多个空格,推荐每个音符包括空格共占用4个占位符,以便主奏和伴奏音符对齐)
② 输入字符"0",则会使音长额外延长一倍,可以理解为停顿;
③ 输入除了上面35个音符以及“0”以外的任意字符不会对弹奏起任何作用;
④ 如果需要换行填写,则需在上一行的末尾以及下一行的开头都加上空格;
(3)、音长里输入每两个音符之间的间隔时长,单位是毫秒(ms)
建议输入整片谱子的最短的间隔,其余更长的的间隔可以利用延时加倍解决
1.3实例练习
下面是上文中片段2里的一段旋律:
(1)确定最小时间间隔
5+5 67 1+2+ 3+4+ //主奏
5--0 2-0 7-0 00 //伴奏
(2)成品
将每个字符间加上空格
5+ 5 6 7 1+ 2+ 3+ 4+ //主奏
5-- 0 2- 0 7- 0 0 0 //伴奏
二、编码部分
1.创建一个maven项目。
2.pom.xml引入相关依赖
<!--工具库--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.4.3</version></dependency><!--播放mp3相关的包--><dependency><groupId>com.googlecode.soundlibs</groupId><artifactId>mp3spi</artifactId><version>1.9.5.4</version></dependency>
3.编写实现控制台输出的类
package com.zxm.play;
public class Animation extends Thread {/*** 音符*/private String[] notes;/*** 间隔时间(单位:毫秒)*/private int times;public Animation(int times) {this.times = times;}//设置音符public Animation loadNotes(String notes) {this.notes = notes.split(" ");return this;}//进程方法@Overridepublic void run() {try {int times = this.times;new Audio("audio/test.mp3").start();sleep(1000);int no = 1;
// System.out.print(no+": ");for (int i = 0; i < this.notes.length; i++) {if (notes[i].length() < 1) {continue;}//将【-、+】这两个字符替换成空String n = this.notes[i].replace("+", "").replace("-", "");if (n.equals("\n") || n.equals("\r")) {System.out.print("\n");no++;
// System.out.print(no+": ");continue;}switch (n) {case "0":System.out.print("_");break;case "1":System.out.print("▁");break;case "2":System.out.print("▂");break;case "3":System.out.print("▃");break;case "4":System.out.print("▄");break;case "5":System.out.print("▅");break;case "6":System.out.print("▆");break;case "7":System.out.print("▇");break;}System.out.print(" ");sleep(times);}} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
4.编写mp3播放相关的类
package com.zxm.play;import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import cn.hutool.core.io.resource.ResourceUtil;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;public class Audio {private static InputStream is;private Player player;ExecutorService service = Executors.newCachedThreadPool();public Audio(String path) {is = ResourceUtil.getStream(path);try {player = new Player(is);} catch (JavaLayerException e) {e.printStackTrace();}}public void start() {service.submit(() -> {try {player.play();} catch (JavaLayerException e) {}});}
}
5.编写处理数字谱的类
package com.zxm.play;public class AudioPlay extends Thread {/*** 音符*/private String[] notes;/*** 间隔时间(单位:毫秒)*/private int times;/*** 有参构造器*/public AudioPlay(int times) {this.times = times;}/*** 加载乐谱*/public AudioPlay loadNotes(String notes) {this.notes = notes.split(" ");return this;}/*** 演奏乐谱*/@Overridepublic void run() {try {int times = this.times;new Audio("audio/test.mp3").start();sleep(1000);//准备时间for (int i = 0; i < notes.length; i++) {if (notes[i].length() < 1) {continue;}switch (notes[i]) {case "1--":new Audio("audio/ll1.mp3").start();sleep(times / 2);break;case "2--":new Audio("audio/ll2.mp3").start();sleep(times / 2);break;case "3--":new Audio("audio/ll3.mp3").start();sleep(times / 2);break;case "4--":new Audio("audio/ll4.mp3").start();sleep(times / 2);break;case "5--":new Audio("audio/ll5.mp3").start();sleep(times / 2);break;case "6--":new Audio("audio/ll6.mp3").start();sleep(times / 2);break;case "7--":new Audio("audio/ll7.mp3").start();sleep(times / 2);break;case "1-":new Audio("audio/l1.mp3").start();sleep(times / 2);break;case "2-":new Audio("audio/l2.mp3").start();sleep(times / 2);break;case "3-":new Audio("audio/l3.mp3").start();sleep(times / 2);break;case "4-":new Audio("audio/l4.mp3").start();sleep(times / 2);break;case "5-":new Audio("audio/l5.mp3").start();sleep(times / 2);break;case "6-":new Audio("audio/l6.mp3").start();sleep(times / 2);break;case "7-":new Audio("audio/l7.mp3").start();sleep(times / 2);break;case "1":new Audio("audio/m1.mp3").start();sleep(times / 2);break;case "2":new Audio("audio/m2.mp3").start();sleep(times / 2);break;case "3":new Audio("audio/m3.mp3").start();sleep(times / 2);break;case "4":new Audio("audio/m4.mp3").start();sleep(times / 2);break;case "5":new Audio("audio/m5.mp3").start();sleep(times / 2);break;case "6":new Audio("audio/m6.mp3").start();sleep(times / 2);break;case "7":new Audio("audio/m7.mp3").start();sleep(times / 2);break;case "1+":new Audio("audio/h1.mp3").start();sleep(times / 2);break;case "2+":new Audio("audio/h2.mp3").start();sleep(times / 2);break;case "3+":new Audio("audio/h3.mp3").start();sleep(times / 2);break;case "4+":new Audio("audio/h4.mp3").start();sleep(times / 2);break;case "5+":new Audio("audio/h5.mp3").start();sleep(times / 2);break;case "6+":new Audio("audio/h6.mp3").start();sleep(times / 2);break;case "7+":new Audio("audio/h7.mp3").start();sleep(times / 2);break;case "1++":new Audio("audio/hh1.mp3").start();sleep(times / 2);break;case "2++":new Audio("audio/hh2.mp3").start();sleep(times / 2);break;case "3++":new Audio("audio/hh3.mp3").start();sleep(times / 2);break;case "4++":new Audio("audio/hh4.mp3").start();sleep(times / 2);break;case "5++":new Audio("audio/hh5.mp3").start();sleep(times / 2);break;case "6++":new Audio("audio/hh6.mp3").start();sleep(times / 2);break;case "7++":new Audio("audio/hh7.mp3").start();sleep(times / 2);break;case "0":sleep(times / 2);break;default:continue;}sleep(times / 2);times = this.times;}} catch (Exception e) {throw new RuntimeException(e);}}}
6.编写乐曲demo
package com.zxm.musicList;import com.zxm.play.Animation;
import com.zxm.play.AudioPlay;/*** @author :silencezheng*琴谱url:http://www.ktvc8.com/mobile/833116_1.html* 《遇见》————孙燕姿*/
public class YuJian {public static void main(String[] args) {//伴奏(太难了,看不懂,需要的话可以自己扒谱补全)String sub = " 0 0 0 0 1- 5 0 0 7- 5 0 0 6- 3 6 0 0 0 0 4- 1 4 0 3- 1 3 0 \n" +" 2- 6- 2 0 5-- 2- 5- 1- 5- 1 5- 7-- 5- 7- 5- 6-- 3- 6- 3- 5-- 3- 5-3- \n" +" ";//主奏String main = " 0 0 0 5+ 3+ 3+ 0 5+ 2+ 2+ 0 5+ 1+ 1+ 0 0 1+ 3 5 1+ 1+ 0 5+ 1+ 1+ 0 1+ 5+ \n" +" 5+ 0 0 4+ 5+ 3 0 4 3 0 5 0 6 0 7 0 7 0 1+ 0 2+ 0 3+ 0 \n" +" 3+ 0 0 1+ 1+ 0 5 0 0 5 3 3 0 5 2 2 0 3 2 \n" + //听见冬天的离开" 2 1+ 0 1 1 7- 6- 7- 1 7- 7- 1 2 3 3 0 0 0 0 5 3 \n" + //我在某年某月 醒过来" 3 0 5 2 2 0 3 2 2 1+ 0 1 1 7- 6- 7- 1 7- 7- 1 2 1 \n" + //我想 我等 我期待 未来却不能因此安排" 4 3 2 1 5- 5 3 3 0 5 2 2 0 3 2 2 1+ 0 0 1 1 7- \n" + //阴天 傍晚 车窗外" 6- 7- 1 7- 7- 1 2 3 3 0 0 5 3 3 0 5 2+ 2+ 1+ 0 7 \n" + //未来有一个人在等待 向左向右向前看" 1+ 0 0 0 1 7- 6- 7- 1 7- 7- 1 2 1 \n" + // 爱要拐几个弯才来" 1 0 0 0 5+ 6+ 7+ 1++ 0 7+ 1++ 7+ 6+ 5+ 4+ 5+ 0 7 \n" + //我遇见谁 会有怎样的对白" 5+ 1+ 0 2 3 4 0 3 4 5 1 2 3 \n" + //我等的人 他在多远的未来" 3 3+ 0 3 5 6 7 1+ 0 7 1+ 2+ 1+ 2+ 3+ 3+ 5+ \n" + //我听见风来自地铁和人海" 0 0 1 2 3 4 0 3 4 3 2 1 7- 1 0 0 \n" + //我排着队 拿着爱的号码牌" 0 5+ 3+ 5 3+ 2++ 5+ 3+ 5 3+ 2++ 5+ 3+ 6 3+ 2++ 5+ 3+ 6 7 1+ 6+ 2+ 0 0 \n" +" 3 1+ 2++ 3++ 2++ 1++ 2 1+ 7- 5- 7- 7- 0 0 6- 5- 6- 7- 2 2 4 \n" +" 3 0 0 5 3 3 0 5 2 2 0 3 2 2 1+ 0 0 1 1 1 7- \n" + //阴天 傍晚 车窗外 未来有一个人在等待" 6- 7- 1 7- 7- 1 2 3 3 0 0 5 3 3 0 5 2+ 2+ 1+ 0 7 \n" + //向左向右向前看" 1+ 0 0 0 1 7- 6- 7- 1 7- 7- 1 2 1 \n" + //爱要拐几个弯才来" 1 0 0 5 6 7 1+ 0 7 1+ 7 6 5 6 6 5+ 5 1 0 2 3 4 0 3 4 5 1 2 3 \n" +//我遇见谁 会有怎样的对白 我等的人 他在多远的未来" 3 3+ 0 3 5 6 7 1+ 0 7 1+ 2+ 1+ 2+ 3+ 3+ 5+ \n" +//我听见风来自地铁和人海" 0 0 1 2 3 4 0 3 4 3 2 1 7- 1 0 0 \n" + //我排着队 拿着爱的号码牌" 1 0 0 5 6 7 1+ 0 7 1+ 7 6 5 6 6 5+ 5 1 0 2 3 4 0 3 4 5 1 2 3 \n" + //我往前飞 飞过一片时间海 我们也曾在爱情里受伤害" 3 3+ 0 3 5 6 7 1+ 0 7 1+ 2+ 1+ 2+ 3+ 3+ 5+ \n" +//我看着路 梦的入口有点窄" 0 0 1 2 3 4 0 3 4 3 2 1 7- 1 0 0 \n" + //我遇见你是最美丽的意外" 5 6 7 1+ 0 7 1+ 7 6 5 4 5 \n" + //总有一天 我的谜底会揭开"0 0 0 4 3 1 6- 5- 4- 3- 0 0 0 \n";// 播放new AudioPlay(320).loadNotes(main).start();//new AudioPlay(320).loadNotes(sub).start();//控制台打印new Animation(320).loadNotes(main).start();}
}
原文链接:https://blog.silencezheng.cn/articles/91