录音/制作/创作 吉他 扩声技术 视频技术 作品展示 生活 信息 更多... | 音频应用专卖店
Sonar / Cakewalk

[教程] CAL编写教程(打造自己独特的MIDI系统)

( 90 )
 
[收藏]
-  第 4 页  -

1018
#46 15-2-24 16:35
希望前辈能够分享下您自己制作 的 CAL命令脚本~~~谢谢您

2559
#47 15-2-24 16:39
谢谢,学习

1158
#48 15-2-24 16:46

CAL教程04(实例讲解:初级一)

CAL编写的复杂程度,取决于需要实现的功能要求,对于一般的功能要求,编写是十分简单的。
我不知道别的语言编写时是什么情况,但CAL的编写,无非就是两个概念:

一:依次执行:
这个概念就是程序将依次读取指令,在这个读取过程中,CAL将依次完成编写者的指令要求。

二:假设执行:
这个概念本质上也很简单,
即——如果条件为真,则执行某指令,如果条件为假则执行另一个指令。
说得通俗易懂些,
就是:如果假设的条件成立,就执行某指令,否则执行另一个指令。

以上两种执行概念,在CAL中,时常是交叉出现的,不过大家不用紧张,
我们来举一些例子,大家就很容易理解并掌握了,很简单的,一学就会。
我们由浅入深,先来一些十分简单,但在制作中却不可或缺的CAL……

——————————————————————————————————————————————————————
CAL的基本执行格式:
CAL指令之间,是由空格或提行来表示划分的,
指令中间不能出现空格;回车,否则系统会将其判断成两段指令。
在编写时,有三个编写方式:
1、下载软件:“CW 9”,打开软件后,点击新建,选择“CAL Script”,在弹出的CAL编写窗中编写。
2、下载专门的CAL编辑器进行编写。
3、直接用TXT文件进行编写,编写完成后保存,并将保存后的TXT文件后缀名改为“cal”即可。
以上三种方法中,最不好用的是第3种方法,
因为编写过程中没有任何后括号提示,也没有自带CAL指令,很麻烦,且容易写错。

第2种方法看起来不错,专门的编辑器中自带了所有的CAL指令,可以在编写过程中直接调用。
但是,它也没有后括号提示,编写起来挺伤精力的。

第1种方法,用CW9直接编写,虽然没有自带CAL指令,
但这些指令在我前边提供的表格中已经全部有了,大家可以拷贝来直接使用。
最关键的是CW9的CAL编辑器带有反括号提示功能,
大家在编写时,先打上一个前括号,然后在打后括号时,
系统会提示此后括号对应的前括号是哪一个。
这非常重要!这非常重要!这非常重要!!!!!!
加上编写时,是在CW9的软件内编写,所以我们可以同时新建一个MIDI工程,
一边编写CAL,一边在MIDI钢琴窗中尝试CAL是否达到了预期的效果。

下面开始我们的实战吧:
——————————————————————————————————————————————————————

范例01:
音符向上移动一个键位(小二度音程)
写法1:
(do
(forEachEvent
  (++ Note.Key)
)
)
写法2:
(do
(forEachEvent
  (+= Note.Key 1)
)
)
以上CAL语句翻成中文来表达如下:
(执行
 (对每一个事件执行一次
  (音高键位增加1)
 )

这段语句的意思就是,对框选的所有事件中的每一个事件(无论它是音符;音色;控制器;弯音……)
都执行一次音高键位+1的操作。
因为只有音符才存在音高概念,所以当CAL程序对所框选的所有事件依次进行音高+1的操作时,
只有音符才会产生有效回应,其它事件不会发生变化。

——————————————————————————————————————————————————————
是不是一目了然,上面我用不同的颜色表达了不同指令,以及这些指令结束时所对应的后括号。
后括号十分重要,它是其对应的指令结束的标致,如果没打后括号,或是后括号打错了位置,系统就会出错并停止。
有了上例的经验,我们再来写一个音符上翻八度的CAL,就十分简单了。
——————————————————————————————————————————————————————

范例2:
音符向上移动12个键位(八度音程)
(do
(forEachEvent
  (+= Note.Key 12)
)
)

以上CAL语句翻成中文来表达如下:
(执行
 (对每一个事件执行一次
  (音高键位增加12)
 )



——————————————————————————————————————————————————————
上诉内容主要是音符上下移动的编写方式,可以看出遍历指令:forEachEvent 是十分常用的,
事实上但凡是需要对选中的事件进行处理的CAL,都必须用到它,
只有它才能给程序发出对每一个被选事件进行一次下列操作的执行信号。
所以它十分的重要,大家要牢记它的编写格式与作用。
——————————————————————————————————————————————————————

另外,我们还用到了音高变量:Note.Key
对于这种变量的名称,大家直接死记就行(当然,有指令列表的情况下,连死记也不用了。)
要改变音高,本质上就是改变音高变量——Note.Key。
只要让Note.Key这个变量,结合运算符发生变化,就能对音高实现各种不同的需要。
————————————————————————————————————————————————————————————
上例中用到了运算符“++”,也用到了“+=”,
二者的区别在于,“++”每运行一次,只能给变量增加1的值,
而“+=”则可以在每次运行时增加不同的值。
上例中我们将音符升高一个小二度,也将音符升高过一个八度,
所以我们当然可以将音符升高一个五度,三度,两个八度……任意多……
至于五度,三度……是多少个键位差,这正好是音乐人的强项,我就不多嘴了。
如果希望使音高向下移动,则会用到“--”或“-=”这两个指令,大家举一反三喽。
————————————————————————————————————————————————————————————
另一个需要举一反三的,就是力度,我们上面已经知道,要改变音高,就是改变音高变量——Note.Key。
那么要改变力度,当然就是改变力度变量——Note.Vel。所以,继续反三喽……


如果再旁通反三一下,当然就是控制器值——Control.Val,弯音值——Wheel.Val
编写方式也是一模一样的,大家只需要将其中的关键变量改为相应的变量即可。



————————————————————————————————————————————————————————————
十分简单是吧,这是音符;力度;弯音;控制器值……等等发生纵向增减效果的编写方式,
那么横向左右移动的方式呢?
是的,大家应该能分析出来了,编写方式几乎与上面的例子一模一样,
唯一不同的,就是将音高变量改变,改为事件位置变量——Event.Time 即可,
只要让这个位置变量发生增减,事件的位置就自然会发生左右移动的效果。

————————————————————————————————————————————————————————————

这里举一个需要一点小逻辑的CAL编写,即:横向移动音尾,或音头。
注意,这与移动整个音符是不一样的概念,
我们需要移动音头时,希望音尾位置保持不变,而移动音尾时,需要音头位置不变。
仔细看过我在前边放出的CAL列表的朋友应该发现了,
CAL有事件位置变量——Event.Time,也有音符长度变量——Note.Dur
但是却没有“音头位置变量”与“音尾位置变量”
所以,要实现只移动音头或音尾的效果,就需要小小的绕一个圈。
如下:
————————————————————————————————————————————————————————————


范例3:
音头左移1TK:(音尾保持不动)
写法1:
(forEachEvent
(do
  (-- Event.Time)
  (++ Note.Dur)
)
)
写法2:
(forEachEvent
(do
  (-= Event.Time 1)
  (+= Note.Dur 1)
)
)
翻译过来如下:
(对每一个事件执行一次
 (执行
  (位置减1TK)
  (音符长度加1TK)
 )

————————————————————————————————————————————————————————————
上例中要特别注意的是那个“do”指令,为什么要加这个指令呢?
这是因为遍历指令——forEachEvent 的格式限制所决定的,
遍历指令只允许在该指令后跟写一条指令来执行,
而我们这次是要对每一个事件都同时执行一次两条指令,
所以我们需要将这两条指令,通过“do”来打包,
使两条指令被当作一条指令来执行。
————————————————————————————————————————————————————————————
CAL的变量类型很少,在很多情况下,我们为了实现更多更疯狂的目的,
在逻辑上需要像上例那样转个圈,再圈中套圈,再多套几层圈……来达到最终的目的。
这就需要大家多多练习,只要理解并习惯了CAL的编写精髓,你就什么都干得出来……
————————————————————————————————————————————————————————————
今天这贴就写到这里,希望大家多多练习,有什么需要实现的目的,
多想想这个目的与哪些音乐元素有关,这些元素在CAL中是由什么变量来表达的,
然后尝试着编写一下。不要怕出错,出错就是最强大的老师,
它教会我们哪些方向是去不得的死胡同,错得越多,我们离正确的方向就越近,
当你尝试了所有的错误,你的手随意的一指,那都是正确的方向。
实在解决不了,可以将你编写的语句发上来进行交流解决。
————————————————————————————————————————————————————————————
下一贴,——插入指令编写方式。
待续……

[ 本帖最后由 溺水鱼 于 15-2-25 13:27 编辑 ]
观众反应
mao

1158
#49 15-2-24 17:19

回复 qq77547123 在 #24 的 pid=4403131 的贴子

是这样的,不论是CW9,还是SONAR数字系列,或是SONAR X系列,在文件夹设定菜单中,都有CAL的文件包路径设定项。
将你在网上下载的CAL,或是自己编写的CAL全部放在某个文件包中,
再在MIDI宿主的文件夹路径设定去把这个包的路径填入CAL一项的路径中去。
接下来,你进入热键设定面版中去,在右侧的功能栏中,你就可以看见那些CAL了,
之后你就可以把CAL指派到热键上去了。
很多功能简单,但在操作中会成千上万次使用的CAL,是一定要指派为热键的,
在热键中交叉使用,会产生完全不同的输入概念……
否则还不如直接鼠标操作了。

1158
#50 15-2-24 17:23

回复 qq77547123 在 #24 的 pid=4403131 的贴子

另外,我这次发放这个CAL教程,主要目的是希望大家学会它的编写,这样大家才能针对自己正在面临的业务进行CAL的编写,简化自己的MIDI操作。
之后的教程中都是以实例为主的,我不只是会放上一些自己编写的CAL,
也会告诉大家我是怎么编写的,我编写时的目的,以及如何设计出这样的功能。

2583
#51 15-2-24 17:55
不知是哪位前辈,可惜卡拉业务也将由中国到印尼了,就像当初从韩国到中国一样

1158
#52 15-2-24 18:01

补充一个CAL热键设置!

CW9与SONAR8.5几乎一样,方法如下:
1:进行CAL存放路径设置



将CAL一栏中的路径设置为存放CAL文件的目录路径。



2:进行热键设置



在设置面板中,左侧是热键,右侧是功能项(也包括CAL文件)
同时选中左侧的热键与右侧的CAL文件后,一定要记得点一下“Bind”按钮,
如此才能成功的绑定热键与CAL文件。每设置一个热键都要绑定一次。



完成!

—————————————————————————————————————————————————

SONAR X3,其实与之前版本也一样,只是菜单路径变了:

1:进行CAL存放路径设置



将CAL一栏中的路径设置为存放CAL文件的目录路径。



2:进行热键设置




在设置面板中,左侧是热键,右侧是功能项(也包括CAL文件)
同时选中左侧的热键与右侧的CAL文件后,一定要记得点一下“绑定”按钮,
如此才能成功的绑定热键与CAL文件。每设置一个热键都要绑定一次。

—————————————————————————————————————————————————
OK,现在,你的CAL文件就可以由热键控制了……

[ 本帖最后由 溺水鱼 于 15-2-24 18:09 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
观众反应
:谢谢老师!谢谢分享!
:谢谢前辈
mao

1158
#53 15-2-24 19:44

回复 黄黄 在 #28 的 pid=4403167 的贴子

CAL 针对的业务,远不止扒带业务,了解了它的编写,在编曲方面,特别是层出不穷的音源操作,都需要大家不停改变写入方式,有了CAL,任何操作都可以转化为热键快速完成,还是很方便的。至于OK业务的去向,这个还与一个国家的经济状态有关,说不清楚也看不清,咱们还是不要太多的去考虑这个问题,总之,多学习各方面的东西,有准备就不会死在一棵树上的。

766
#54 15-2-24 20:26
怎么没人讨论一下Ableton Live的MAX 7语言?和CAL 有一比吗?哪个更好用,更强大?

1158
#55 15-2-25 11:16

回复 lhls 在 #30 的 pid=4403250 的贴子

一个是用于现场演出用的,本质上是一个带有简单演奏并可将演奏作为LOOP回放的强大软件。一个是用于音乐制作方面的,本质上是结合MIDI制作,效果器、插件调整,后期缩混于一身的强大软件。
Ableton Live 是电子音乐风格的现场控制型软件,而如SONAR这类软件是所有音乐风格的音乐制作工作站。
前者的发展方向是更方便,更灵活的进行音乐素材现场控制。后者的发展方向就是音乐制作。
两个软件完全不在一类用途上,无法作比较的。

766
#56 15-2-25 12:07

回复 lhls 在 #30 的 pid=4403250 的贴子

大师,多谢!

1158
#57 15-2-26 15:37

CAL教程05(实例讲解:初级二)

[size=16.3799991607666px]
[size=16.3799991607666px]本贴讲一讲“插入”指令与“输入”指令的用法。
[size=16.3799991607666px]—————————————————————————————————————————————————

[size=16.3799991607666px]插入指令:

[size=16.3799991607666px]本指令一共有四条,本质上就是一条,
[size=16.3799991607666px]即:
[size=16.3799991607666px](insert Event.Time Event.Chan NOTE Note.Key Note.Vel Note.Dur)
[size=16.3799991607666px](insert Event.Time Event.Chan PATCH Patch.Num Patch.Bank)
[size=16.3799991607666px](insert Event.Time Event.Chan CONTROL Control.Num Control.Val)
[size=16.3799991607666px](insert Event.Time Event.Chan WHEEL Wheel.Val)
[size=16.3799991607666px]

[size=16.3799991607666px]我们可以看出,红色字符区,四条语句无论是指令名,还是格式,都是一模一样的,
[size=16.3799991607666px]因为无论我们插入什么类型的事件,都必须涉及到三个相同的概念,
[size=16.3799991607666px]即:
[size=16.3799991607666px]插入(insert):给出进行插入的操作命令。
[size=16.3799991607666px]位置(Event.Time):需要将事件插入在什么位置。
[size=16.3799991607666px]通道(Event.Chan):需要将事件插入在什么通道。
[size=16.3799991607666px](通道这一项其实没什么作用,在插入过程中,系统只会将事件插入正在处理的事件相同的通道,
[size=16.3799991607666px]或插入当前被激活的轨道。所以,这一项一般不用去改变。)

[size=16.3799991607666px]后面的内容,本质上也是一样的,只是因为蓝色字符所代表的事件类型不一样,
[size=16.3799991607666px]所以后面的细节就发生了相应的变化,[size=16.3799991607666px]比如:
[size=16.3799991607666px]NOTE(音符事件):
[size=16.3799991607666px] 既然是音符,与它对应的细节自然只能是——音高Note.Key,力度Note.Vel,时值Note.Dur。
[size=16.3799991607666px]PATCH(音色事件):
[size=16.3799991607666px] 与它对应的细节就是——音色号Patch.Num,库号Patch.Bank。
[size=16.3799991607666px]CONTROL(控制器事件):
[size=16.3799991607666px] 对应的是——控制器号Control.Num,控制器值Control.Val。
[size=16.3799991607666px]WHEEL(弯音事件):
[size=16.3799991607666px] 对应的就只有一个——弯音值Wheel.Val。
[size=16.3799991607666px]

[size=16.3799991607666px]需要注意的是,上面提到的四条插入语句,大家可以直接建立一个表格,将四条语句分别拷贝在表格中,
[size=16.3799991607666px]当我们需要插入什么类型的事件时,就拷贝某一整条语句来用。
[size=16.3799991607666px]下面,我们就以编写一个需要用到插入语句的CAL实例,来实际运用插入指令。

[size=16.3799991607666px]—————————————————————————————————————————————————

[size=16.3799991607666px]例1:为被选音符向上添加一个八度音

[size=16.3799991607666px](forEachEvent
[size=16.3799991607666px] (insert Event.Time Event.Chan NOTE (+ Note.Key 12) Note.Vel Note.Dur)
[size=16.3799991607666px])
[size=16.3799991607666px]

[size=16.3799991607666px]这个例子中,大家可以看出,我们只是修改了一个指令项,[size=16.3799991607666px]即:将音高变量 Note.Key,修改成了:(+ Note.Key 12)
[size=16.3799991607666px]为什么修改成(+ Note.Key 12)呢?[size=16.3799991607666px]这是因为CAL在执行时,程序会自动依照时间,由前至后的对被选事件进行扫描,
[size=16.3799991607666px]所有的变量值,都将自动默认为当前被扫描的事件属性。
[size=16.3799991607666px]比如我们框选了一段音符,当程序扫描到第一个音符时,[size=16.3799991607666px]与此音符相关的属性就将被赋予给相关的变量,
[size=16.3799991607666px]即:起始位置,通道号,音高,力度,时值,都会变成正在被扫描的音符所对应的值。
[size=16.3799991607666px]所以,我们要给被选音符添加一个八度音,本质上就是插入一个音符,
[size=16.3799991607666px]插入的音符只有音高是在被选音符的基础上增加了12个半音,其它的所有属性都与被选音符一样,
[size=16.3799991607666px]于是在插入时,就只需要使音高变量在自身基础上加12,而其它变量则不作修改。

[size=16.3799991607666px]在使用遍历指令(forEachEvent)时,大家一定要注意它的格式,
[size=16.3799991607666px]即:在遍历指令的后面,只能有一个操作指令,其后必须马上由后括号结束,
[size=16.3799991607666px]如果打破这个格式,程序则会报错停止。
[size=16.3799991607666px]由此,
[size=16.3799991607666px]大家一定会产生一个问题,如果我们要在遍历指令(forEachEvent)后,执行N多个指令怎么办?
[size=16.3799991607666px]很简单,利用“do”指令进行打包,将N多条指令被封装成一条“do”指令即可。
[size=16.3799991607666px]下例中,我们就来实现这个用法。

[size=16.3799991607666px]—————————————————————————————————————————————————
[size=16.3799991607666px]
[size=16.3799991607666px]例2:为被选音符,向上同时添加一个五度音,一个八度音

[size=16.3799991607666px](forEachEvent
[size=16.3799991607666px] (do
[size=16.3799991607666px]  (insert Event.Time Event.Chan NOTE (+ Note.Key 7) Note.Vel Note.Dur)
[size=16.3799991607666px]  (insert Event.Time Event.Chan NOTE (+ Note.Key 12) Note.Vel Note.Dur)
[size=16.3799991607666px] )
[size=16.3799991607666px])

[size=16.3799991607666px]此例中,我们在遍历指令(forEachEvent)后,执行了两条插入语句,
[size=16.3799991607666px]因为用到了“do”指令进行打包,所以蓝色区域中的指令,无论有多少条,都将被视为一条“do”指令被依次执行。
[size=16.3799991607666px]大家现在应该理解了“do”的妙用了,它除了给出“开始执行”这一概念外,还有将各条指令打包的作用。
[size=16.3799991607666px]

[size=16.3799991607666px]那么再旁通一下,是的,这是一个疯狂的想法,[size=16.3799991607666px]在“do”指令中,也可以钳入各种指令,
[size=16.3799991607666px]包括forEachEvent,包括if……,只要逻辑上能通过都行。

[ 本帖最后由 溺水鱼 于 15-2-26 16:52 编辑 ]

1158
#58 15-2-26 16:51

CAL教程05(实例讲解:初级二)

[size=16.3799991607666px]下例中,我们将讲解输入与输出指令

[size=16.3799991607666px]输入指令:

[size=16.3799991607666px]说到输入指令,就不得不先说说用户自定义变量,
[size=16.3799991607666px]因为输入指令在绝大多数情况下,[size=16.3799991607666px]就是针对自定义变量进行修改的!

[size=16.3799991607666px]在前文中,我已经放出了CAL的所有指令列表,最开头的四个常用变量,就是用户自定义变量,
[size=16.3799991607666px]即:int;word;long;dword[size=16.3799991607666px]掌握这四个变量的应用,是步入中级CAL编写的必备条件,它们,很简单!
[size=16.3799991607666px]设置这四个变量的格式是:(变量类型 变量名 默认值)
[size=16.3799991607666px]其中,默认值是可以不写的,如果不写,则默认为“零”
[size=16.3799991607666px]我们利用上面的两个例子来加入输入指令,看看有什么惊喜!

[size=16.3799991607666px]—————————————————————————————————————————————————

[size=16.3799991607666px]例3:由一个音符,生成一个用户输入的指定音程音符

[size=16.3799991607666px]这就涉及到——“getInt类型”,“getWord类型”,“getTime类型”,这三种输入指令。
[size=16.3799991607666px]它们的编写格式是完全一样的,即:[size=16.3799991607666px](类型 变量 "说明文字" 取值限制)

[size=16.3799991607666px]注:类型,填写上面讲到的三种输入类型,这取决于你用来承载输入值的变量类型,
[size=16.3799991607666px]如果你设定的变量是int类型,则填写getInt类型,如果是word类型,则填写getWord类型。
[size=16.3799991607666px]getTime类型稍微特殊,它是描述时间位置的输入类型,[size=16.3799991607666px]因此,对应它的变量类型的取值要尽可能的大,
[size=16.3799991607666px]因为时间不可能为负值,[size=16.3799991607666px]所以对应getTime输入的最佳变量类型,就是dword类型。

[size=16.3799991607666px]下例中,我们涉及到用户自定义的音乐元素是音高,音高在钢琴窗中的值是0键位至127键位,
[size=16.3799991607666px]所以我们只需要int作为变量类型即可。

[size=16.3799991607666px](do
[size=16.3799991607666px] (int KEY 4)
[size=16.3799991607666px] (getInt KEY "KEY+?" 1 6)
[size=16.3799991607666px] (forEachEvent
[size=16.3799991607666px]  (do
[size=16.3799991607666px]   (insert Event.Time Event.Chan NOTE (+ Note.Key 7) Note.Vel Note.Dur)
[size=16.3799991607666px]   (insert Event.Time Event.Chan NOTE (+ Note.Key KEY) Note.Vel Note.Dur)
[size=16.3799991607666px]  )
[size=16.3799991607666px] )
[size=16.3799991607666px])

[size=16.3799991607666px]此例中,我们的CAL执行后,被选中的音符将变成一个三和弦,根音与五音是固定写入的,
[size=16.3799991607666px]中间的和弦音则会弹出对话框,由用户自己输入需要增加的半音数。
[size=16.3799991607666px]因此,我们必须知道,我们在音乐中的音程关系,用键位要如何表达,其实很简单,
[size=16.3799991607666px]即:
[size=16.3799991607666px]小二度,则是在原音符的基础上增加1个键位。
[size=16.3799991607666px]大二度,则是在原音符的基础上增加2个键位。
[size=16.3799991607666px]小三度,则是在原音符的基础上增加3个键位。
[size=16.3799991607666px]大三度,则是在原音符的基础上增加4个键位。
[size=16.3799991607666px]……
[size=16.3799991607666px]依次类推,是不是很简单!
[size=16.3799991607666px]所以,在上例中,当我们要输入一个大三和弦时,在执行CAL脚本后,
[size=16.3799991607666px]程序会弹出一个标有“[size=16.3799991607666px]KEY+?[size=16.3799991607666px]”字样的对话框,
[size=16.3799991607666px]要求输入中间的和弦内音与根音之间的半音差值。
[size=16.3799991607666px]比如:
[size=16.3799991607666px]我们需要得到一个挂四和弦,[size=16.3799991607666px]我们知道挂四音就是大三音再向上多一个小二度,
[size=16.3799991607666px]那么我们在执行CAL后,就需要在弹出的对话框中输入5,并点击确定,
[size=16.3799991607666px]程序将帮我们把选中的音符变成一个挂四和弦。


但是,这样的一个CAL程序,其执行结果是将被选中的所有音符,都统一的变成以自身为根音的某个和弦,
这显得很鸡肋,因为很多情况下,我们需要输入的第一个和弦是大三,第二个和弦又想要小三,第三个或许想要挂四,
再后面又希望回到大三……

当然,也许童鞋们说,我可以将CAL设置成热键,然后每次只选中一个音符,执行热键,生成一个和声,
然后再点中下一个音符,再按热键……
确实,这样操作已经比用鼠标一个个去写方便很多了,但是,CAL的威力远不只如此,大家要意识到,它在MIDI领域,
是无所不能的,只要我们花心思去设置语句的排序,精心的去设置执行思路,CAL效率的提升,将会更加剧烈!
上例中,
我们只需要将输入指令的位置加以改变,我们就可以全选所有音符,并在每一个音符变为和弦时,都弹出输入对话框。


[size=16.3799991607666px]—————————————————————————————————————————————————


例4:对每一个音符都弹出一次输入框

[size=16.3799991607666px](do
[size=16.3799991607666px] (int KEY 4)
[size=16.3799991607666px] (forEachEvent
[size=16.3799991607666px]  (do
[size=16.3799991607666px]   (getInt KEY "KEY+?" -32768 32767)
[size=16.3799991607666px]   (insert Event.Time Event.Chan NOTE (+ Note.Key 7) Note.Vel Note.Dur)
[size=16.3799991607666px]   (insert Event.Time Event.Chan NOTE (+ Note.Key KEY) Note.Vel Note.Dur)
[size=16.3799991607666px]  )
[size=16.3799991607666px] )
[size=16.3799991607666px])



[size=16.3799991607666px]此例中,我们将输入语句的位置,从红色的 do 指令区,改到了蓝色的 do 指令区,
[size=16.3799991607666px]这就意味着原本在红色区中,只会被执行一次的输入指令,变成了现在每一次扫描一个音符时,
[size=16.3799991607666px]都要执行一次用户输入指令。是不是更高效了?


[size=16.3799991607666px]但是我们很快又不满足于此,因为如果框选的音符太多,在执行CAL的过程中,
[size=16.3799991607666px]我们很容易迷失,不知道程序到底扫描的是哪个音符,如果能在每次扫描音符时,
[size=16.3799991607666px]都能知道当前音符是什么音,那就太好了。


[size=16.3799991607666px]CAL对音符进行音高识别,并转换成音乐人一目了然的音高名,这当然是没问题的,
[size=16.3799991607666px]不过这涉及到除余运算,以及对比语句这两个中级CAL概念,我们留到以后再讲。


[size=16.3799991607666px]再多提一句,
[size=16.3799991607666px]很多会编写CAL的用户,在针对和弦写入的编写方式中,花了不少心思,其功能也五花八门,
[size=16.3799991607666px]比如,我们可以将常用的每一个和弦结构,都编写成一个单独的CAL脚本,
[size=16.3799991607666px]比如:大三,小三,挂四,加九,加六……甚至各种七和弦结构,
[size=16.3799991607666px]然后将这些CAL全部设置到好记的热键上去。
[size=16.3799991607666px]比如大三和弦设置到Shift+3,小三和弦设置到Ctrl+3……只要自己方便记忆,就怎么设置,
[size=16.3799991607666px]这样在写和弦时,将会相当快,甚至,在乐理与和声概念上十分熟习的人,
[size=16.3799991607666px]用CAL的输入速度将远超MIDI键盘输入的速度。


[size=16.3799991607666px]所以,我们在设计CAL功能时,不能仅限于功能的实现,[size=16.3799991607666px]而是要用“高效”二字贯穿整个设计思路。
[size=16.3799991607666px]有时并不是CAL的编写一定要多么高深,功能多么强大,才能体现高效这个概念。


[size=16.3799991607666px]就[size=16.3799991607666px]像例4,虽然一个CAL就可以输入很多种三和弦结构,如果将五音的输入也改由用户输入,
[size=16.3799991607666px]那么这一个CAL就可以输入几乎所有结构的和弦。但是,大家可以预见,这样一个CAL,
[size=16.3799991607666px]并不如将各种常用结构分解成各个不同的独立CAL,再由多个热键控制来得更加方便。


[size=16.3799991607666px]—————————————————————————————————————————————————


下一贴,讲一些控制器与弯音的插入,当然也是初级的用法,仔细理解并能运用本贴的童鞋们,其实可能自己都能旁通理解。

待续……

187
#59 15-2-26 20:02
一直关注此物,遗憾还没来得及研究已经不用CW了。

7
#60 15-2-27 11:47
确实看不懂,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

搜索