1 |
<html> |
2 |
<head> |
3 |
<meta name="author" content="Christian Schoenebeck"> |
4 |
<title>NKSP Language</title> |
5 |
<meta name="description" content="Introduction to the NKSP real-time instrument script language."> |
6 |
</head> |
7 |
<body> |
8 |
<p> |
9 |
This document intends to give you a compact introduction and overview to |
10 |
the NKSP real-time instrument script language, so you can start writing |
11 |
your own instrument scripts in short time. It concentrates on describing |
12 |
the script language. If you rather want to learn how to modify and |
13 |
attach scripts to your sounds, then please refer to the gigedit manual for |
14 |
<a href="gigedit_scripts.html">how to manage instrument scripts with gigedit</a> |
15 |
for Gigasampler/GigaStudio format sounds, or refer to the SFZ opcode |
16 |
<code lang="sfz">script</code> for attaching NKSP scripts with |
17 |
SFZ format sounds. |
18 |
</p> |
19 |
|
20 |
<h3>At a Glance</h3> |
21 |
<p> |
22 |
<img src="nksp_file.png" style="height:111px; margin-right:12px;"> |
23 |
NKSP stands for "is <b>N</b>ot <b>KSP</b>", which denotes its distinction |
24 |
to an existing proprietary language called <i>KSP</i>. |
25 |
NSKP is a script language specifically designed to write real-time capable |
26 |
software extensions to LinuxSampler's sampler engines that can be bundled |
27 |
individually with sounds by sound designers themselves. |
28 |
|
29 |
Instead of defining a completely new script language, NKSP is leaned on |
30 |
that mentioned properiatary script language. The biggest advantage is that |
31 |
sound designers and musicians can leverage the huge amount of existing KSP |
32 |
scripts which are already available for various purposes on the Internet, |
33 |
instead of being forced to write all scripts from scratch in a completely |
34 |
different language. |
35 |
</p> |
36 |
<p> |
37 |
That also means however that there are some differences between those two |
38 |
languages. Some extensions have been added to the NKSP core language to |
39 |
make it a bit more convenient and less error prone to write scripts, and |
40 |
various new functions had to be added due to the large difference of the |
41 |
sampler engines and their underlying sampler format. Efforts have been |
42 |
made though to make NKSP as much compatible to KSP as possible. |
43 |
The NKSP documentation will emphasize individual differences in |
44 |
the two languages and function implementations wherever they may occur, to |
45 |
give you immediate hints where you need to take care of regarding |
46 |
compatibility issues when writing scripts that should be spawned on both |
47 |
platforms. |
48 |
</p> |
49 |
<p> |
50 |
Please note that the current focus of NKSP is the sound controlling aspect |
51 |
of sounds. At this point there is no support for the graphical user |
52 |
interface function set of KSP in NKSP. |
53 |
</p> |
54 |
|
55 |
<h2>Event Handlers</h2> |
56 |
<p> |
57 |
NKSP is an event-driven language. That means you are writing so called |
58 |
<i>event handlers</i> which define what the sampler shall do on individual |
59 |
events that occur, while using the sound the script was bundled with. |
60 |
An event handler in general looks like this: |
61 |
</p> |
62 |
<code lang="nksp"> |
63 |
on ??event-name?? |
64 |
|
65 |
??statements?? |
66 |
|
67 |
end on |
68 |
</code> |
69 |
<p> |
70 |
There are currently four events available: |
71 |
</p> |
72 |
<table> |
73 |
<tr> |
74 |
<th>Event Type</th> <th>Description</th> |
75 |
</tr> |
76 |
<tr> |
77 |
<td><code>on note</code></td> <td>This event handler is executed when a new note was triggered, i.e. when hitting a key on a MIDI keyboard.</td> |
78 |
</tr> |
79 |
<tr> |
80 |
<td><code>on release</code></td> <td>This event handler is executed when a new note was released, i.e. when releasing a key on a MIDI keyboard.</td> |
81 |
</tr> |
82 |
<tr> |
83 |
<td><code>on controller</code></td> <td>This event handler is executed when a MIDI control change event occurred. For instance when turning the modulation wheel at a MIDI keyboard.</td> |
84 |
</tr> |
85 |
<tr> |
86 |
<td><code>on init</code></td> <td>Executed only once, as very first event handler, right after the script had been loaded. This code block is usually used to initialize variables in your script with some initial, useful data.</td> |
87 |
</tr> |
88 |
</table> |
89 |
<p> |
90 |
You are free to decide for which ones of those event types you are going to |
91 |
write an event handler for. You can write an event handler for only one |
92 |
event type or write event handlers for all of those event types. Also |
93 |
dependent on the respective event type, there are certain things you can |
94 |
do and things which you can't do. But more on that later. |
95 |
</p> |
96 |
|
97 |
<h3>Note Events</h3> |
98 |
<p> |
99 |
As a first example, the following tiny script will print a message to your |
100 |
terminal whenever you trigger a new note with your MIDI keyboard. |
101 |
</p> |
102 |
<code> |
103 |
on note |
104 |
message("A new note was triggered!") |
105 |
end on |
106 |
</code> |
107 |
<p> |
108 |
Probably you are also interested to see which note you triggered exactly. |
109 |
The sampler provides you a so called |
110 |
<i title="A script variable which is provided by the sampler and which has a very specific purpose which you cannot override for other purposes."> |
111 |
built-in variable |
112 |
</i> |
113 |
called <code>$EVENT_NOTE</code> which reflects the note number |
114 |
(as value between 0 and 127) of the note that has just been triggered. Additionally |
115 |
the built-in variable <code>$EVENT_VELOCITY</code> provides you the |
116 |
velocity value (also between 0 and 127) of the note event. |
117 |
</p> |
118 |
<code> |
119 |
on note |
120 |
message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY) |
121 |
end on |
122 |
</code> |
123 |
<p> |
124 |
The <code>&</code> character concatenates text strings with each other. |
125 |
In this case it is also automatically converting the note number into a |
126 |
text string. |
127 |
</p> |
128 |
<note class="important"> |
129 |
The message() function is not appropriate for being used with your final |
130 |
production sounds, since it can lead to audio dropouts. |
131 |
You should only use the message() function to try out things, and to spot |
132 |
and debug problems with your scripts. |
133 |
</note> |
134 |
|
135 |
<h3>Release Events</h3> |
136 |
<p> |
137 |
As counter part to the <code>note</code> event handler, there is also the |
138 |
<code>release</code> event handler, which is executed when a note was |
139 |
released. This event handler can be used similarly: |
140 |
</p> |
141 |
<code> |
142 |
on release |
143 |
message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY) |
144 |
end on |
145 |
</code> |
146 |
<p> |
147 |
Please note that you can hardly find MIDI keyboards which support release |
148 |
velocity. So with most keyboards this value will be 127. |
149 |
</p> |
150 |
|
151 |
<h3>Controller Events</h3> |
152 |
<p> |
153 |
Now let's extend the first script to not only show note-on and note-off |
154 |
events, but also to show a message whenever |
155 |
you use a MIDI controller (i.e. modulation wheel, sustain pedal, etc.). |
156 |
</p> |
157 |
<code> |
158 |
on note |
159 |
message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY) |
160 |
end on |
161 |
|
162 |
on release |
163 |
message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY) |
164 |
end on |
165 |
|
166 |
on controller |
167 |
message("MIDI Controller " & $CC_NUM " changed its value to " & %CC[$CC_NUM]) |
168 |
end on |
169 |
</code> |
170 |
<p> |
171 |
It looks very similar to the note event handlers. <code>$CC_NUM</code> |
172 |
reflects the MIDI controller number of the MIDI controller that had been |
173 |
changed and <code>%CC</code> is a so called <i>array variable</i>, which not only |
174 |
contains a single number value, but instead it contains several values at |
175 |
the same time. The built-in <code>%CC</code> array variable contains the current |
176 |
controller values of all 127 MIDI controllers. So <code>%CC[1]</code> for |
177 |
example would give you the current controller value of the modulation |
178 |
wheel, and therefore <code>%CC[$CC_NUM]</code> reflects the new controller |
179 |
value of the controller that just had been changed. |
180 |
</p> |
181 |
<p> |
182 |
There is some special aspect you need to be aware about: in contrast to the MIDI standard, |
183 |
monophonic aftertouch (a.k.a. channel pressure) and pitch beend wheel are |
184 |
handled by NKSP as if they were regular MIDI controllers. So a value change |
185 |
of one of those two triggers a regular <code>controller</code> event handler |
186 |
to be executed. To obtain the current aftertouch value you can use |
187 |
<code>%CC[$VCC_MONO_AT]</code>, and to get the current pitch bend wheel |
188 |
value use <code>%CC[$VCC_PITCH_BEND]</code>. |
189 |
</p> |
190 |
|
191 |
<h3>Script Load Event</h3> |
192 |
<p> |
193 |
As the last one of the four event types available with NKSP, the following |
194 |
is an example of an <code>init</code> event handler. |
195 |
</p> |
196 |
<code> |
197 |
on init |
198 |
message("This script has been loaded and is ready now!") |
199 |
end on |
200 |
</code> |
201 |
<p> |
202 |
You might think, that this is probably a very exotic event. Because in |
203 |
fact, this "event" is only executed once for your script: exactly when |
204 |
the script was loaded by the sampler. This is not an unimportant event |
205 |
handler though. Because it is used to prepare your script for various |
206 |
purposes. We will get more about that later. |
207 |
</p> |
208 |
|
209 |
<h2>Comments</h2> |
210 |
<p> |
211 |
Let's face it: software code is sometimes hard to read, especially when you |
212 |
are not a professional software developer who deals with such kinds of |
213 |
things every day. To make it more easy for you to understand, what you |
214 |
had in mind when you wrote a certain script three years ago, and also if |
215 |
some other developer might need to continue working on your scripts one |
216 |
day, you should place as many comments into your scripts as possible. A |
217 |
comment in NKSP is everything that is nested into a an opening and closing |
218 |
pair of curly braces. |
219 |
</p> |
220 |
<code>{ This is a comment. }</code> |
221 |
<p> |
222 |
You cannot only use this to leave some human readable explanations here |
223 |
and there, you might also use such curly braces to quickly disable parts |
224 |
of your scripts for a moment, i.e. when debugging certain things. |
225 |
</p> |
226 |
<code> |
227 |
on init |
228 |
{ The following will be prompted to the terminal when the sampler loaded this script. } |
229 |
message("My script loaded.") |
230 |
|
231 |
{ This code block is commented out, so these two messages will not be displayed } |
232 |
{ |
233 |
message("Another text") |
234 |
message("And another one") |
235 |
} |
236 |
end on |
237 |
</code> |
238 |
|
239 |
<h2>Variables</h2> |
240 |
<p> |
241 |
In order to be able to write more complex and more useful scripts, you |
242 |
also need to remember some data somewhere for being able to use that |
243 |
data at a later point. This can be done by using |
244 |
<i title="A variable is a storage location paired with an associated symbolic name."> |
245 |
variables |
246 |
</i>. |
247 |
We already came across some <i>built-in variables</i>, which are already |
248 |
defined by the sampler for you. To store your own data you need to declare |
249 |
your own <i>user variables</i>, which has the following form: |
250 |
</p> |
251 |
<p> |
252 |
<code>declare $??variable-name?? := ??initial-value?? |
253 |
</p> |
254 |
<p> |
255 |
The left hand side's <code>??variable-name??</code> is an arbitrary name |
256 |
you can chose for your variable. That name might consist of English |
257 |
letters A to Z (lower and upper case), digits (<code>0</code> to <code>9</code>), |
258 |
and the underscore character "<code>_</code>". |
259 |
Variable names must be unique. So you can neither declare several variables |
260 |
with the same name, nor can you use a name for your variable that is |
261 |
already been reserved by <i>built-in variables</i>. |
262 |
The right hand side's <code>??initial-value??</code> is simply the first |
263 |
value the variable should store right after it was created. You can also |
264 |
omit that. |
265 |
</p> |
266 |
<p> |
267 |
<code>declare $??variable-name?? |
268 |
</p> |
269 |
<p> |
270 |
In that case the sampler will automatically assign <code>0</code> for you |
271 |
as the variable's initial value. This way we could for example count the |
272 |
total amount of notes triggered. |
273 |
</p> |
274 |
<code> |
275 |
on init |
276 |
declare $numberOfNotes := 0 |
277 |
end on |
278 |
|
279 |
on note |
280 |
$numberOfNotes := $numberOfNotes + 1 |
281 |
|
282 |
message("This is the " & $numberOfNotes & "th note triggered so far.") |
283 |
end on |
284 |
</code> |
285 |
<p> |
286 |
In the <code>init</code> event handler we create our own variable |
287 |
<code>$numberOfNotes</code> and assign <code>0</code> to it as its |
288 |
initial value. Like mentioned before, that initial assignment is optional. |
289 |
In the <code>note</code> event handler we then increase the |
290 |
<code>$numberOfNotes</code> variable by one, each time a new note was |
291 |
triggered and then print a message to the terminal with the current total |
292 |
amount of notes that have been triggered so far. |
293 |
</p> |
294 |
<note> |
295 |
NKSP allows you to declare variables in all event handlers, however if |
296 |
you want to keep compatibility with KSP, then you should only |
297 |
declare variables in <code>init</code> event handlers. |
298 |
</note> |
299 |
|
300 |
<h3>Variable Types</h3> |
301 |
<p> |
302 |
There are currently three different variable types, which you can easily |
303 |
recognize upon their first character. |
304 |
</p> |
305 |
<table> |
306 |
<tr> |
307 |
<th>Variable Form</th> <th>Data Type</th> <th>Description</th> |
308 |
</tr> |
309 |
<tr> |
310 |
<td><code>$??variable-name??</code></td> <td>Integer Scalar</td> <td>Stores one single integer number value.</td> |
311 |
</tr> |
312 |
<tr> |
313 |
<td><code>%??variable-name??</code></td> <td>Integer Array</td> <td>Stores a certain amount of integer number values.</td> |
314 |
</tr> |
315 |
<tr> |
316 |
<td><code>@??variable-name??</code></td> <td>String</td> <td>Stores one text string.</td> |
317 |
</tr> |
318 |
</table> |
319 |
<p> |
320 |
So the first character just before the actual variable name, always |
321 |
denotes the data type of the variable. Also note that all variable types |
322 |
share the same variable name space. That means you cannot declare a |
323 |
variable with a name that has already been used to declare a variable of |
324 |
another variable type. |
325 |
</p> |
326 |
|
327 |
<h3>Array Variables</h3> |
328 |
<p> |
329 |
We already used the first two variable types. However we have not seen yet |
330 |
how to declare such array variables. This is the common declaration form |
331 |
for creating your own array variables. |
332 |
</p> |
333 |
<code> |
334 |
on init |
335 |
declare %??variable-name??[??array-size??] := ( ??list-of-values?? ) |
336 |
end on |
337 |
</code> |
338 |
<p> |
339 |
So let's say you wanted to create an array variable with the first 12 |
340 |
prime numbers, then it might look like this. |
341 |
</p> |
342 |
<code> |
343 |
on init |
344 |
declare %primes[12] := ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ) |
345 |
end on |
346 |
</code> |
347 |
<p> |
348 |
Like with integer variables, assigning some initial values with |
349 |
<code>??list-of-values??</code> is optional. The array |
350 |
declaration form without initial value assignment looks like this. |
351 |
</p> |
352 |
<code> |
353 |
on init |
354 |
declare %??variable-name??[??array-size??] |
355 |
end on |
356 |
</code> |
357 |
<p> |
358 |
When you omit that initial assignment, then all numbers of that array will |
359 |
automatically be initialized with <code>0</code> each. With array |
360 |
variables however, it is always mandatory to provide |
361 |
<code>??array-size??</code> with an array |
362 |
variable declaration, so the sampler can create that array with the |
363 |
requested amount of values when the script is loaded. In contrast to many |
364 |
other programming languages, changing that amount of values of an array |
365 |
variable is not possible after the variable had been declared. That's due |
366 |
to the fact that this language is dedicated to real-time applications, and |
367 |
changing the size of an array variable at runtime would harm real-time |
368 |
stability of the sampler and thus could lead to audio dropouts. So NKSP |
369 |
does not allow you to do that. |
370 |
</p> |
371 |
|
372 |
|
373 |
<h3>String Variables</h3> |
374 |
<p> |
375 |
You might also store text with variables. These are called <i>text string |
376 |
variables</i>, or short: <i>string variables</i>. Let's skip the common declaration |
377 |
form of string variables and let us modify a prior example to just use |
378 |
such kind of variable. |
379 |
</p> |
380 |
<code> |
381 |
on init |
382 |
declare $numberOfNotes |
383 |
declare @firstText := "This is the " |
384 |
declare @secondText |
385 |
end on |
386 |
|
387 |
on note |
388 |
$numberOfNotes := $numberOfNotes + 1 |
389 |
@secondText := "th note triggered so far." |
390 |
message(@firstText & $numberOfNotes & @secondText) |
391 |
end on |
392 |
</code> |
393 |
<p> |
394 |
It behaves exactly like the prior example and shall just give you a |
395 |
first idea how to declare and use string variables. |
396 |
</p> |
397 |
<note class="important"> |
398 |
Like with the message() function, you should not use string variables |
399 |
with your final production sounds, since it can lead to audio dropouts. |
400 |
You should only use string variables to try out things, and to spot |
401 |
and debug problems with your scripts. |
402 |
</note> |
403 |
|
404 |
<h3>Variable Scope</h3> |
405 |
<p> |
406 |
By default, all variables you declare with NKSP are |
407 |
<i title="A variable that is accessible throughout an entire script."> |
408 |
global variables |
409 |
</i>. That means every event handler can access the data of such a global |
410 |
variable. Furthermore, each instance of an event handler accesses the same |
411 |
data when it is referencing that variable. And the latter fact can be a |
412 |
problem sometimes, which we will outline next. |
413 |
</p> |
414 |
<p> |
415 |
Let's assume you wanted to write an instrument script that shall resemble |
416 |
a simple delay effect. You could do that by writing an note event handler |
417 |
that automatically triggers several new notes for each note being |
418 |
triggered on a MIDI keyboard. The following example demonstrates how that |
419 |
could be achieved. |
420 |
</p> |
421 |
<note> |
422 |
You need at least LinuxSampler 2.0.0.svn2 or higher for the following |
423 |
example to work as described and as expected. Refer to the notes of the |
424 |
<code>wait()</code> function reference documentation for more |
425 |
informations about this issue. |
426 |
</note> |
427 |
<code> |
428 |
on init |
429 |
{ The amount of notes to play } |
430 |
declare const $delayNotes := 4 |
431 |
{ Tempo with which the new notes will follow the orignal note } |
432 |
declare const $bpm := 90 |
433 |
{ Convert BPM to microseconds (duration between the notes) } |
434 |
declare const $delayMicroSeconds := 60 * 1000000 / $bpm |
435 |
{ Just a working variable for being used with the while loop below } |
436 |
declare $i |
437 |
{ For each successive note we trigger, we will reduce the velocity a bit} |
438 |
declare $velocity |
439 |
end on |
440 |
|
441 |
on note |
442 |
{ First initialize the variable $i with 4 each time we enter this event |
443 |
handler, because each time we executed this handler, the variable will be 0 } |
444 |
$i := $delayNotes |
445 |
|
446 |
{ Loop which will be executed 4 times in a row } |
447 |
while ($i) |
448 |
{ Calculate the velocity for the next note being triggered } |
449 |
$velocity := 127 * $i / ($delayNotes + 1) |
450 |
{ Suspend this script for a short moment ... } |
451 |
wait($delayMicroSeconds) |
452 |
{ ... and after that short break, trigger a new note. } |
453 |
play_note($EVENT_NOTE, $velocity) |
454 |
{ Decrement loop counter $i by one } |
455 |
$i := $i - 1 |
456 |
end while |
457 |
end on |
458 |
</code> |
459 |
<p> |
460 |
In this example we used a new keyword <code>const</code>. This additional |
461 |
variable qualifier defines that we don't intend to change this variable |
462 |
after declaration. So if you know beforehand, that a certain variable should |
463 |
remain with a certain value, then you might use the <code>const</code> |
464 |
qualifier to avoid that you i.e. change the value accidently when you |
465 |
modify the script somewhere in future. |
466 |
</p> |
467 |
<p> |
468 |
Now when you trigger one single note on your keyboard with that script, |
469 |
you will hear the additional notes being triggered. And also when you |
470 |
hit another note after a while, everything seems to be fine. However if |
471 |
you start playing quick successive notes, you will notice something goes |
472 |
wrong. The amount of notes being triggered by the script is now incorrect |
473 |
and also the volume of the individual notes triggered by the script is wrong. |
474 |
What's going on? |
475 |
</p> |
476 |
<p> |
477 |
To understand the problem in the last example, let's consider what is |
478 |
happening when executing that script exactly: Each time you play a note |
479 |
on your keyboard, a new instance of the <code>note</code> event handler |
480 |
will be spawned and executed by the sampler. In all our examples so far |
481 |
our scripts were so simple, that in practice only one handler instance |
482 |
was executed at a time. This is different in this case though. Because |
483 |
by calling the <code>wait()</code> function, the respective handler |
484 |
execution instance is paused for a while and in total each handler |
485 |
instance will be executed for more than 2 seconds in this particular |
486 |
example. As a consequence, when |
487 |
you play multiple, successive notes on your keyboard in short time, you |
488 |
will have several instances of the <code>note</code> event handler running |
489 |
simultaniously. And that's where the problem starts. Because by default, |
490 |
as said, all variables are global variables. So the handler instances |
491 |
which are now running in parallel, are all reading and modifying the same |
492 |
data. Thus the individual handler instances will modify the |
493 |
<code>$i</code> and <code>$velocity</code> variables of each other, causing |
494 |
an undesired misbehavior. |
495 |
</p> |
496 |
<note> |
497 |
NKSP's built-in function <code>play_note()</code> allows you to pass |
498 |
between one and four function arguments. For the function arguments you |
499 |
don't provide to a <code>play_note()</code> call, NKSP will automatically |
500 |
use default values. If you want your script to be compatible with KSP, |
501 |
then you should always pass four arguments to that function though. |
502 |
</note> |
503 |
|
504 |
<h3>Polyphonic Variables</h3> |
505 |
<p> |
506 |
As a logical consequence of the previously described data concurrency |
507 |
problem, it would be desirable to have each event handler instance use |
508 |
its own variable instance, so that the individual handler instances stop |
509 |
interfering with each other. For this purpose the so called |
510 |
<i title="A variable which is effectively a separate variable for each event handler instance."> |
511 |
polyphonic variable |
512 |
</i> |
513 |
qualifier exists with NKSP. Declaring such a variable is identical to |
514 |
declaring a regular variable, just that you add the keyword <code>polyphonic</code>. |
515 |
</p> |
516 |
<code> |
517 |
declare polyphonic $??variable-name?? |
518 |
</code> |
519 |
<p> |
520 |
So to fix the bug in our previous example, we simply make the variables |
521 |
<code>$i</code> and <code>$velocity</code> polyphonic variables. |
522 |
</p> |
523 |
<code> |
524 |
on init |
525 |
{ The amount of notes to play } |
526 |
declare const $delayNotes := 4 |
527 |
{ Tempo with which the new notes will follow the orignal note } |
528 |
declare const $bpm := 90 |
529 |
{ Convert BPM to microseconds (duration between the notes) } |
530 |
declare const $delayMicroSeconds := 60 * 1000000 / $bpm |
531 |
{ Just a working variable for being used with the while loop below } |
532 |
declare polyphonic $i { < --- NOW POLYPHONIC !!! } |
533 |
{ For each successive note we trigger, we will reduce the velocity a bit} |
534 |
declare polyphonic $velocity { < --- NOW POLYPHONIC !!! } |
535 |
end on |
536 |
|
537 |
on note |
538 |
{ First initialize the variable $i with 4 each time we enter this event |
539 |
handler, because each time we executed this handler, the variable will be 0 } |
540 |
$i := $delayNotes |
541 |
|
542 |
{ Loop which will be executed 4 times in a row } |
543 |
while ($i) |
544 |
{ Calculate the velocity for the next note being triggered } |
545 |
$velocity := 127 * $i / ($delayNotes + 1) |
546 |
{ Suspend this script for a short moment ... } |
547 |
wait($delayMicroSeconds) |
548 |
{ ... and after that short break, trigger a new note. } |
549 |
play_note($EVENT_NOTE, $velocity) |
550 |
{ Decrement loop counter $i by one } |
551 |
$i := $i - 1 |
552 |
end while |
553 |
end on |
554 |
</code> |
555 |
<p> |
556 |
And that's it! The script works now as intended. Now you might wonder, why |
557 |
are variables not <i>polyphonic</i> by default? Isn't that more common and |
558 |
wouldn't that be more safer than using global variables by default? The reason is that |
559 |
a polyphonic variable consumes a lot more memory than a regular (global) variable. |
560 |
That's because for each polyphonic variable, the sampler has to allocate |
561 |
in advance (when the script is loaded) as many instances of that |
562 |
polyphonic variable as there are maximum events |
563 |
allowed with the sampler. So that's a lot! Considering that today's |
564 |
computers have plenty of RAM this might be a theoretical aspect, but in the |
565 |
end: this default scope of variables was already like this with <i>KSP</i> |
566 |
so we are also doing it like this with NKSP for compatibility reasons. |
567 |
</p> |
568 |
<p> |
569 |
Please note that the <i>polyphonic</i> qualifier only exists for integer |
570 |
variables. So you cannot declare polyphonic string variables, nor can you |
571 |
declare polyphonic array variables. Like in the previous explanation, |
572 |
this is due to the fact that it would consume a huge amount of memory |
573 |
for such variables. And with string variables and array variables, the |
574 |
required amount of memory would be much higher than with simple integer |
575 |
variables. |
576 |
</p> |
577 |
<p> |
578 |
As summary, the following are guideline rules describing when you should |
579 |
use the polyphonic qualifier for a certain variable. You should declare |
580 |
a particular variable polyphonic if one (or even both) of the following two |
581 |
conditions apply to that variable. |
582 |
</p> |
583 |
<ol> |
584 |
<li> |
585 |
If you call the <code>wait()</code> function within your event |
586 |
handlers and the respective variable is modified and read before |
587 |
and after at least one of the individual <code>wait()</code> calls. |
588 |
</li> |
589 |
<li> |
590 |
If you have loops that might run for a very long time, while accessing |
591 |
the respective variable in between. That's because if your script is |
592 |
running consecutively for too long, the sampler will automatically suspend your |
593 |
script for a while to avoid your script becoming a real-time stability |
594 |
hazard for the sampler. Your script will then automatically be resumed |
595 |
after a short moment by the sampler, so effectively this is similar to |
596 |
something like an "automated" <code>wait()</code> function call by |
597 |
the sampler. |
598 |
</li> |
599 |
</ol> |
600 |
<p> |
601 |
In all other cases you should rather use regular (global) variables instead. |
602 |
But keep in mind that you might need to re-assign a certain value for |
603 |
some global variables when you enter the respective event handler, just |
604 |
like we did with <code>$i := $delayNotes</code> right from the start |
605 |
during discussion of the previous example script. |
606 |
</p> |
607 |
<p> |
608 |
There is another special aspect regarding the variable scope of polyphonic |
609 |
variables: <code>note</code> handlers and <code>release</code> handlers of |
610 |
the same script share the same polyphonic variable scope, that means you |
611 |
may pass data from a particular note's <code>note</code> handler to its |
612 |
<code>release</code> handler by using the same polyphonic variable name. |
613 |
</p> |
614 |
|
615 |
<h2>Control Structures</h2> |
616 |
<p> |
617 |
A computer is more than a calculator that adds numbers and stores them |
618 |
somewhere. One of the biggest strength of a computer, which makes it |
619 |
such powerful, is the ability to do different things depending on various |
620 |
conditions. For example your computer might clean up your hard drive |
621 |
while you are not sitting in front of it, and it might immediately stop |
622 |
doing so when you need all its resources to cut your latest video which |
623 |
you just shot. |
624 |
</p> |
625 |
<p> |
626 |
In order to do that for you, a computer program allows you to define |
627 |
conditions and a list of instructions the computer shall |
628 |
perform for you under those individual conditions. These kinds of |
629 |
software mechanisms are called <i>Control Structures</i>. |
630 |
</p> |
631 |
|
632 |
<h3>if Branches</h3> |
633 |
<p> |
634 |
The most fundamental control structure are <i>if branches</i>, which has |
635 |
the following general form. |
636 |
</p> |
637 |
<code> |
638 |
if (??condition??) |
639 |
|
640 |
??statements?? |
641 |
|
642 |
end if |
643 |
</code> |
644 |
<p> |
645 |
The specified <code>??condition??</code> is evaluated each time script |
646 |
execution reaches this control block. The condition can for example be |
647 |
the value of a variable, some arithmetic expression, a function call or |
648 |
a combination of them. In all cases the sampler expects the |
649 |
<code>??condition??</code> expression to evaluate to some numeric |
650 |
(or boolean) value. If the evaluated number is exactly <code>0</code> then |
651 |
the condition is interpreted to be <i>false</i> and thus the list of |
652 |
<code>??statements??</code> is not executed. If the evaluated value is any |
653 |
other value than <code>0</code> then the condition is interpreted to be |
654 |
<i>true</i> and accordingly the list of <code>??statements??</code> will be |
655 |
executed. |
656 |
</p> |
657 |
<p> |
658 |
Alternatively you might also specify a list of instructions which shall be |
659 |
executed when the condition is <i>false</i>. |
660 |
</p> |
661 |
<code> |
662 |
if (??condition??) |
663 |
|
664 |
??statements-when-true?? |
665 |
|
666 |
else |
667 |
|
668 |
??statements-when-false?? |
669 |
|
670 |
end if |
671 |
</code> |
672 |
<p> |
673 |
In this case the first list of statements is executed when the |
674 |
<code>??condition??</code> evaluated to <i>true</i>, otherwise the second |
675 |
list of statements is executed instead. |
676 |
</p> |
677 |
<p> |
678 |
Once again, let's get back to the example of counting triggered notes. |
679 |
You might have noticed that it did not output correct English for the |
680 |
first three notes. Let's correct this now. |
681 |
</p> |
682 |
<code> |
683 |
on init |
684 |
declare $numberOfNotes |
685 |
declare @postfix |
686 |
end on |
687 |
|
688 |
on note |
689 |
$numberOfNotes := $numberOfNotes + 1 |
690 |
|
691 |
if ($numberOfNotes == 1) |
692 |
@postfix := "st" |
693 |
else |
694 |
if ($numberOfNotes == 2) |
695 |
@postfix := "nd" |
696 |
else |
697 |
if ($numberOfNotes == 3) |
698 |
@postfix := "rd" |
699 |
else |
700 |
@postfix := "th" |
701 |
end if |
702 |
end if |
703 |
end if |
704 |
|
705 |
message("This is the " & $numberOfNotes & @postfix & " note triggered so far.") |
706 |
end on |
707 |
</code> |
708 |
<p> |
709 |
We are now checking the value of <code>$numberOfNotes</code> before we |
710 |
print out a message. If <code>$numberOfNotes</code> equals one, then we |
711 |
assign the string <code>"st"</code> to the variable <code>@postfix</code>, |
712 |
if <code>$numberOfNotes</code> equals 2 instead we assign the string |
713 |
<code>"nd"</code> instead, if it equals 3 instead we assign |
714 |
<code>"rd"</code>, in all other cases we assign the string |
715 |
<code>"th"</code>. And finally we assemble the text message to be |
716 |
printed out to the terminal on line 23. |
717 |
</p> |
718 |
|
719 |
<h3>Select Case Branches</h3> |
720 |
<p> |
721 |
The previous example now outputs the numbers in correct English. But the |
722 |
script code looks a bit bloated, right? That's why there is a short hand |
723 |
form. |
724 |
</p> |
725 |
<code> |
726 |
select ??expression?? |
727 |
|
728 |
case ??integer-1?? |
729 |
|
730 |
??statements-1?? |
731 |
|
732 |
|
733 |
case ??integer-2?? |
734 |
|
735 |
??statements-2?? |
736 |
|
737 |
. |
738 |
. |
739 |
. |
740 |
end select |
741 |
</code> |
742 |
<p> |
743 |
The provided <code>??expression??</code> is first evaluated to an integer |
744 |
value. Then this value is compared to the integer values of the nested |
745 |
<code>case</code> lines. So it first compares the evaluated value of |
746 |
<code>??expression??</code> with <code>??integer-1??</code>, then it |
747 |
compares it with <code>??integer-2??</code>, and so on. The first integer |
748 |
number that matches with the evaluated value of <code>??expression??</code>, |
749 |
will be interpreted as being the current valid condition. So if |
750 |
<code>??expression??</code> equals <code>??integer-1??</code>, |
751 |
then <code>??statements-1??</code> will be executed, otherwise if |
752 |
<code>??expression??</code> equals <code>??integer-2??</code>, |
753 |
then <code>??statements-2??</code> will be executed, and so on. |
754 |
</p> |
755 |
<p> |
756 |
Using a select-case construct, our previous example would look like follows. |
757 |
</p> |
758 |
<code> |
759 |
on init |
760 |
declare $numberOfNotes |
761 |
declare @postfix |
762 |
end on |
763 |
|
764 |
on note |
765 |
$numberOfNotes := $numberOfNotes + 1 |
766 |
@postfix := "th" |
767 |
|
768 |
select $numberOfNotes |
769 |
case 1 |
770 |
@postfix := "st" |
771 |
case 2 |
772 |
@postfix := "nd" |
773 |
case 3 |
774 |
@postfix := "rd" |
775 |
end select |
776 |
|
777 |
message("This is the " & $numberOfNotes & @postfix & " note triggered so far.") |
778 |
end on |
779 |
</code> |
780 |
<note> |
781 |
If you like, you can also put parentheses around the select expression, |
782 |
like <code>select (??expression??)</code>. Some developers familiar with |
783 |
other programming languages might prefer this style. However if you want |
784 |
to keep compatibility with KSP, you should not use parentheses for |
785 |
select expressions. |
786 |
</note> |
787 |
<p> |
788 |
The amount |
789 |
of case conditions you add to such select-case blocks is completely up |
790 |
to you. Just remember that the case conditions will be compared one by one, |
791 |
from top to down. The latter can be important when you define a case line |
792 |
that defines a value range. So for instance the following example will |
793 |
not do what was probably intended. |
794 |
</p> |
795 |
<code> |
796 |
on init |
797 |
declare $numberOfNotes |
798 |
end on |
799 |
|
800 |
on note |
801 |
$numberOfNotes := $numberOfNotes + 1 |
802 |
|
803 |
select $numberOfNotes |
804 |
case 1 to 99 |
805 |
message("Less than 100 notes triggered so far") |
806 |
exit |
807 |
case 1 |
808 |
message("First note was triggered!") { Will never be printed ! } |
809 |
exit |
810 |
case 2 |
811 |
message("Second note was triggered!") { Will never be printed ! } |
812 |
exit |
813 |
case 3 |
814 |
message("Third note was triggered!") { Will never be printed ! } |
815 |
exit |
816 |
end select |
817 |
|
818 |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
819 |
end on |
820 |
</code> |
821 |
<p> |
822 |
You probably get the idea what this script "should" do. For the 1st note |
823 |
it should print <code>"First note was triggered!"</code>, for the 2nd |
824 |
note it should print <code>"Second note was triggered!"</code>, for the 3rd |
825 |
note it should print <code>"Third note was triggered!"</code>, for the 4th |
826 |
up to 99th note it should print <code>"Less than 100 notes triggered so far"</code>, |
827 |
and starting from the 100th note and all following ones, it should print |
828 |
the precise note number according to line 23. However, it doesn't! |
829 |
</p> |
830 |
<p> |
831 |
To correct this problem, you need to move the first case block to the end, |
832 |
like follows. |
833 |
</p> |
834 |
<code> |
835 |
on init |
836 |
declare $numberOfNotes |
837 |
end on |
838 |
|
839 |
on note |
840 |
$numberOfNotes := $numberOfNotes + 1 |
841 |
|
842 |
select $numberOfNotes |
843 |
case 1 |
844 |
message("First note was triggered!") |
845 |
exit |
846 |
case 2 |
847 |
message("Second note was triggered!") |
848 |
exit |
849 |
case 3 |
850 |
message("Third note was triggered!") |
851 |
exit |
852 |
case 1 to 99 |
853 |
message("Less than 100 notes triggered so far") |
854 |
exit |
855 |
end select |
856 |
|
857 |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
858 |
end on |
859 |
</code> |
860 |
<p> |
861 |
Or you could of course fix the questioned case range from <code>case 1 to 99</code> |
862 |
to <code>case 4 to 99</code>. Both solutions will do. |
863 |
</p> |
864 |
<p> |
865 |
We also used the <i>built-in function</i> <code>exit()</code> in the |
866 |
previous example. You can use it to stop execution at that point of your |
867 |
script. In the previous example it prevents multiple messages to be |
868 |
printed to the terminal. |
869 |
</p> |
870 |
<note class="important"> |
871 |
The <code>exit()</code> function only stops execution of the <b>current</b> |
872 |
event handler instance! It does <b>not</b> stop execution of other |
873 |
instances of the same event handler, nor does it stop execution of other |
874 |
handlers of other event types, and especially it does <b>not</b> stop or |
875 |
prevent further or future execution of your entire script! In other words, |
876 |
you should rather see this function as a return statement, in case you are |
877 |
familiar with other programming languages already. |
878 |
</note> |
879 |
|
880 |
<h3>while Loops</h3> |
881 |
<p> |
882 |
Another fundamental control construct of program flow are loops. |
883 |
You can use so called |
884 |
<i title="Repeats a given list of instructions until the defined condition turns false."> |
885 |
while loops |
886 |
</i> |
887 |
with NKSP. |
888 |
</p> |
889 |
<code> |
890 |
while (??condition??) |
891 |
|
892 |
??statements?? |
893 |
|
894 |
end while |
895 |
</code> |
896 |
<p> |
897 |
A while loop is entered if the provided <code>??condition??</code> |
898 |
expression evaluates to <i>true</i> and will then continue to execute |
899 |
the given list of <code>??statements??</code> down to the end of the statements |
900 |
list. The <code>??condition??</code> is re-evaluated each time execution |
901 |
reached the end of the <code>??statements??</code> list and according to |
902 |
that latest evaluated <code>??condition??</code> value at that point, it |
903 |
will or will not repeat executing the statements again. If the condition |
904 |
turned <i>false</i> instead, it will leave the loop and continue executing |
905 |
statements that follow after the while loop block. |
906 |
</p> |
907 |
<p> |
908 |
The next example will print the same message three times in a row to the |
909 |
terminal, right after the script had been loaded by the sampler. |
910 |
</p> |
911 |
<code> |
912 |
on init |
913 |
declare $i := 3 |
914 |
|
915 |
while ($i) |
916 |
message("Print this three times.") |
917 |
$i := $i - 1 |
918 |
end while |
919 |
end on |
920 |
</code> |
921 |
<p> |
922 |
When the while loop is reached for the first time in this example, the |
923 |
condition value is <code>3</code>. And as we learned before, all integer |
924 |
values that are not <code>0</code> are interpreted as being a <i>true</i> condition. |
925 |
Accordingly the while loop is entered, the message is printed to the |
926 |
terminal and the variable <code>$i</code> is reduced by one. We reached |
927 |
the end of the loop's statements list, so it is now re-evaluating the |
928 |
condition, which is now the value <code>2</code> and thus the loop |
929 |
instructions are executed again. That is repeated until the loop was |
930 |
executed for the third time. The variable <code>$i</code> is now |
931 |
<code>0</code>, so the loop condition turned finally to <i>false</i> and the |
932 |
loop is thus left at that point and the text message was printed |
933 |
three times in total. |
934 |
</p> |
935 |
|
936 |
<h3>User Functions</h3> |
937 |
<p> |
938 |
We already came across various built-in functions, which you may call |
939 |
by your scripts to perform certain tasks or behavior which is already |
940 |
provided for you by the sampler. NKSP also allows you to write your |
941 |
own functions, which you then may call from various places of your |
942 |
script. |
943 |
<p> |
944 |
</p> |
945 |
When working on larger scripts, you |
946 |
may notice that you easily get to the point where you may have to |
947 |
duplicate portions of your script code, since there are certain things |
948 |
that you may have to do again and again in different parts of your script. |
949 |
Software developers usually try to avoid such code duplications to |
950 |
keep the overall amount of code as small as possible, since the |
951 |
overall amount of code would bloat quickly and would |
952 |
make the software very hard to maintain. One way for you to avoid such |
953 |
script code duplications with NKSP is to write so called <i>User Functions</s>. |
954 |
</p> |
955 |
<p> |
956 |
Let's assume you wanted to create a simple stuttering effect. You may do so |
957 |
like in the following example. |
958 |
</p> |
959 |
<code> |
960 |
on note |
961 |
while (1) |
962 |
wait(200000) |
963 |
if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE)) |
964 |
exit() |
965 |
end if |
966 |
change_vol($EVENT_ID, -20000) { Reduce volume by 20 dB. } |
967 |
wait(200000) |
968 |
if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE)) |
969 |
exit() |
970 |
end if |
971 |
change_vol($EVENT_ID, 0) { Increase volume to 0 dB. } |
972 |
end while |
973 |
end on |
974 |
</code> |
975 |
<p> |
976 |
This script will run an endless loop for each note being triggered. |
977 |
Every <code lang="none">200ms</code> it will turn the volume alternatingly down and |
978 |
up to create the audible stuttering effect. After each <code lang="nksp">wait()</code> |
979 |
call it calls <code>event_status($EVENT_ID)</code> to check whether |
980 |
this note is still alive, and as soon as the note died, it will stop |
981 |
execution of the script instance by calling <code>exit()</code>. The latter |
982 |
is important in this example, because otherwise the script execution instances would |
983 |
continue to run in this endless loop forever, even after the respectives |
984 |
notes are gone. Which would let your CPU usage to increase with every new note |
985 |
and would never decrease again. |
986 |
This behavior of the sampler is not a bug, it is intended, since there may |
987 |
also be cases where you want to do certain things by script even after the |
988 |
respective notes are dead and gone. However as you can see, that script is |
989 |
using the same portions of script code twice. To avoid that, you could also |
990 |
write the same script with a user function like this: |
991 |
</p> |
992 |
<code> |
993 |
function pauseMyScript |
994 |
wait(200000) |
995 |
if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE)) |
996 |
exit() |
997 |
end if |
998 |
end function |
999 |
|
1000 |
on note |
1001 |
while (1) |
1002 |
call pauseMyScript |
1003 |
change_vol($EVENT_ID, -20000) { Reduce volume by 20 dB. } |
1004 |
call pauseMyScript |
1005 |
change_vol($EVENT_ID, 0) { Increase volume back to 0 dB. } |
1006 |
end while |
1007 |
end on |
1008 |
</code> |
1009 |
<p> |
1010 |
The script became in this simple example only slightly smaller, but it also |
1011 |
became easier to read and behaves identically to the previous solution. |
1012 |
And in practice, with a more complex script, you can |
1013 |
reduce the overall amount of script code a lot this way. You can choose any |
1014 |
name for your own user functions, as long as the name is not already |
1015 |
reserved by a built-in function. Note that for calling a user function, |
1016 |
you must always precede the actual user function name with the |
1017 |
<code>call</code> keyword. Likewise you may however not use the |
1018 |
<code>call</code> keyword for calling any built-in function. So that |
1019 |
substantially differs calling built-in functions from calling user functions. |
1020 |
</p> |
1021 |
|
1022 |
<h3>Synchronized Blocks</h3> |
1023 |
<p> |
1024 |
When we introduced the <a href="#polyphonic_variables">polyphonic keyword</a> |
1025 |
previously, we learned that a script may automatically be suspended by |
1026 |
the sampler at any time and then your script is thus sleeping for an |
1027 |
arbitrary while. The sampler must do such auto suspensions under certain |
1028 |
situations in cases where an instrument script may become a hazard for the |
1029 |
sampler's overall real-time stability. If the sampler would not do so, then |
1030 |
instrument scripts might easily cause audio dropouts, or at worst, buggy |
1031 |
instrument scripts might even lock up the entire sampler in an endless |
1032 |
loop. So auto suspension is an essential feature of the sampler's real-time |
1033 |
instrument script engine. |
1034 |
</p> |
1035 |
<p> |
1036 |
Now the problem as a script author is that you don't really know beforehand |
1037 |
why and when your script might get auto suspended by the sampler. And when |
1038 |
you are working on more complex, sophisticated scripts, you will notice |
1039 |
that this might indeed be a big problem in certain sections of your scripts. |
1040 |
Because in practice, a sophisticated script often has at least one certain |
1041 |
consecutive portion of statements which must be executed in strict consecutive order |
1042 |
by the sampler, which might otherwise cause concurrency issues and thus |
1043 |
misbehavior of your script if that sensible code section was auto suspended |
1044 |
in between. A typical example of such concurrency sensible code sections are |
1045 |
statements which are reading and conditionally modifying global variables. |
1046 |
If your script gets auto suspended in such a code section, another |
1047 |
script handler instance might then interfere and change those global |
1048 |
variables in between. |
1049 |
</p> |
1050 |
<p> |
1051 |
To avoid that, you can place such a sensible code section at the very beginning |
1052 |
of your event handler. For example consider you might be writing a custom |
1053 |
<i title="A consecutive pitch glide from one note to another note.">glissando</i> |
1054 |
script starting like this: |
1055 |
</p> |
1056 |
<code> |
1057 |
on init |
1058 |
declare $keysDown |
1059 |
declare $firstNoteID |
1060 |
declare $firstNoteNr |
1061 |
declare $firstVelocity |
1062 |
end on |
1063 |
|
1064 |
on note |
1065 |
{ The concurrency sensible code section for the "first active" note. } |
1066 |
inc($keysDown) |
1067 |
if ($keysDown = 1 or event_status($firstNoteID) = $EVENT_STATUS_INACTIVE) |
1068 |
$firstNoteID = $EVENT_ID |
1069 |
$firstNoteNr = $EVENT_NOTE |
1070 |
$firstVelocity = $EVENT_VELOCITY |
1071 |
exit { return from event handler here } |
1072 |
end if |
1073 |
|
1074 |
{ The non-sensible code for all other subsequent notes would go here. } |
1075 |
end on |
1076 |
|
1077 |
on release |
1078 |
dec($keysDown) |
1079 |
end on |
1080 |
</code> |
1081 |
<p> |
1082 |
Because the earlier statements are executed in an event handler, the higher |
1083 |
the chance that they will never get auto suspended. And with those couple of |
1084 |
lines in the latter example you might even be lucky that it won't ever get |
1085 |
suspended in that sensible code section at least. However when it comes to live |
1086 |
concerts you don't really want to depend on luck, and in practice such a |
1087 |
sensible code section might be bigger than this one. |
1088 |
</p> |
1089 |
<p> |
1090 |
That's why we introduced <code>synchronized</code> code blocks for the |
1091 |
NKSP language, which have the following form: |
1092 |
</p> |
1093 |
<code> |
1094 |
synchronized |
1095 |
|
1096 |
??statements?? |
1097 |
|
1098 |
end synchronized |
1099 |
</code> |
1100 |
<p> |
1101 |
All <code>??statements??</code> which you put into such a synchronized |
1102 |
code block are guaranteed that they will never get auto suspended by |
1103 |
the sampler. |
1104 |
</p> |
1105 |
<note> |
1106 |
Such <code>synchronized</code> blocks are a language extension which |
1107 |
is only available with NKSP and requires at least LinuxSampler 2.0.0.svn60 |
1108 |
or higher. KSP does not support <code>synchronized</code> blocks. |
1109 |
</note> |
1110 |
<p> |
1111 |
So to make our previous example concurrency safe, we would |
1112 |
change it like this: |
1113 |
</p> |
1114 |
<code> |
1115 |
on init |
1116 |
declare $keysDown |
1117 |
declare $firstNoteID |
1118 |
declare $firstNoteNr |
1119 |
declare $firstVelocity |
1120 |
end on |
1121 |
|
1122 |
on note |
1123 |
{ The concurrency sensible code section for the "first active" note. } |
1124 |
synchronized |
1125 |
inc($keysDown) |
1126 |
if ($keysDown = 1 or event_status($firstNoteID) = $EVENT_STATUS_INACTIVE) |
1127 |
$firstNoteID = $EVENT_ID |
1128 |
$firstNoteNr = $EVENT_NOTE |
1129 |
$firstVelocity = $EVENT_VELOCITY |
1130 |
exit { return from event handler here } |
1131 |
end if |
1132 |
end synchronized |
1133 |
|
1134 |
{ The non-sensible code for all other subsequent notes would go here. } |
1135 |
end on |
1136 |
|
1137 |
on release |
1138 |
dec($keysDown) |
1139 |
end on |
1140 |
</code> |
1141 |
<p> |
1142 |
If you are already familiar with some programming languages, then you |
1143 |
might already have seen such synchronized code block concepts |
1144 |
in languages like i.e. Java. This technique really provides an easy way |
1145 |
to protect certain sections of your script against concurrency issues. |
1146 |
</p> |
1147 |
<note class="important"> |
1148 |
You <b>must</b> use such <code>synchronized</code> code blocks only with great |
1149 |
care! If the amount of statements being executed in your synchronized block |
1150 |
is too large, then you will get audio dropouts. If you even use loops in |
1151 |
synchronized code blocks, then the entire sampler might even become |
1152 |
unresponsive in case your script is buggy! |
1153 |
</note> |
1154 |
|
1155 |
<h2>Operators</h2> |
1156 |
<p> |
1157 |
A programming language provides so called <i>operators</i> to perform |
1158 |
certain kinds of transformations of data placed next to the operators. |
1159 |
These are the operators available with NKSP. |
1160 |
</p> |
1161 |
|
1162 |
<h3>Arithmetic Operators</h3> |
1163 |
<p> |
1164 |
These are the most basic mathematical operators, which allow to add, |
1165 |
subtract, multiply and divide integer values with each other. |
1166 |
</p> |
1167 |
<code> |
1168 |
on init |
1169 |
message("4 + 3 is " & 4 + 3) { Add } |
1170 |
message("4 - 3 is " & 4 - 3) { Subtract } |
1171 |
message("4 * 3 is " & 4 * 3) { Multiply } |
1172 |
message("35 / 5 is " & 35 / 5) { Divide } |
1173 |
message("35 mod 5 is " & 35 mod 5) { Remainder of Division ("modulo") } |
1174 |
end on |
1175 |
</code> |
1176 |
<p> |
1177 |
You may either use direct integer literal numbers like used in the upper |
1178 |
example, or you can use integer number variables or integer array variables. |
1179 |
</p> |
1180 |
|
1181 |
<h3>Boolean Operators</h3> |
1182 |
<p> |
1183 |
To perform logical transformations of <i>boolean</i> data, you may use the |
1184 |
following logical operators: |
1185 |
</p> |
1186 |
<code> |
1187 |
on init |
1188 |
message("1 and 1 is " & 1 and 1) { logical "and" } |
1189 |
message("1 and 0 is " & 1 and 0) { logical "and" } |
1190 |
message("1 or 1 is " & 1 or 1) { logical "or" } |
1191 |
message("1 or 0 is " & 1 or 0) { logical "or" } |
1192 |
message("not 1 is " & not 1) { logical "not" } |
1193 |
message("not 0 is " & not 0) { logical "not" } |
1194 |
end on |
1195 |
</code> |
1196 |
<p> |
1197 |
Keep in mind that with logical operators shown above, |
1198 |
all integer values other than <code>0</code> |
1199 |
are interpreted as boolean <i>true</i> while an integer value of |
1200 |
precisely <code>0</code> is interpreted as being boolean <i>false</i>. |
1201 |
</p> |
1202 |
<p> |
1203 |
So the logical operators shown above always look at numbers at a whole. |
1204 |
Sometimes however you might rather need to process numbers bit by bit. For |
1205 |
that purpose the following bitwise operators exist. |
1206 |
</p> |
1207 |
<code> |
1208 |
on init |
1209 |
message("1 .and. 1 is " & 1 .and. 1) { bitwise "and" } |
1210 |
message("1 .and. 0 is " & 1 .and. 0) { bitwise "and" } |
1211 |
message("1 .or. 1 is " & 1 .or. 1) { bitwise "or" } |
1212 |
message("1 .or. 0 is " & 1 .or. 0) { bitwise "or" } |
1213 |
message(".not. 1 is " & .not. 1) { bitwise "not" } |
1214 |
message(".not. 0 is " & .not. 0) { bitwise "not" } |
1215 |
end on |
1216 |
</code> |
1217 |
<p> |
1218 |
Bitwise operators work essentially like logical operators, with the |
1219 |
difference that bitwise operators compare each bit independently. |
1220 |
So a bitwise <code>.and.</code> operator for instance takes the 1st bit |
1221 |
of the left hand's side value, the 1st bit of the right hand's side value, |
1222 |
compares the two bits logically and then stores that result as 1st bit of |
1223 |
the final result value, then it takes the 2nd bit of the left hand's side value |
1224 |
and the 2nd bit of the right hand's side value, compares those two bits logically |
1225 |
and then stores that result as 2nd bit of the final result value, and so on. |
1226 |
</p> |
1227 |
|
1228 |
|
1229 |
<h3>Comparison Operators</h3> |
1230 |
<p> |
1231 |
For branches in your program flow, it is often required to compare data |
1232 |
with each other. This is done by using comparison operators, enumerated |
1233 |
below. |
1234 |
</p> |
1235 |
<code> |
1236 |
on init |
1237 |
message("Relation 3 < 4 -> " & 3 < 4) { "smaller than" comparison } |
1238 |
message("Relation 3 > 4 -> " & 3 > 4) { "greater than" comparison } |
1239 |
message("Relation 3 <= 4 -> " & 3 <= 4) { "smaller or equal than" comparison} |
1240 |
message("Relation 3 >= 4 -> " & 3 >= 4) { "greater or equal than" comparison} |
1241 |
message("Relation 3 # 4 -> " & 3 # 4) { "not equal to" comparison} |
1242 |
message("Relation 3 = 4 -> " & 3 = 4) { "is equal to" comparison} |
1243 |
end on |
1244 |
</code> |
1245 |
<p> |
1246 |
All these operations yield in a <i>boolean</i> result which could then |
1247 |
be used i.e. with <code>if</code> or <code>while</code> loop statements. |
1248 |
</p> |
1249 |
|
1250 |
<h3>String Operators</h3> |
1251 |
<p> |
1252 |
Last but not least, there is exactly one operator for text string data; |
1253 |
the string concatenation operator <code>&</code>, which |
1254 |
combines two text strings with each other. |
1255 |
</p> |
1256 |
<code> |
1257 |
on init |
1258 |
declare @s := "foo" & " bar" |
1259 |
message(@s) |
1260 |
end on |
1261 |
</code> |
1262 |
<p> |
1263 |
We have used it now frequently in various examples before. |
1264 |
</p> |
1265 |
|
1266 |
<h2>Preprocessor Statements</h2> |
1267 |
<p> |
1268 |
Similar to low-level programming languages like C, C++, Objective C |
1269 |
and the like, NKSP supports a set of so called preprocessor statements. |
1270 |
These are essentially "instructions" which are "executed" or rather |
1271 |
processed, before (and only before) the script is executed by the sampler, |
1272 |
and even before the script is parsed by the actual NKSP language parser. |
1273 |
You can think of a preprocessor as a very primitive parser, which is the |
1274 |
first one getting in touch with your script, it modifies the script code |
1275 |
if requested by your preprocessor statements in the script, and then |
1276 |
passes the (probably) modified script to the actual NKSP language parser. |
1277 |
</p> |
1278 |
<p> |
1279 |
When we discussed <a href="#comments">comments</a> in NKSP scripts before, |
1280 |
it was suggested that you might comment out certain code parts to disable |
1281 |
them for a while during development of scripts. It was also suggested |
1282 |
during this language tour that you should not use string variables or use |
1283 |
the <code>message()</code> function with your final production sounds. |
1284 |
However those are very handy things during development of your instrument |
1285 |
scripts. You might even have a bunch of additional code in your scripts |
1286 |
which only satisfies the purpose to make debugging of your scripts more easy, |
1287 |
which however wastes on the other hand precious CPU time. So what do you |
1288 |
do? Like suggested, you could comment out the respective code sections as |
1289 |
soon as development of your script is completed. But then one day you |
1290 |
might continue to improve your scripts, and the debugging code would be |
1291 |
handy, so you would uncomment all the relevant code sections to get them |
1292 |
back. When you think about this, that might be quite some work each time. |
1293 |
Fortunately there is an alternative by using preprocessor statements. |
1294 |
</p> |
1295 |
|
1296 |
<h3>Set a Condition</h3> |
1297 |
<p> |
1298 |
First you need to set a preprocessor condition in your script. You can do |
1299 |
that like this: |
1300 |
</p> |
1301 |
<code> |
1302 |
SET_CONDITION(??condition-name??) |
1303 |
</code> |
1304 |
<p> |
1305 |
This preprocessor "condition" is just like some kind of |
1306 |
<i title="A variable which can only have two states: i.e. true or false."> |
1307 |
boolean variable |
1308 |
</i> |
1309 |
which is only available to the preprocessor and by using |
1310 |
<code>SET_CONDITION(??condition-name??)</code>, this is like setting this |
1311 |
preprocessor condition to <i>true</i>. Like with regular script |
1312 |
variables, a preprocessor condition name can be chosen quite arbitrarily |
1313 |
by you. But again, there are some pre-defined preprocessor conditions |
1314 |
defined by the sampler for you. So you can only set a condition name here |
1315 |
which is not already reserved by a built-in preprocessor condition. Also |
1316 |
you shall not set a condition in your script again if you have already set it |
1317 |
before somewhere in your script. The NKSP preprocessor will ignore setting |
1318 |
a condition a 2nd time and will just print a warning when the script is |
1319 |
loaded, but you should take care of it, because it might be a cause for |
1320 |
some bug. |
1321 |
</p> |
1322 |
|
1323 |
<h3>Reset a Condition</h3> |
1324 |
<p> |
1325 |
To clear a condition in your script, you might reset the condition like so: |
1326 |
</p> |
1327 |
<code> |
1328 |
RESET_CONDITION(??condition-name??) |
1329 |
</code> |
1330 |
<p> |
1331 |
This is like setting that preprocessor condition back to <i>false</i> again. |
1332 |
You should only reset a preprocessor condition that way if you did set it |
1333 |
with <code>SET_CONDITION(??condition-name??)</code> before. Trying to |
1334 |
reset a condition that has not been set before, or trying to reset a |
1335 |
condition that has already been reset, will both be ignored by the samlper, |
1336 |
but again you will get a warning, and you should take care about it. |
1337 |
</p> |
1338 |
|
1339 |
<h3>Conditionally Using Code</h3> |
1340 |
<p> |
1341 |
Now what do you actually do with such preprocessor conditions? You can use |
1342 |
them for the NKSP language parser to either |
1343 |
</p> |
1344 |
<ul> |
1345 |
<li>use certain parts of your code</i> |
1346 |
<li><b>and</b> / <b>or</b> to ignore certain parts of your code</i> |
1347 |
</ul> |
1348 |
<p> |
1349 |
You can achieve that by wrapping NKSP code parts into a pair of either |
1350 |
</p> |
1351 |
<code> |
1352 |
USE_CODE_IF(??condition-name??) |
1353 |
|
1354 |
??some-NKSP-code-goes-here?? |
1355 |
|
1356 |
END_USE_CODE |
1357 |
</code> |
1358 |
<p> |
1359 |
preprocessor statements, or between |
1360 |
</p> |
1361 |
<code> |
1362 |
USE_CODE_IF_NOT(??condition-name??) |
1363 |
|
1364 |
??some-NKSP-code-goes-here?? |
1365 |
|
1366 |
END_USE_CODE |
1367 |
</code> |
1368 |
<p> |
1369 |
statements. In the first case, the NKSP code portion is used by the NKSP |
1370 |
language parser if the given preprocessor <code>??condition-name??</code> is set |
1371 |
(that is if condition is <i>true</i>). |
1372 |
If the condition is not set, the NKSP code portion in between is |
1373 |
completely ignored by the NKSP language parser. |
1374 |
</p> |
1375 |
<p> |
1376 |
In the second case, the NKSP code portion is used by the NKSP |
1377 |
language parser if the given preprocessor <code>??condition-name??</code> is <b>not</b> set |
1378 |
(or was reset) |
1379 |
(that is if condition is <i>false</i>). |
1380 |
If the condition is set, the NKSP code portion in between is |
1381 |
completely ignored by the NKSP language parser. |
1382 |
</p> |
1383 |
<p> |
1384 |
Let's look at an example how to use that to define conditional debugging |
1385 |
code. |
1386 |
</p> |
1387 |
<code> |
1388 |
SET_CONDITION(DEBUG_MODE) |
1389 |
|
1390 |
on init |
1391 |
declare const %primes[12] := ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ) |
1392 |
declare $i |
1393 |
|
1394 |
USE_CODE_IF(DEBUG_MODE) |
1395 |
message("This script has just been loaded.") |
1396 |
|
1397 |
$i := 0 |
1398 |
while ($i < num_elements(%primes)) |
1399 |
message("Prime " & $i & " is " & %primes[$i]) |
1400 |
$i := $i + 1 |
1401 |
end while |
1402 |
END_USE_CODE |
1403 |
end on |
1404 |
|
1405 |
on note |
1406 |
USE_CODE_IF(DEBUG_MODE) |
1407 |
message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY) |
1408 |
END_USE_CODE |
1409 |
end on |
1410 |
|
1411 |
on release |
1412 |
USE_CODE_IF(DEBUG_MODE) |
1413 |
message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY) |
1414 |
END_USE_CODE |
1415 |
end on |
1416 |
|
1417 |
on controller |
1418 |
USE_CODE_IF(DEBUG_MODE) |
1419 |
message("MIDI Controller " & $CC_NUM " changed its value to " & %CC[$CC_NUM]) |
1420 |
END_USE_CODE |
1421 |
end on |
1422 |
</code> |
1423 |
<p> |
1424 |
The <i>built-in function</i> <code>num_elements()</code> used above, can |
1425 |
be called to obtain the size of an array variable at runtime. |
1426 |
As this script looks now, the debug messages will be printed out. However |
1427 |
it requires you to just remove the first line, or to comment out the first |
1428 |
line, in order to disable all debug code portions in just a second: |
1429 |
</p> |
1430 |
<code> |
1431 |
{ Setting the condition is commented out, so our DEBUG_MODE is disabled now. } |
1432 |
{ SET_CONDITION(DEBUG_MODE) } |
1433 |
|
1434 |
on init |
1435 |
declare const %primes[12] := ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ) |
1436 |
declare $i |
1437 |
|
1438 |
USE_CODE_IF(DEBUG_MODE) { Condition is not set, so this entire block will be ignored now. } |
1439 |
message("This script has just been loaded.") |
1440 |
|
1441 |
$i := 0 |
1442 |
while ($i < num_elements(%primes)) |
1443 |
message("Prime " & $i & " is " & %primes[$i]) |
1444 |
$i := $i + 1 |
1445 |
end while |
1446 |
END_USE_CODE |
1447 |
end on |
1448 |
|
1449 |
on note |
1450 |
USE_CODE_IF(DEBUG_MODE) { Condition is not set, no message will be printed. } |
1451 |
message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY) |
1452 |
END_USE_CODE |
1453 |
end on |
1454 |
|
1455 |
on release |
1456 |
USE_CODE_IF(DEBUG_MODE) { Condition is not set, no message will be printed. } |
1457 |
message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY) |
1458 |
END_USE_CODE |
1459 |
end on |
1460 |
|
1461 |
on controller |
1462 |
USE_CODE_IF(DEBUG_MODE) { Condition is not set, no message will be printed. } |
1463 |
message("MIDI Controller " & $CC_NUM " changed its value to " & %CC[$CC_NUM]) |
1464 |
END_USE_CODE |
1465 |
end on |
1466 |
</code> |
1467 |
<p> |
1468 |
Now you might say, you could also achieve that by declaring and using |
1469 |
a regular NKSP variable. That's correct, but there are two major |
1470 |
advantages by using preprocessor statements. |
1471 |
</p> |
1472 |
<ol> |
1473 |
<li> |
1474 |
<b>Saving Resources</b> - |
1475 |
The preprocessor conditions are only processed before the script is |
1476 |
loaded into the NKSP parser. So in contrast to using NKSP variables, |
1477 |
the preprocessor solution does not waste any CPU time or memory |
1478 |
resources while executing the script. That also means that variable |
1479 |
declarations can be disabled with the preprocessor this way |
1480 |
and thus will also safe resources. |
1481 |
</li> |
1482 |
<li> |
1483 |
<b>Cross Platform Support</b> - |
1484 |
Since the code portions filtered out by the preprocessor never make it |
1485 |
into the NKSP language parser, those filtered code portions might also |
1486 |
contain code which would have lead to parser errors. For example you |
1487 |
could use a built-in preprocessor condition to check whether your script |
1488 |
was loaded into LinuxSampler or rather into another sampler. That way |
1489 |
you could maintain one script for both platforms: NKSP and KSP. |
1490 |
Accordingly you could |
1491 |
also check a built-in variable to obtain the version of the sampler in |
1492 |
order to enable or disable code portions of your script that might |
1493 |
use some newer script features of the sampler which don't exist in older |
1494 |
version of the sampler. |
1495 |
</li> |
1496 |
</ol> |
1497 |
<p> |
1498 |
As a rule of thumb: if there are things that you could move from your |
1499 |
NKSP executed programming code out to the preprocessor, then you should |
1500 |
use the preprocessor instead for such things. And like stated above, |
1501 |
there are certain things which you can only achieve with the preprocessor. |
1502 |
</p> |
1503 |
|
1504 |
<h3>Disable Messages</h3> |
1505 |
<p> |
1506 |
Since it is quite common to switch a script between a development version |
1507 |
and a production version, you actually don't need to wrap all your |
1508 |
<code>message()</code> calls into preprocessor statements like in the |
1509 |
previous example just to disable messages. There is actually a built-in |
1510 |
preprocessor condition dedicated to perform that task much more conveniently for you. |
1511 |
To disable all messages in your script, simply add <code>SET_CONDITION(NKSP_NO_MESSAGE)</code> |
1512 |
i.e. at the very beginning of your script. |
1513 |
So the previous example can be simplified like this: |
1514 |
</p> |
1515 |
<code> |
1516 |
{ Enable debug mode, so show all debug messages. } |
1517 |
SET_CONDITION(DEBUG_MODE) |
1518 |
|
1519 |
{ If our user declared condition "DEBUG_MODE" is not set ... } |
1520 |
USE_CODE_IF_NOT(DEBUG_MODE) |
1521 |
{ ... then enable this built-in condition to disable all message() calls. } |
1522 |
SET_CONDITION(NKSP_NO_MESSAGE) |
1523 |
END_USE_CODE |
1524 |
|
1525 |
on init |
1526 |
declare const %primes[12] := ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ) |
1527 |
declare $i |
1528 |
|
1529 |
message("This script has just been loaded.") |
1530 |
|
1531 |
USE_CODE_IF(DEBUG_MODE) |
1532 |
$i := 0 |
1533 |
while ($i < num_elements(%primes)) |
1534 |
message("Prime " & $i & " is " & %primes[$i]) |
1535 |
$i := $i + 1 |
1536 |
end while |
1537 |
END_USE_CODE |
1538 |
end on |
1539 |
|
1540 |
on note |
1541 |
message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY) |
1542 |
end on |
1543 |
|
1544 |
on release |
1545 |
message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY) |
1546 |
end on |
1547 |
|
1548 |
on controller |
1549 |
message("MIDI Controller " & $CC_NUM " changed its value to " & %CC[$CC_NUM]) |
1550 |
end on |
1551 |
</code> |
1552 |
<p> |
1553 |
You can then actually also add <code>RESET_CONDITION(NKSP_NO_MESSAGE)</code> |
1554 |
at another section of your script, which will cause all subsequent |
1555 |
<code>message()</code> calls to be processed again. So that way you can |
1556 |
easily enable and disable <code>message()</code> calls of entire individual |
1557 |
sections of your script, without having to wrap all <code>message()</code> |
1558 |
calls into preprocessor statements. |
1559 |
</p> |
1560 |
|
1561 |
<h2>What Next?</h2> |
1562 |
<p> |
1563 |
You have completed the introduction of the NKSP real-time instrument |
1564 |
script language at this point. You can now dive into the details of the |
1565 |
NKSP language by moving on to the |
1566 |
<a href="nksp_reference.html">NKSP reference documentation</a>. |
1567 |
Which provides you an overview and quick access to the details of all |
1568 |
built-in functions, built-in variables and more. |
1569 |
</p> |
1570 |
|
1571 |
</body> |
1572 |
</html> |