11 |
your own instrument scripts in short time. It concentrates on describing |
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 |
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 |
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>. |
<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> |
</p> |
19 |
|
|
20 |
<h3>At a Glance</h3> |
<h3>At a Glance</h3> |
21 |
<p> |
<p> |
22 |
<img src="nksp_file.png" style="height:111px; margin-right:12px;"> |
<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 |
NKSP stands for "is <b>N</b>ot <b>KSP</b>", which denotes its distinction |
24 |
to an existing proprieatary language called <i>KSP</i>. |
to an existing proprietary language called <i>KSP</i>. |
25 |
NSKP is a script language specifically designed to write real-time capable |
NSKP is a script language specifically designed to write real-time capable |
26 |
software extensions to LinuxSampler's sampler engines that can be bundled |
software extensions to LinuxSampler's sampler engines that can be bundled |
27 |
individually with sounds by sound designers themselves. |
individually with sounds by sound designers themselves. |
254 |
<p> |
<p> |
255 |
The left hand side's <code>??variable-name??</code> is an arbitrary name |
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 |
you can chose for your variable. That name might consist of English |
257 |
letters A to Z (lower and upper case) and the underscore character "<code>_</code>". |
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 |
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 |
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>. |
already been reserved by <i>built-in variables</i>. |
772 |
@postfix := "nd" |
@postfix := "nd" |
773 |
case 3 |
case 3 |
774 |
@postfix := "rd" |
@postfix := "rd" |
775 |
end if |
end select |
776 |
|
|
777 |
message("This is the " & $numberOfNotes & @postfix & " note triggered so far.") |
message("This is the " & $numberOfNotes & @postfix & " note triggered so far.") |
778 |
end on |
end on |
813 |
case 3 |
case 3 |
814 |
message("Third note was triggered!") { Will never be printed ! } |
message("Third note was triggered!") { Will never be printed ! } |
815 |
exit |
exit |
816 |
end if |
end select |
817 |
|
|
818 |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
819 |
end on |
end on |
852 |
case 1 to 99 |
case 1 to 99 |
853 |
message("Less than 100 notes triggered so far") |
message("Less than 100 notes triggered so far") |
854 |
exit |
exit |
855 |
end if |
end select |
856 |
|
|
857 |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
message("Wow, already the " & $numberOfNotes & "th note triggered.") |
858 |
end on |
end on |
932 |
loop is thus left at that point and the text message was printed |
loop is thus left at that point and the text message was printed |
933 |
three times in total. |
three times in total. |
934 |
</p> |
</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> |
<h2>Operators</h2> |
1156 |
<p> |
<p> |
1157 |
A programming language provides so called <i>operators</i> to perform |
A programming language provides so called <i>operators</i> to perform |