我们使用简单的开发工具 aardio ,体积只有几 MB,下载打开就可以编程了,不需要任何复杂的配置。
使用 aardio 新建一个源码文件:
输入以下代码,点击「运行」按钮合成并播放乐曲:
import sys.midiOut;
//打开播放设备
var midiOut = sys.midiOut();
//播放简谱
midiOut.play("
两只老虎,
1__,2__,3__,1__,
两只老虎,
1__,2__,3__,1__,
跑得快,
3__,4__,5__,__,
跑得快,
3__,4__,5__,__,
一只没有耳朵,
5_,6_,5_,4_,3__,1__,
一只没有尾巴,
5_,6_,5_,4_,3__,1__,
真奇怪,
2__,'5__,1__,__
");
上面的编程记谱法基于简谱记号设计。
中音使用简谱记号:
"1,2,3,4,5,6,7"
高音在后面加一个单引号:
"1',2',3',4',5',6',7'"
低音在音符前面加一个单引号:
"'1,'2,'3,'4,'5,'6,'7"
所有音符以逗号分开,忽略空格、制表符、换行等。
前面加负号表示消音(停止演奏指定音符),例如:
"-5,-'5"
用下划线表示一个延时单位(默认为 250 毫秒 ),前面的音符(或下划线)与后面的下划线可以连起来写,例如:
"5___,5___"
记谱时可以直接调用 midiOut 的成员函数,函数名后必须有括号 () 且必须有参数,例如:
"pitchBend(0.6),1__,2__,3__"
pitchBend 函数用于弯音,参数为表示百分比的小数,0 ~ 0.5 为向下弯音,0.5 ~ 1 为向上弯音。更多可用函数请参考库函数文档。
其他数值表示延时,其他字符串表示字幕。
下面是一个小例子:
import sys.midiOut;
var midiOut = sys.midiOut();
//播放简谱
midiOut.play("
1,150,
pitchBend(0.6), 弯音,
500, 延时 500 毫秒,
-1,停(音符前加负号表示消音)
1000
");
我们学习一下怎么翻译简谱,先找个简谱:
4/4 表示以四分音符为一拍,每小节有 4 拍。那么我们用 2 个下划线表示一拍(也就是 500 毫秒 ),那么 上面的
我们翻译为代码:
1__,2__,3__,1__,
再看下面的简谱:
这上面的短横线为增时线,表示增加一拍(这里是 500 毫秒,代码里就是增加 2 个下划线 ),所以上面的简谱翻译为代码就是:
3__,4__,5__,__,
然后我们再看简谱:
音符下面的横线是减时线,也就是由一拍减为半拍(这里是 250 毫秒,代码里用一个下划线表示),所以上面的简谱翻译为代码就是:
5_,6_,5_,4_,3__,1__,
最后生成完整源代码如下:
import sys.midiOut;
//打开播放设备
var midiOut = sys.midiOut();
//播放简谱
midiOut.play("
1__,2__,3__,1__,
1__,2__,3__,1__,
3__,4__,5__,__,
3__,4__,5__,__,
5_,6_,5_,4_,3__,1__,
5_,6_,5_,4_,3__,1__,
2__,'5__,1__,__
");
要特别注意上面有一个低音 '5,音符前面加个单引号表示低音。
midiOut.play 函数可选用第 2 个参数指定音符 1 对应的 SPN 音名( 可用音名在 sys.midiOut.notes 名字空间定义 ),默认值为 "C4"。可选用第 3 个参数指定单个下划线对应的延时单位(默认为 250 毫秒 )
我们将上面示例的音符 1 改为 "E4" (其他数字音符会自动调整音高),一个延时单位改为 125 毫秒(加快一倍),代码如下:
import sys.midiOut;
//打开播放设备
var midiOut = sys.midiOut();
//播放简谱
midiOut.play("
两只老虎,
1__,2__,3__,1__,
两只老虎,
1__,2__,3__,1__,
跑得快,
3__,4__,5__,__,
跑得快,
3__,4__,5__,__,
一只没有耳朵,
5_,6_,5_,4_,3__,1__,
一只没有尾巴,
5_,6_,5_,4_,3__,1__,
真奇怪,
2__,'5__,1__,__
","E4",125);
请运行一下,听一听有什么区别。
下面我们再小小改进一下,播放音乐时在桌面上显示漂亮的歌词。
源码如下:
//创建桌面歌词窗口
import win.util.lyric;
var lyric = win.util.lyric();
lyric.show();
//打开播放设备
import sys.midiOut;
var midiOut = sys.midiOut();
//定义显示歌词的函数
midiOut.log = function(str){
lyric.text = str;
}
//播放简谱
midiOut.play("
两只老虎,
1__,2__,3__,1__,
两只老虎,
1__,2__,3__,1__,
跑得快,
3__,4__,5__,__,
跑得快,
3__,4__,5__,__,
一只没有耳朵,
5_,6_,5_,4_,3__,1__,
一只没有尾巴,
5_,6_,5_,4_,3__,1__,
真奇怪,
2__,'5__,1__,__
");
按「运行」按钮,显示效果如下:
下面创建独立线程合成并播放音乐,源码:
//合成并输出音乐
import win.util.lyric;
var lyric = win.util.lyric();
lyric.show();
//创建独立线程
thread.invoke( function(lyric){
import sys.midiOut;
var midiOut = sys.midiOut();
//指定字幕回显函数
midiOut.log = function(v) lyric.text = v;
midiOut.play("
两只老虎,
1__,2__,3__,1__,
两只老虎,
1__,2__,3__,1__,
跑得快,
3__,4__,5__,__,
跑得快,
3__,4__,5__,__,
一只没有耳朵,
5_,6_,5_,4_,3__,1__,
一只没有尾巴,
5_,6_,5_,4_,3__,1__,
真奇怪,
2__,'5__,1__,__
");
lyric.close();
},lyric);
win.loopMessage();
编程记谱时可使用 sys.midiOut.notes 名字空间指定的所有音名,这些音名使用科学音高记号(Scientific pitch notation)。
音名与音符的对应关系如下:
当然音名与唱名的对应关系可以变更,这里先不用管这些。音名后面的数值越大表示越高的音,例如 C4( 中央C ,简谱中的 1 ) 高八度就是 C5( 高音 do,简谱 1 上面加一点),低八度的音就是 C3 ( 低音 do,简谱 1 下面加一点)。
注意:
SPN 音名中的 -1 省略
SPN 音名中的升号 ♯(Sharp) 用小写 s 替代
例如:C-1♯ 略写为 Cs 。
示例:
import sys.midiOut;
var midiOut = sys.midiOut();
midiOut.play("
C4,_,_,D4,_,_,E4,_,_,C4,_,_,
C4,_,_,D4,_,_,E4,_,_,C4,_,_,
E4,_,_,F4,_,_,G4,_,_,_,_,
E4,_,_,F4,_,_,G4,_,_,_,_,
G4,_,A4,_,G4,_,F4,_,E4,_,_,C4,_,_,
G4,_,A4,_,G4,_,F4,_,E4,_,_,C4,_,_,
D4,_,_,G3,_, _,C4,
1000
");
也可以这样写:
import sys.midiOut;
//打开音名空间
namespace sys.midiOut.notes{
//记谱(这里下划线与音符不能连起来,也不能使用数字音符)
drm = {
"两只老虎",
C4,_,_,D4,_,_,E4,_,_,C4,_,_,
"两只老虎",
C4,_,_,D4,_,_,E4,_,_,C4,_,_,
"跑得快",
E4,_,_,F4,_,_,G4,_,_,_,_,
"跑得快",
E4,_,_,F4,_,_,G4,_,_,_,_,
"一只没有耳朵",
G4,_,A4,_,G4,_,F4,_,E4,_,_,C4,_,_,
"一只没有尾巴",
G4,_,A4,_,G4,_,F4,_,E4,_,_,C4,_,_,
"真奇怪",
D4,_,_,G3,_, _,C4,
//用下面的方式调用函数,小于等于 127 的延时必须调用 delay 函数
{"delay",1000}
}
}
var midiOut = sys.midiOut();
midiOut.play( sys.midiOut.notes.drm );
我们还可以选择不同的乐器,代码示例:
import sys.midiOut;
var midiOut = sys.midiOut();
//选择八音盒,参数为乐器编号
midiOut.changeInstrument(10);
在谱子中也可以切换乐器,例如:
import sys.midiOut;
var midiOut = sys.midiOut();
midiOut.play( "
changeInstrument(10),
1___,
2___,
3___,
" );