/[svn]/doc/docbase/instrument_scripts/nksp/01_nksp.html
ViewVC logotype

Diff of /doc/docbase/instrument_scripts/nksp/01_nksp.html

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2763 by schoenebeck, Wed May 6 21:14:19 2015 UTC revision 3702 by schoenebeck, Mon Jan 6 15:55:17 2020 UTC
# Line 11  Line 11 
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.
# Line 64  on ??event-name?? Line 67  on ??event-name??
67  end on  end on
68      </code>      </code>
69      <p>      <p>
70        There are currently four events available:        There are currently six events available:
71      </p>      </p>
72        <table>        <table>
73          <tr>          <tr>
# Line 74  end on Line 77  end on
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>            <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>          </tr>
79          <tr>          <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>            <td><code>on release</code></td> <td>This event handler is executed when a note was released, i.e. when releasing a key on a MIDI keyboard.</td>
81          </tr>          </tr>
82          <tr>          <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>            <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>          </tr>
85          <tr>          <tr>
86              <td><code>on rpn</code></td> <td>This event handler is executed when a MIDI <i>RPN</i> event occurred.</td>
87            </tr>
88            <tr>
89              <td><code>on nrpn</code></td> <td>This event handler is executed when a MIDI <i>NRPN</i> event occurred.</td>
90            </tr>
91            <tr>
92            <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>            <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>
93          </tr>          </tr>
94        </table>        </table>
# Line 144  end on Line 153  end on
153        Please note that you can hardly find MIDI keyboards which support release        Please note that you can hardly find MIDI keyboards which support release
154        velocity. So with most keyboards this value will be 127.        velocity. So with most keyboards this value will be 127.
155      </p>      </p>
156        
157      <h3>Controller Events</h3>      <h3>Controller Events</h3>
158      <p>        <p>  
159        Now let's extend the first script to not only show note-on and note-off        Now let's extend the first script to not only show note-on and note-off
# Line 177  end on Line 186  end on
186      </p>      </p>
187      <p>      <p>
188        There is some special aspect you need to be aware about: in contrast to the MIDI standard,        There is some special aspect you need to be aware about: in contrast to the MIDI standard,
189        monophonic aftertouch (a.k.a. channel pressure) and pitch beend wheel are        monophonic aftertouch (a.k.a. channel pressure) and pitch bend wheel are
190        handled by NKSP as if they were regular MIDI controllers. So a value change        handled by NKSP as if they were regular MIDI controllers. So a value change
191        of one of those two triggers a regular <code>controller</code> event handler        of one of those two triggers a regular <code>controller</code> event handler
192        to be executed. To obtain the current aftertouch value you can use        to be executed. To obtain the current aftertouch value you can use
193        <code>%CC[$VCC_MONO_AT]</code>, and to get the current pitch bend wheel        <code>%CC[$VCC_MONO_AT]</code>, and to get the current pitch bend wheel
194        value use <code>%CC[$VCC_PITCH_BEND]</code>.        value use <code>%CC[$VCC_PITCH_BEND]</code>.
195      </p>      </p>
196        
197        <h3>RPN / NRPN Events</h3>
198        <p>
199          There are also dedicated event handlers for
200          MIDI <i title="Registered Parameter Number">RPN</i> and
201          <i title="Non-Registered Parameter Number">NRPN</i>
202          events:
203        </p>
204        <code>
205    on rpn
206      message("RPN address msb=" & msb($RPN_ADDRESS) & ",lsb=" & lsb($RPN_ADDRESS) &
207              "-> value msb=" & msb($RPN_VALUE) & ",lsb="  & lsb($RPN_VALUE))
208      if ($RPN_ADDRESS = 2)
209        message("Standard Coarse Tuning RPN received")
210      end if
211    end on
212    
213    on nrpn
214      message("NRPN address msb=" & msb($RPN_ADDRESS) & ",lsb=" & lsb($RPN_ADDRESS) &
215              "-> value msb=" & msb($RPN_VALUE) & ",lsb="  & lsb($RPN_VALUE))
216    end on
217        </code>
218        <p>
219          Since MIDI RPN and NRPN events are actually MIDI controller events,
220          you might as well handle these with the previous
221          <code>controller</code> event handler. But since RPN and NRPN messages
222          are not just one MIDI message, but rather always handled by a set of
223          individual MIDI messages, and since the
224          precise set and sequence of actual MIDI commands sent varies between
225          vendors and even among individual of their products, it highly makes sense to
226          use these two specialized event handlers for these instead, because the
227          sampler will already relief you from that burden to deal with all those
228          low-level MIDI event processing issues and all their wrinkles involved
229          when handling RPNs and NRPNs.
230        </p>
231        <note>
232          Even though there are two separate, dedicated event handlers for RPN and NRPN events,
233          they both share the same built-in variable names as you can see in the
234          example above.
235        </note>
236        <p>
237          So by reading <code>$RPN_ADDRESS</code> you get the RPN / NRPN parameter
238          number that had been changed, and <code>$RPN_VALUE</code> represents the
239          new value of that RPN / NRPN parameter. Note that these two built-in
240          variables are a 14-bit representation of the parameter number and new
241          value. So their possible value range is <code>0 .. 16383</code>. If you
242          rather want to use their (in MIDI world) more common separated two 7 bit
243          values instead, then you can easily do that by wrapping them into either
244          <code>msb()</code> or <code>lsb()</code> calls like also demonstrated above.
245        </p>
246    
247      <h3>Script Load Event</h3>      <h3>Script Load Event</h3>
248      <p>      <p>
249        As the last one of the four event types available with NKSP, the following        As the last one of the six event types available with NKSP, the following
250        is an example of an <code>init</code> event handler.        is an example of an <code>init</code> event handler.
251      </p>      </p>
252      <code>      <code>
# Line 211  end on Line 270  end on
270        had in mind when you wrote a certain script three years ago, and also if        had in mind when you wrote a certain script three years ago, and also if
271        some other developer might need to continue working on your scripts one        some other developer might need to continue working on your scripts one
272        day, you should place as many comments into your scripts as possible. A        day, you should place as many comments into your scripts as possible. A
273        comment in NKSP is everything that is nested into a an opening and closing        comment in NKSP is everything that is nested into an opening and closing
274        pair of curly braces.        pair of curly braces.
275      </p>      </p>
276      <code>{ This is a comment. }</code>      <code>{ This is a comment. }</code>
# Line 251  end on Line 310  end on
310      <p>      <p>
311        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
312        you can chose for your variable. That name might consist of English        you can chose for your variable. That name might consist of English
313        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>),
314          and the underscore character "<code>_</code>".
315        Variable names must be unique. So you can neither declare several variables        Variable names must be unique. So you can neither declare several variables
316        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
317        already been reserved by <i>built-in variables</i>.        already been reserved by <i>built-in variables</i>.
# Line 409  end on Line 469  end on
469      </p>      </p>
470      <p>      <p>
471        Let's assume you wanted to write an instrument script that shall resemble        Let's assume you wanted to write an instrument script that shall resemble
472        a simple delay effect. You could do that by writing an note event handler        a simple delay effect. You could do that by writing a note event handler
473        that automatically triggers several new notes for each note being        that automatically triggers several new notes for each note being
474        triggered on a MIDI keyboard. The following example demonstrates how that        triggered on a MIDI keyboard. The following example demonstrates how that
475        could be achieved.        could be achieved.
476      </p>      </p>
     <note class="important">  
       The following example does not fully work with LinuxSampler yet. That's  
       because the used <code>wait()</code> function is not fully implemented  
       yet. Currently a <code>wait()</code> function call suspends execution,  
       but since the respective scheduler code is yet missing, the script  
       will automatically be resumed with the next audio fragment cycle. So  
       effectively a <code>wait()</code> call will pause your script for a few  
       miliseconds with LinuxSampler right now, no matter which function argument  
       you provided. Hopefully this will be implemented soon though.  
     </note>  
477      <code>      <code>
478  on init  on init
479    { The amount of notes to play }    { The amount of notes to play }
# Line 478  end on Line 528  end on
528        happening when executing that script exactly: Each time you play a note        happening when executing that script exactly: Each time you play a note
529        on your keyboard, a new instance of the <code>note</code> event handler        on your keyboard, a new instance of the <code>note</code> event handler
530        will be spawned and executed by the sampler. In all our examples so far        will be spawned and executed by the sampler. In all our examples so far
531        our scripts were so simple, that in practice only one handler instance        our scripts were so simple, that in practice only one event handler instance
532        was executed at a time. This is different in this case though. Because        was executed at a time. This is different in this case though. Because
533        by calling the <code>wait()</code> function, the respective handler        by calling the <code>wait()</code> function, the respective handler
534        execution instance is paused for a while and in total each handler        execution instance is paused for a while and in total each handler
# Line 487  end on Line 537  end on
537        you play multiple, successive notes on your keyboard in short time, you        you play multiple, successive notes on your keyboard in short time, you
538        will have several instances of the <code>note</code> event handler running        will have several instances of the <code>note</code> event handler running
539        simultaniously. And that's where the problem starts. Because by default,        simultaniously. And that's where the problem starts. Because by default,
540        as said, all variables are global variables. So the handler instances        as said, all variables are global variables. So the event handler instances
541        which are now running in parallel, are all reading and modifying the same        which are now running in parallel, are all reading and modifying the same
542        data. Thus the individual handler instances will modify the        data. Thus the individual event handler instances will modify the
543        <code>$i</code> and <code>$velocity</code> variables of each other, causing        <code>$i</code> and <code>$velocity</code> variables of each other, causing
544        an undesired misbehavior.        an undesired misbehavior.
545      </p>      </p>
# Line 772  on note Line 822  on note
822        @postfix := "nd"        @postfix := "nd"
823      case 3      case 3
824        @postfix := "rd"        @postfix := "rd"
825    end if    end select
826    
827    message("This is the " & $numberOfNotes & @postfix & " note triggered so far.")    message("This is the " & $numberOfNotes & @postfix & " note triggered so far.")
828  end on  end on
# Line 813  on note Line 863  on note
863      case 3      case 3
864        message("Third note was triggered!") { Will never be printed ! }        message("Third note was triggered!") { Will never be printed ! }
865        exit        exit
866    end if    end select
867    
868    message("Wow, already the " & $numberOfNotes & "th note triggered.")    message("Wow, already the " & $numberOfNotes & "th note triggered.")
869  end on  end on
# Line 852  on note Line 902  on note
902      case 1 to 99      case 1 to 99
903        message("Less than 100 notes triggered so far")        message("Less than 100 notes triggered so far")
904        exit        exit
905    end if    end select
906    
907    message("Wow, already the " & $numberOfNotes & "th note triggered.")    message("Wow, already the " & $numberOfNotes & "th note triggered.")
908  end on  end on
# Line 932  end on Line 982  end on
982        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
983        three times in total.        three times in total.
984      </p>      </p>
985    
986        <h3>User Functions</h3>
987        <p>
988          We already came across various built-in functions, which you may call
989          by your scripts to perform certain tasks or behavior which is already
990          provided for you by the sampler. NKSP also allows you to write your
991          own functions, which you then may call from various places of your
992          script.
993        <p>  
994        </p>
995          When working on larger scripts, you
996          may notice that you easily get to the point where you may have to
997          duplicate portions of your script code, since there are certain things
998          that you may have to do again and again in different parts of your script.
999          Software developers usually try to avoid such code duplications to
1000          keep the overall amount of code as small as possible, since the
1001          overall amount of code would bloat quickly and would
1002          make the software very hard to maintain. One way for you to avoid such
1003          script code duplications with NKSP is to write so called <i>User Functions</s>.
1004        </p>
1005        <p>
1006          Let's assume you wanted to create a simple stuttering effect. You may do so
1007          like in the following example.
1008        </p>
1009        <code>
1010    on note
1011      while (1)
1012        wait(200000)
1013        if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE))
1014          exit()
1015        end if
1016        change_vol($EVENT_ID, -20000)  { Reduce volume by 20 dB. }
1017        wait(200000)
1018        if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE))
1019          exit()
1020        end if
1021        change_vol($EVENT_ID, 0)  { Increase volume to 0 dB. }
1022      end while
1023    end on
1024        </code>
1025        <p>
1026          This script will run an endless loop for each note being triggered.
1027          Every <code lang="none">200ms</code> it will turn the volume alternatingly down and
1028          up to create the audible stuttering effect. After each <code lang="nksp">wait()</code>
1029          call it calls <code>event_status($EVENT_ID)</code> to check whether
1030          this note is still alive, and as soon as the note died, it will stop
1031          execution of the script instance by calling <code>exit()</code>. The latter
1032          is important in this example, because otherwise the script execution instances would
1033          continue to run in this endless loop forever, even after the respectives
1034          notes are gone. Which would let your CPU usage increase with every new note
1035          and would never decrease again.
1036          This behavior of the sampler is not a bug, it is intended, since there may
1037          also be cases where you want to do certain things by script even after the
1038          respective notes are dead and gone. However as you can see, that script is
1039          using the same portions of script code twice. To avoid that, you could also
1040          write the same script with a user function like this:
1041        </p>
1042        <code>
1043    function pauseMyScript
1044      wait(200000)
1045      if (not (event_status($EVENT_ID) .and. $EVENT_STATUS_NOTE_QUEUE))
1046        exit()
1047      end if
1048    end function
1049            
1050    on note
1051      while (1)
1052        call pauseMyScript
1053        change_vol($EVENT_ID, -20000)  { Reduce volume by 20 dB. }
1054        call pauseMyScript
1055        change_vol($EVENT_ID, 0)  { Increase volume back to 0 dB. }
1056      end while
1057    end on
1058        </code>
1059        <p>
1060          The script became in this simple example only slightly smaller, but it also
1061          became easier to read and behaves identically to the previous solution.
1062          And in practice, with a more complex script, you can
1063          reduce the overall amount of script code a lot this way. You can choose any
1064          name for your own user functions, as long as the name is not already
1065          reserved by a built-in function. Note that for calling a user function,
1066          you must always precede the actual user function name with the
1067          <code>call</code> keyword. Likewise you may however not use the
1068          <code>call</code> keyword for calling any built-in function. So that
1069          substantially differs calling built-in functions from calling user functions.
1070        </p>
1071    
1072        <h3>Synchronized Blocks</h3>
1073        <p>
1074          When we introduced the <a href="#polyphonic_variables">polyphonic keyword</a>
1075          previously, we learned that a script may automatically be suspended by
1076          the sampler at any time and then your script is thus sleeping for an
1077          arbitrary while. The sampler must do such auto suspensions under certain
1078          situations in cases where an instrument script may become a hazard for the
1079          sampler's overall real-time stability. If the sampler would not do so, then
1080          instrument scripts might easily cause audio dropouts, or at worst, buggy
1081          instrument scripts might even lock up the entire sampler in an endless
1082          loop. So auto suspension is an essential feature of the sampler's real-time
1083          instrument script engine.
1084        </p>
1085        <p>
1086          Now the problem as a script author is that you don't really know beforehand
1087          why and when your script might get auto suspended by the sampler. And when
1088          you are working on more complex, sophisticated scripts, you will notice
1089          that this might indeed be a big problem in certain sections of your scripts.
1090          Because in practice, a sophisticated script often has at least one certain
1091          consecutive portion of statements which must be executed in strict consecutive order
1092          by the sampler, which might otherwise cause concurrency issues and thus
1093          misbehavior of your script if that sensible code section was auto suspended
1094          in between. A typical example of such concurrency sensible code sections are
1095          statements which are reading and conditionally modifying global variables.
1096          If your script gets auto suspended in such a code section, another
1097          script handler instance might then interfere and change those global
1098          variables in between.
1099        </p>
1100        <p>
1101          To avoid that, you can place such a sensible code section at the very beginning
1102          of your event handler. For example consider you might be writing a custom
1103          <i title="A consecutive pitch glide from one note to another note.">glissando</i>
1104          script starting like this:
1105        </p>
1106        <code>
1107    on init
1108      declare $keysDown
1109      declare $firstNoteID
1110      declare $firstNoteNr
1111      declare $firstVelocity
1112    end on
1113    
1114    on note
1115      { The concurrency sensible code section for the "first active" note. }
1116      inc($keysDown)
1117      if ($keysDown = 1 or event_status($firstNoteID) = $EVENT_STATUS_INACTIVE)
1118        $firstNoteID = $EVENT_ID
1119        $firstNoteNr = $EVENT_NOTE
1120        $firstVelocity = $EVENT_VELOCITY
1121        exit { return from event handler here }
1122      end if
1123    
1124      { The non-sensible code for all other subsequent notes would go here. }
1125    end on
1126    
1127    on release
1128      dec($keysDown)
1129    end on
1130        </code>
1131        <p>
1132          Because the earlier statements are executed in an event handler, the higher
1133          the chance that they will never get auto suspended. And with those couple of
1134          lines in the latter example you might even be lucky that it won't ever get
1135          suspended in that sensible code section at least. However when it comes to live
1136          concerts you don't really want to depend on luck, and in practice such a
1137          sensible code section might be bigger than this one.
1138        </p>
1139        <p>
1140          That's why we introduced <code>synchronized</code> code blocks for the
1141          NKSP language, which have the following form:
1142        </p>
1143        <code>
1144    synchronized
1145    
1146      ??statements??
1147    
1148    end synchronized
1149        </code>
1150        <p>
1151          All <code>??statements??</code> which you put into such a synchronized
1152          code block are guaranteed that they will never get auto suspended by
1153          the sampler.
1154        </p>
1155        <note>
1156          Such <code>synchronized</code> blocks are a language extension which
1157          is only available with NKSP. KSP does not support <code>synchronized</code> blocks.
1158        </note>
1159        <p>
1160          So to make our previous example concurrency safe, we would
1161          change it like this:
1162        </p>
1163        <code>
1164    on init
1165      declare $keysDown
1166      declare $firstNoteID
1167      declare $firstNoteNr
1168      declare $firstVelocity
1169    end on
1170    
1171    on note
1172      { The concurrency sensible code section for the "first active" note. }
1173      synchronized
1174        inc($keysDown)
1175        if ($keysDown = 1 or event_status($firstNoteID) = $EVENT_STATUS_INACTIVE)
1176          $firstNoteID = $EVENT_ID
1177          $firstNoteNr = $EVENT_NOTE
1178          $firstVelocity = $EVENT_VELOCITY
1179          exit { return from event handler here }
1180        end if
1181      end synchronized
1182    
1183      { The non-sensible code for all other subsequent notes would go here. }
1184    end on
1185    
1186    on release
1187      dec($keysDown)
1188    end on
1189        </code>
1190        <p>
1191          If you are already familiar with some programming languages, then you
1192          might already have seen such synchronized code block concepts
1193          in languages like e.g. Java. This technique really provides an easy way
1194          to protect certain sections of your script against concurrency issues.
1195        </p>
1196        <note class="important">
1197          You <b>must</b> use such <code>synchronized</code> code blocks only with great
1198          care! If the amount of statements being executed in your synchronized block
1199          is too large, then you will get audio dropouts. If you even use loops in
1200          synchronized code blocks, then the entire sampler might even become
1201          unresponsive in case your script is buggy!
1202        </note>
1203    
1204      <h2>Operators</h2>      <h2>Operators</h2>
1205      <p>      <p>
1206        A programming language provides so called <i>operators</i> to perform        A programming language provides so called <i>operators</i> to perform
# Line 962  end on Line 1230  end on
1230      <h3>Boolean Operators</h3>      <h3>Boolean Operators</h3>
1231      <p>      <p>
1232        To perform logical transformations of <i>boolean</i> data, you may use the        To perform logical transformations of <i>boolean</i> data, you may use the
1233        following boolean operators:        following logical operators:
1234      </p>      </p>
1235      <code>      <code>
1236  on init  on init
# Line 975  on init Line 1243  on init
1243  end on  end on
1244      </code>      </code>
1245      <p>      <p>
1246        Remember that with boolean operations, all integer values other than <code>0</code>        Keep in mind that with logical operators shown above,
1247          all integer values other than <code>0</code>
1248        are interpreted as boolean <i>true</i> while an integer value of        are interpreted as boolean <i>true</i> while an integer value of
1249        precisely <code>0</code> is interpreted of being boolean <i>false</i>.        precisely <code>0</code> is interpreted as being boolean <i>false</i>.
1250        </p>
1251        <p>
1252          So the logical operators shown above always look at numbers at a whole.
1253          Sometimes however you might rather need to process numbers bit by bit. For
1254          that purpose the following bitwise operators exist.
1255        </p>
1256        <code>
1257    on init
1258      message("1 .and. 1 is " & 1 .and. 1)  { bitwise "and" }
1259      message("1 .and. 0 is " & 1 .and. 0)  { bitwise "and" }
1260      message("1 .or. 1 is " & 1 .or. 1)    { bitwise "or" }
1261      message("1 .or. 0 is " & 1 .or. 0)    { bitwise "or" }
1262      message(".not. 1 is " & .not. 1)      { bitwise "not" }
1263      message(".not. 0 is " & .not. 0)      { bitwise "not" }
1264    end on
1265        </code>
1266        <p>
1267          Bitwise operators work essentially like logical operators, with the
1268          difference that bitwise operators compare each bit independently.
1269          So a bitwise <code>.and.</code> operator for instance takes the 1st bit
1270          of the left hand's side value, the 1st bit of the right hand's side value,
1271          compares the two bits logically and then stores that result as 1st bit of
1272          the final result value, then it takes the 2nd bit of the left hand's side value
1273          and the 2nd bit of the right hand's side value, compares those two bits logically
1274          and then stores that result as 2nd bit of the final result value, and so on.
1275      </p>      </p>
1276    
1277            
1278      <h3>Comparison Operators</h3>      <h3>Comparison Operators</h3>
1279      <p>      <p>
# Line 998  end on Line 1293  end on
1293      </code>      </code>
1294      <p>      <p>
1295        All these operations yield in a <i>boolean</i> result which could then        All these operations yield in a <i>boolean</i> result which could then
1296        by used i.e. with <code>if</code> or <code>while</code> loop statements.        be used e.g. with <code>if</code> or <code>while</code> loop statements.
1297      </p>      </p>
1298            
1299      <h3>String Operators</h3>      <h3>String Operators</h3>
# Line 1086  RESET_CONDITION(??condition-name??) Line 1381  RESET_CONDITION(??condition-name??)
1381        You should only reset a preprocessor condition that way if you did set it        You should only reset a preprocessor condition that way if you did set it
1382        with <code>SET_CONDITION(??condition-name??)</code> before. Trying to        with <code>SET_CONDITION(??condition-name??)</code> before. Trying to
1383        reset a condition that has not been set before, or trying to reset a        reset a condition that has not been set before, or trying to reset a
1384        condition that has already been reset, will both be ignored by the samlper,        condition that has already been reset, will both be ignored by the sampler,
1385        but again you will get a warning, and you should take care about it.        but again you will get a warning, and you should take care about it.
1386      </p>      </p>
1387            
# Line 1254  end on Line 1549  end on
1549        use the preprocessor instead for such things. And like stated above,        use the preprocessor instead for such things. And like stated above,
1550        there are certain things which you can only achieve with the preprocessor.        there are certain things which you can only achieve with the preprocessor.
1551      </p>      </p>
1552        
1553        <h3>Disable Messages</h3>
1554        <p>
1555          Since it is quite common to switch a script between a development version
1556          and a production version, you actually don't need to wrap all your
1557          <code>message()</code> calls into preprocessor statements like in the
1558          previous example just to disable messages. There is actually a built-in
1559          preprocessor condition dedicated to perform that task much more conveniently for you.
1560          To disable all messages in your script, simply add <code>SET_CONDITION(NKSP_NO_MESSAGE)</code>
1561          e.g. at the very beginning of your script.
1562          So the previous example can be simplified to this:
1563        </p>
1564        <code>
1565    { Enable debug mode, so show all debug messages. }
1566    SET_CONDITION(DEBUG_MODE)
1567    
1568    { If our user declared condition "DEBUG_MODE" is not set ... }
1569    USE_CODE_IF_NOT(DEBUG_MODE)
1570      { ... then enable this built-in condition to disable all message() calls. }
1571      SET_CONDITION(NKSP_NO_MESSAGE)
1572    END_USE_CODE
1573    
1574    on init
1575      declare const %primes[12] :=  ( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 )
1576      declare $i
1577    
1578      message("This script has just been loaded.")
1579    
1580      USE_CODE_IF(DEBUG_MODE)
1581      $i := 0
1582      while ($i < num_elements(%primes))
1583        message("Prime " & $i & " is " & %primes[$i])
1584        $i := $i + 1
1585      end while
1586      END_USE_CODE
1587    end on
1588    
1589    on note
1590      message("Note " & $EVENT_NOTE & " was triggered with velocity " & $EVENT_VELOCITY)
1591    end on
1592    
1593    on release
1594      message("Note " & $EVENT_NOTE & " was released with release velocity " & $EVENT_VELOCITY)
1595    end on
1596    
1597    on controller
1598      message("MIDI Controller " & $CC_NUM " changed its value to " & %CC[$CC_NUM])
1599    end on
1600        </code>
1601        <p>
1602          You can then actually also add <code>RESET_CONDITION(NKSP_NO_MESSAGE)</code>
1603          at another section of your script, which will cause all subsequent
1604          <code>message()</code> calls to be processed again. So that way you can
1605          easily enable and disable <code>message()</code> calls of entire individual
1606          sections of your script, without having to wrap all <code>message()</code>
1607          calls into preprocessor statements.
1608        </p>
1609    
1610      <h2>What Next?</h2>      <h2>What Next?</h2>
1611      <p>      <p>
1612        You have completed the introduction of the NKSP real-time instrument        You have completed the introduction of the NKSP real-time instrument
# Line 1264  end on Line 1616  end on
1616        Which provides you an overview and quick access to the details of all        Which provides you an overview and quick access to the details of all
1617        built-in functions, built-in variables and more.        built-in functions, built-in variables and more.
1618      </p>      </p>
1619        <p>
1620          You might also be interested to look at new <i>NKSP</i> core language
1621          features being added to the latest development version of the sampler:
1622          <a href="real_unit_final/01_nksp_real_unit_final.html">
1623            Real Numbers, Units and Finalness ...
1624          </a>
1625        </p>
1626    
1627    </body>    </body>
1628  </html>  </html>

Legend:
Removed from v.2763  
changed lines
  Added in v.3702

  ViewVC Help
Powered by ViewVC