所有分类
  • 所有分类
  • 宿主
  • 工具
  • 效果器
  • 教程
  • 采样器
  • 音源
  • 预设采样
  • 工程模板
  • 乐谱

Kontakt Script官方教程 – 变量

目录
[隐藏]

变量

现在我们回头看最开始的代码:

on note
  play_note(60,120,0,-1)
end on

之前已经说过,给每个音符都配同一个伴奏音着实平平无奇。我们想编写一个更高级的伴奏器,能够生成力度相同的高八度伴奏音,因此便有了:

on note
  play_note($EVENT_NOTE + 12,$EVENT_VELOCITY,0,-1)
end on

这个程序中我们没有指定某一固定的音符序号,而是写了$EVENT_NOTE + 12,也没有指定固定的力度,而是写了$EVENT_VELOCITY。其中的$EVENT_NOTE与$EVENT_VELOCITY便是所谓的内建变量,分别对应着输入音符的序号与力度。

脚本语言的核心就是变量。用计算机术语来说,变量就是命名了的存储空间,用于存放数据。稍后我们会讨论几种类型的变量,但马上我们要学习区分用户定义变量内建变量

以上两种变量有两种形式:

  • 常规变量,使用美元符号标记(($my_variable或$EVENT_VELOCITY)或“at”符号标记(@my_text)。
  • 阵列变量,使用百分符号标记(%my_array[]或%KEY_DOWN[<note-number>])或者感叹号标记(!my_text_array[])。

常规变量可以存储单一整数值或字符串。阵列变量与常规变量类似,但是可以存储多个数值或字符串。阵列是有索引的数组。若有一个表格,每一个索引x都指向地址y,这就是阵列的工作原理。阵列的元素数范围是1~512。

变量的声明

用户定义变量顾名思义需要事先声明。声明这一过程为变量注册一个名称,方便后续调用,同时为变量赋予一个值,将变量初始化。下面是一些变量的声明范例:

on init
  declare $first_variable
  declare $second_variable := 12
  declare const $third_variable := 24
  declare %first_array[4]
  declare %second_array[3] := (3,7,2)
end on
  • 第一行标记了初始化回调函数的开始(代码正确解析后,初始化回调函数立即执行)
  • 第二行中的declare(声明)指令,声明了一个变量first_variable。但是代码并没有为此变量赋值,所以它的值默认为0。
  • 第三行声明了一个变量second_variable,使用:=运算符赋值12。
  • 第四行声明了一个特殊的常规变量:名为third_variable的常量。常量与常规变量基本类似,但常量的数值不可更改,并且有助于提高程序效能,因为运行时不需要求值(evaluate)。
  • 第五行声明了一个阵列变量first_array,包含了四个元素,全都默认赋值为0。
  • 第六行声明了另一个阵列变量second_array,包含了三个元素,分别赋值为3,7和2。
  • 第七行标记了初始化回调函数的结尾。

从中不难看出变量的命名有几条规则:非阵列变量的开头都是$,而阵列变量的开头都是%。声明的语法如出一辙,范例中也有明显体现。声明常量时必须使用:=运算符赋值。

使用变量编程

请读者将下列代码粘贴进Kontakt,并在键盘上演奏音符:

on init
  declare $first_variable
  declare $second_variable := 12
  declare const $third_variable := 24
  declare %first_array[4]
  declare %second_array[3] := (3,7,2)
end on

on note
  play_note ($second_variable + 48,$third_variable + 96,...
      %first_array[2] + $first_variable,%second_array[0] - 4)
end on

这段代码与最开始那段代码的作用完全一样,每个音符都会有一个力度为120的伴奏音,音高为C3。看起来似乎是小题大做,但本例的真真目的在于展示如何操纵变量,传达给读者一些最基本的理念。上例中的play_note()函数与play_note (60, 120, 0, -1)完全一致:

  • $second_variable + 48=60
  • $third_variable + 96=120
  • %first_array[2]=0,因为2号元素的值为0
  • %second_array[0] – 4等于-1,因为0号元素的值为3,3减去4是-1。

内建变量极为重要,功能强大,不可被定义,随写随用。我们来看两个重要的内建变量(完整内建变量列表请移步查阅书后附录)

$EVENT_NOTE 触发回调函数的音符的序号
$EVENT_VELOCITY 触发回调函数的音符的力度

一个音符触发了回调函数后,此MIDI事件的音符序号便存储进$EVENT_NOTE中,而$EVENT_VELOCITY则是力度。显而易见,这两个变量在初始化回调函数中都不会用到,因为音符不能触发初始化回调函数,何谈音符或力度!

MIDI音符的序号范围是0~127,对应的音名为C-2~G8。$EVENT_VELOCITY的范围是1~127。内建变量的名称都是大写字母,所以用户定义的变量最好使用小写字母命名。

下面的范例包含了这两种类型的内建变量。

on init
  declare $new_note
end on

on note
  $new_note := $EVENT_NOTE + 12
  play_note($new_note,$EVENT_VELOCITY,0,-1)
end on

与本书最开头的例子一样,它还是生成一个力度为120的伴奏音,音高为C3。我们声明了一个变量$new_note,由于没有进行赋值操作,值默认为0。用户演奏音符时,程序执行音符回调函数,$EVENT_NOTE+12便赋值给了$new_note(:=将其左边的变量值赋给右边的变量)。

下面这段代码可以说有了实质性进步:

on init
  declare %addNote[12] := (4, 6, 3, 6, 3, 4, 6, 4, 6, 3, 6, 3)
  declare $keyClass
end on

on note
  $keyClass := $EVENT_NOTE mod 12
  play_note($EVENT_NOTE + %addNote[$keyClass],$EVENT_VELOCITY,0,-1)
end on

现在再演奏,情况就完全不一样了。用户演奏的音符,都有C调的伴奏音。但是在分析代码之前,我们要先搞懂求余(modulo)运算符mod。求余运算符输出两数相除后的余数,例如14 mod 12的值为2,128 mod 10的值为8,等等。

本例中的求余运算符的用法相当常见:$EVENT_NOTE mod 12的结果确定了演奏音符音级(pitch class),所以不管是哪个音组的D音,$keyClass都会是2。

加入演奏音符时D3(62),以$keyClass作为索引序号,程序从%addNote[12]取出的值为3,因此伴奏音序号为62+3=65,即F3。

字符串变量

字符串变量有两种:

  • 字符串变量,前缀为@
  • 字符串阵列,前缀为!

下面是一个简单范例:

on init
  declare @text
  @text := "note played: "
  declare !list[12]
  !list[0] := "C"
  !list[1] := "C#"
  !list[2] := "D"
  !list[3] := "D#"
  !list[4] := "E"
  !list[5] := "F"
  !list[6] := "F#"
  !list[7] := "G"
  !list[8] := "G#"
  !list[9] := "A"
  !list[10] := "A#"
  !list[11] := "B"
end on

on note
  message(@text & !list[$EVENT_NOTE mod 12])
end on

变量固化

在前面的编程基础章节中,我们已经学习了make_persistent()指令:

make_persistent(<变量名>)

加载文件后记住变量值。

用户加载文件或脚本后,程序会执行初始化回调函数,并将固化变量设置为保存时的值。而且用户点击Apply按钮后,固化变量的值也会保存。比如用户加载了Arpeggiator(琶音器)后,操作控件对其节奏进行了修改,然后决定对代码进行修改,先前所作的修改是不会丢失的。

注意:如果用户从脚本菜单加载脚本,固化变量的值不会进行缓冲处理。这一设计很有必要,因为不同脚本中可能由重名变量。

假如用户加载了一个延迟(delay)脚本,其中有变量$Time,用户修改变量后保存代码,再加载另一个脚本。无独有偶,这段脚本中也有一个变量名为$Time,用户是肯定不希望自己在前段代码中做的修改应用到后来代码中的。

脚本调用规则

五组代码的调用顺序是从前往后。键盘发出的MIDI信号传递给第一组代码,第一组代码发送MIDI信号给第二组,第二组再给第三组,以此类推。以一言蔽之,位次靠后的代码从靠前的代码中接受MIDI信号。

如果第一组脚本中某一事件被忽略,那此事件在后续代码中就不会出现了。假如第一组代码中生成了一个音符,第二组代码会收到此音符的序号,与在MIDI键盘上演奏的效果是一样的。

变量只能在自身所处的代码中生效,比如用户可以在不同代码中分别使用$tune_amount这个变量。因此在其他脚本之后插入别的代码不会引起错误,比如:

MIDI锁存器(Latch)→和声器(Harmonize)→琶音器(Arpeggiator)→调音器(Microtuning)

用户可以加载Kontakt 2库中的Ambient Harmonizat ion.nki,其位于:

Kontakt 2 Library/02 – KSP Instruments/06 – Harmonizer/Ambient Harmonization.nki。

  • 第一段脚本截获输入的MIDI信号。
  • 第二段脚本以特定速率演奏这些音符。
  • 第三段脚本按照重复音符构造和弦。
  • 第四段脚本将这些音符限定在特定音阶内。
1
分享海报
需要编曲混音教程、乐谱、工程文件,请联系微信:musicyoupin
没有账号?注册  忘记密码?