1 |
<html> |
2 |
<head> |
3 |
<meta name="author" content="Christian Schoenebeck"> |
4 |
<title>Real Numbers, Units and Finalness</title> |
5 |
<urlpath>Real_Numbers_Units_and_Finalness</urlpath> |
6 |
<meta name="description" content="New NKSP Core Language Features: Support for real numbers, standard measuring units and finalness."> |
7 |
<link rel="stylesheet" href="http://doc.linuxsampler.org/css/preview.css"> |
8 |
<script type="text/javascript" src="http://doc.linuxsampler.org/js/preview.js"></script> |
9 |
</head> |
10 |
<body> |
11 |
<p> |
12 |
As you might have seen from our change log, I've been recently working on |
13 |
a bunch of new core features for our <a href="01_nksp.html">NKSP</a> |
14 |
real-time instrument script engine, with the goal to make instrument |
15 |
scripting more intuitive and less error prone, especially from a |
16 |
musician's point of view. |
17 |
</p> |
18 |
<p> |
19 |
The changes are quite substantial, so here is |
20 |
a more detailed description of what's new, how to use those new |
21 |
features, what's the motivation behind them, and also a discourse |
22 |
about some of the associated language design (and implementation) aspects. |
23 |
</p> |
24 |
<note class="important"> |
25 |
Features described in this article refer to LinuxSampler version <b>2.1.1.svn16</b> (or higher). |
26 |
So these features are not available in older versions of the sampler. |
27 |
And since these are new development features, they still might be subject to change. |
28 |
</note> |
29 |
|
30 |
<h2 id="64bit">64-Bit Integers</h2> |
31 |
<p> |
32 |
First of all, integers, i.e. integer number literals (as e.g. <code lang="nksp">4294967295</code>), integer |
33 |
variables (like <code lang="nksp">declare $foo := 4294967295</code>), or |
34 |
integer array variables (like <code>declare %bar[3] := ( 1, 2, 3 ) </code>), |
35 |
and all their arithmetics like |
36 |
<code lang="nksp">($foo + 1024) / 24</code> and all built-in functions (as e.g. |
37 |
<code>min()</code>), are now all 64 bit with <a href="01_nksp.html">NKSP</a>.<br> |
38 |
<br> |
39 |
I hear your "<i>Yaaawn</i>" at this point. You might be surprised though about the amount of |
40 |
<a href="https://en.wikipedia.org/wiki/Diff">diff</a> involved |
41 |
and how often people stumbled over undesired 32-bit truncation with their |
42 |
scripts before. So that change alone reduced error-proneness tremendously. |
43 |
But let's get on. |
44 |
</p> |
45 |
|
46 |
<h2 id="real_numbers">Real Numbers</h2> |
47 |
<p> |
48 |
You are finally no longer limited to integer math with <a href="01_nksp.html">NKSP</a>. |
49 |
You can now also use floating point arithmetics which will make calculations, |
50 |
that is mathematical formulas in your scripts much easier than before. |
51 |
Sounds a bit more interesting, doesn't it?<br> |
52 |
</p> |
53 |
|
54 |
<h3 id="real_variables">Variables</h3> |
55 |
<p> |
56 |
We call those floating point numbers |
57 |
<i title="One of the most important classes of numbers in mathematics where each <b>real number</b> represents a continous quantity qualified for reflecting a distance on a line, and hence real numbers are commonly used for the numerical value of measurements of physical quantities like e.g. length, temperature, mass, velocity."> |
58 |
real numbers |
59 |
</i> from now on and you can |
60 |
write them like you probably already expected; in simple dotted notation like |
61 |
<code>2.98</code>. Likewise there are new variable types for real numbers as well. |
62 |
The syntax to declare a real number variable is: |
63 |
</p> |
64 |
<p> |
65 |
<code lang="nksp"> |
66 |
declare ~??real-variable-name?? := ??initial-value?? |
67 |
</code> |
68 |
</p> |
69 |
<p> |
70 |
Like e.g.: |
71 |
</p> |
72 |
<p> |
73 |
<code lang="nksp"> |
74 |
declare ~foo := 3.14159265 |
75 |
</code> |
76 |
</p> |
77 |
<p> |
78 |
So it looks pretty much the same as with integer variables, just that you use |
79 |
"~" as prefix in front of the variable name instead of "$" that you would |
80 |
use for integer variables <b>and</b> the values <b>must always</b> contain a dot so that the parser |
81 |
can distinguish them clearly from integer numbers. |
82 |
Moreover there is now also a real number array variable type which you can |
83 |
declare like this: |
84 |
</p> |
85 |
<p> |
86 |
<code lang="nksp"> |
87 |
declare ???real-array-variable-name??[??amount-of-elements??] := ( ??initial-values?? ) |
88 |
</code> |
89 |
</p> |
90 |
<p> |
91 |
Like e.g.: |
92 |
</p> |
93 |
<p> |
94 |
<code lang="nksp"> |
95 |
declare ?foo[4] := ( 0.1, 2.0, 46.238, 104.97 ) |
96 |
</code> |
97 |
</p> |
98 |
<p> |
99 |
Once again, the only differences to integer array variables are that you use |
100 |
"?" as prefix in front of the array variable name instead of "%" that you |
101 |
would use for integer array variables, <b>and</b> that you <b>must always</b> use a |
102 |
dot for each value being assigned. |
103 |
And as with integer variables, if you omit to assign initial value(s) for |
104 |
your real number variables or real array variables then they are automatically |
105 |
initialized with zero value(s) (that is <code>0.0</code> actually). |
106 |
</p> |
107 |
<note class="remark"> |
108 |
I actually already had plans for implementing floating point support in |
109 |
<i title="NKSP stands for 'is <b>N</b>ot <b>KSP</b>', which denotes its distinction to an existing proprietary language called <i>KSP</i>. NSKP is a script language specifically designed to write real-time capable software extensions to LinuxSampler's sampler engines that can be bundled individually with sounds by sound designers themselves.">NKSP</i> |
110 |
much earlier, but I somehow had the feeling that <i>KSP</i> would add it as well. |
111 |
And I though before "inventing" again some kind of new syntax set for this feature |
112 |
and then having to somehow merge and maintain cross-compatibility between <i>KSP</i> syntax |
113 |
and <i>NKSP</i> syntax, I decided to wait a bit, and it |
114 |
eventually appeared now on <i>KSP</i> side, so it was a good point to finally fill |
115 |
this gap in <i>NKSP</i>. |
116 |
</note> |
117 |
|
118 |
<h3 id="type_casting">Type Casting</h3> |
119 |
<p> |
120 |
Like <i>KSP</i> we are (currently) quite strict about your obligation to distinguish |
121 |
clearly between integer numbers and real numbers with <i>NKSP</i>. That means blindly |
122 |
mixing integers and real numbers e.g. in formulas, will currently cause a parser error |
123 |
like in this example: |
124 |
</p> |
125 |
<p> |
126 |
<code>~foo := (~bar + 1.9) / 24 { WRONG! }</code> |
127 |
</p> |
128 |
<p> |
129 |
In this example you would simply use <code>24.0</code> instead of <code>24</code> to |
130 |
fix the parser error: |
131 |
</p> |
132 |
<p> |
133 |
<code>~foo := (~bar + 1.9) / 24.0 { correct }</code> |
134 |
</p> |
135 |
<p> |
136 |
That's because, when you are mixing integer numbers and real numbers in mathematical |
137 |
operations, like the division in the latter example, what was your intended data type that you |
138 |
expected of the result of that division; a real number or an integer result? Because it |
139 |
would not only mean a different data type, it might certainly also mean a completely |
140 |
different result value accordingly. |
141 |
</p> |
142 |
<p> |
143 |
That does not mean you were not allowed to mix real numbers with integers, it is just |
144 |
that you have to make your point clear to the parser what your intention is. For that |
145 |
purpose there are now 2 new built-in functions <code>int_to_real()</code> and |
146 |
<code>real_to_int()</code> which you may use for required type casts (data type conversions). |
147 |
So let's say you have a mathematical formula where you want to mix that formula with |
148 |
a real number variable and an integer variable, then you might e.g. type cast the |
149 |
integer variable like this: |
150 |
</p> |
151 |
<p> |
152 |
<code>~bla := ~foo / int_to_real($bar)</code> |
153 |
</p> |
154 |
<p> |
155 |
And since this is a very common thing to do, we also have 2 short-hand forms of these |
156 |
2 built-in functions in <i>NKSP</i> which are simply <code>real()</code> and <code>int()</code>: |
157 |
</p> |
158 |
<p> |
159 |
<code>~bla := ~foo / real($bar) { same as above, just shorter } </code> |
160 |
</p> |
161 |
<note> |
162 |
The short-hand functions <code>real()</code> and <code>int()</code> only exist in |
163 |
<i>NKSP</i>. They don't exist with <i>KSP</i>. |
164 |
</note> |
165 |
<note class="remark"> |
166 |
In future we might certainly lift this data type strictness and do it like many other |
167 |
programming languages handle this: just showing a parser warning (not an error) on mixed |
168 |
integer vs. real number expressions, and at the same time performing always an implied type cast |
169 |
of the respective integer to a real number type automatically by the compiler. |
170 |
</note> |
171 |
|
172 |
<h3>Built-in Functions</h3> |
173 |
<p> |
174 |
What about real numbers and existing built-in functions? When you check our latest reference |
175 |
documentation of <a href="01_nksp_reference.html">NKSP built-in functions</a>, |
176 |
you will notice that most of them accept now both, integers and real numbers as arguments |
177 |
to their function calls. You should be aware though that the precise acceptance of data |
178 |
types and the resulting behaviour change, varies between the individual built-in functions, |
179 |
which is due to the difference in purpose of all those numerous built-in functions. |
180 |
</p> |
181 |
<p> |
182 |
For instance the data type of the result returned by <code>min()</code> and <code>max()</code> |
183 |
function calls depends now on the data type being passed to those functions. That is |
184 |
if you pass real numbers to those 2 functions then you'll get a real number as result; |
185 |
if you pass integers instead then you'll get an integer as result instead. |
186 |
</p> |
187 |
<p> |
188 |
Then there are functions, like e.g. the new math functions <code>sin()</code>, <code>cos()</code>, |
189 |
<code>tan()</code>, <code>sqrt()</code>, which only accept real numbers as arguments (and |
190 |
always return a real number as result). Trying to pass integers will cause a parser error, |
191 |
because those particular functions are not really useful on integers at all. |
192 |
</p> |
193 |
<p> |
194 |
Likewise the previously already existing functions <code>fade_in()</code> and <code>fade_out()</code> |
195 |
accept now both integers and real numbers for their 2nd argument (<code>??duration-us??</code>), |
196 |
but do not allow real numbers for their 1st argument (<code>??note-id??</code>), because for |
197 |
a duration real numbers make sense, whereas for a <code>??note-id??</code> |
198 |
real numbers would not make any sense and such an attempt is usually a result of some |
199 |
programming error, hence you will get a parser error when trying to pass a real number |
200 |
to the 1st argument of those 2 built-in functions. |
201 |
</p> |
202 |
<p> |
203 |
There might also be differences how built-in functions handle mixed usage of integers |
204 |
and real numbers as arguments, simultaniously for the same function call that is. |
205 |
For instance |
206 |
the <code>min()</code> and <code>max()</code> functions are very permissive and allow you to mix |
207 |
an integer argument with a real number argument. In such mixed cases those 2 functions |
208 |
will simply handle the integer argument as if it was a real number and hence the |
209 |
result's data type would be a real number. So this would be Ok: |
210 |
</p> |
211 |
<p> |
212 |
<code> |
213 |
min(0.3, 300) { OK for this function: mixed real and integer arguments } |
214 |
</code> |
215 |
</p> |
216 |
<p> |
217 |
|
218 |
Yet other functions, |
219 |
like the <code>search()</code> |
220 |
function, are very strict regarding data type. So if you are passing an integer array as 1st argument to |
221 |
the <code>search()</code> function then it only accepts an integer (scalar) as |
222 |
2nd argument, and likewise if you are passing a real number array as 1st argument |
223 |
then it only accepts a real number (scalar) as 2nd argument. Attempts passing |
224 |
different types, or in a different way to that function, will cause a parser error. |
225 |
</p> |
226 |
<note> |
227 |
Use common sense! The accepted data types of arguments and correspending |
228 |
result's data type of built-in functions usually match with your intuition, |
229 |
and if it does not for some reason, then |
230 |
you always get a clear parser error message immediately when trying to pass a wrong data |
231 |
type while typing your scripts (e.g. in Gigedit's script editor). And on doubt you can |
232 |
always refer to the <a href="01_nksp_reference.html">reference documentation</a> for |
233 |
details of course. |
234 |
</note> |
235 |
|
236 |
<h3>Comparing for Equalness</h3> |
237 |
<p> |
238 |
If you are also writing <i>KSP</i> scripts, then you probably already knew most of the things that I |
239 |
described above about real numbers. But here comes an important difference that we |
240 |
have when dealing with real numbers in <i>NKSP</i>: real number value comparison for equalness and unequalness. |
241 |
</p> |
242 |
<p> |
243 |
In our automated |
244 |
<a href="http://svn.linuxsampler.org/cgi-bin/viewvc.cgi/linuxsampler/trunk/src/scriptvm/tests/NKSPCoreLangTest.cpp?view=markup">NKSP core language test cases</a> |
245 |
you find an example that looks |
246 |
like this (slightly changed here for simplicity): |
247 |
</p> |
248 |
<p> |
249 |
<code> |
250 |
on init |
251 |
declare ~a := 0.165 |
252 |
declare ~b := 0.185 |
253 |
declare ~x := 0.1 |
254 |
declare ~y := 0.25 |
255 |
|
256 |
if (~a + ~b = ~x + ~y) |
257 |
message("Test succeeded") |
258 |
else |
259 |
message("Test failed") |
260 |
end if |
261 |
|
262 |
end on |
263 |
</code> |
264 |
</p> |
265 |
<p> |
266 |
When you add the values of those variables from this example in your head, you will see that the actual |
267 |
test in that example theoretically boils down to comparing <code>if (0.35 = 0.35)</code>. |
268 |
Hence this test should always succeed. At least |
269 |
that's what one would expect if one would do the calculations above manually by humans |
270 |
in the real world. |
271 |
In practice though, when this script is executed on a computer, the numbers on both sides would |
272 |
slightly deviate from <code>0.35</code>. These differences to the expected value are |
273 |
actually extremely little, that is very tiny fractions of several digits behind the decimal point, |
274 |
but the final consequence would still be nevertheless different values on both sides and this test "would" hence fail. |
275 |
These small errors are due to the technical way |
276 |
<a href="https://en.wikipedia.org/wiki/Floating-point_arithmetic">floating point numbers are encoded</a> |
277 |
on any modern <i>CPU</i> which causes small calculation errors with these summations for instance. |
278 |
Due to that very well known circumstance of floating point arithmetics on |
279 |
CPUs, it is commonly discouraged with system programming languages like C/C++ |
280 |
to directly compare floating point numbers for equalness, nor for unequalness for that exact reason. |
281 |
</p> |
282 |
<p> |
283 |
However the use case for the NKSP language is completely different from |
284 |
system level programming languages like C/C++. We don't need to be so |
285 |
conservative in many aspects those languages need to be. The musical context of |
286 |
<i>NKSP</i> simply has different requirements. Simplicity and high level |
287 |
handling is more important for <i>NKSP</i> than revealing bit by bit |
288 |
of the actual CPU registers bare-bone directly to users of instrument scripts. |
289 |
So I decided to implement |
290 |
real number equal (<code>=</code> operator) and unequal comparison |
291 |
(<code>#</code> operator) to automatically take the expected floating |
292 |
point tolerances of the underlying CPU into account. |
293 |
</p> |
294 |
<p> |
295 |
So in short: the |
296 |
<u>test case example above does <b>not</b> fail with our <i>NKSP</i> implementation</u>! |
297 |
</p> |
298 |
<p> |
299 |
That does not mean you can simply switch off your head when doing |
300 |
real number arithmetics and subsequent comparisons of those calculations. |
301 |
Because with every calculation you do, the total amount of calculation |
302 |
error (caused by the utilized floating point processing hardware) increases, |
303 |
so after a certain amount of subsequent calculations |
304 |
our equal/unequal comparisons would fail as well after a certain point. |
305 |
But most of the time you will have formulas which end up with a very |
306 |
limited amount of floating point calculations before you eventually |
307 |
do your comparisons, so in most cases you should just be fine. But keep |
308 |
this issue in mind when doing e.g. numeric (large amount of subsequent) |
309 |
calculations e.g. in <code>while</code> loops. |
310 |
</p> |
311 |
<p> |
312 |
What about the other comparison operators like <code><</code>, |
313 |
<code>></code>, <code><=</code>, <code>>=</code>? Well, |
314 |
those other comparison operators all behave like with system level |
315 |
programming languages. So these comparison operators currently |
316 |
do <b>not</b> take the mentioned floating point tolerances into |
317 |
account and hence they behave differently than the <code>=</code> |
318 |
and <code>#</code> operators with <i>NKSP</i>. |
319 |
The idea was that those other |
320 |
comparison operators are typically used for what mathematicians |
321 |
call "transitivity". So they are used e.g. for sorting tasks |
322 |
where there should always be a clear determinism of the |
323 |
comparison results, and where execution speed is an issue as well. |
324 |
Because the truth is also that our floating point tolerance |
325 |
aware "equal" / "unequal" comparisons come with the price of |
326 |
requiring execution of additional calculations on the underlying CPU. |
327 |
</p> |
328 |
|
329 |
<note class="remark"> |
330 |
You might wonder now, isn't this still sort of a hack? Wouldn't |
331 |
there be a better way to implement real numbers in <i>NKSP</i> so that |
332 |
all calculations would behave exactly as we would expect them from |
333 |
theoretical math? The short answer is both <b>yes</b> and <b>no</b>.<br> |
334 |
<br> |
335 |
<b>Yes</b>, we could implement support for real numbers as so called |
336 |
<a href="https://en.wikipedia.org/wiki/Computer_algebra_system">algebraic system</a>, |
337 |
which would accomplish that real number calculations would always exactly |
338 |
result as you would expect them to do from traditional mathematics, |
339 |
like certain mathematical software applications use to do it |
340 |
(e.g. <a href="https://en.wikipedia.org/wiki/Maple_(software)">Maple</a>). |
341 |
However to achieve that we could no longer utilize hardware acceleration |
342 |
of the CPU's floating point unit, because it is limited to floating point |
343 |
values of fixed precision (e.g. either 32 bit and/or 64 bit). |
344 |
Hence we would need to execute a huge amount of instructions on the CPU |
345 |
instead for every single real number calculation in scripts, so there would |
346 |
be a severe performance penalty.<br> |
347 |
<br> |
348 |
And <b>no</b>, we actually cannot do that in <i>NKSP</i> at all, because this kind of |
349 |
complex real number implementation would require memory allocations at |
350 |
runtime, which in turn would violate a key feature of <i>NKSP</i> |
351 |
scripting: its guaranteed real-time stability and runtime determinism. |
352 |
</note> |
353 |
|
354 |
<h2 id="units">Standard Measuring Units</h2> |
355 |
<p> |
356 |
If you are coming from <i>KSP</i> then you are eventually going to think next |
357 |
"WTF? What is this all about?". But hang with me, no matter how often you |
358 |
wrote instrument scripts before, you will most |
359 |
certainly regularly come into a situation like described next and we |
360 |
have a convenient fix for that. |
361 |
<p> |
362 |
|
363 |
<h3 id="unit_literals">Unit Literals</h3> |
364 |
<p> |
365 |
Let's consider you wanted to pause your script at a certain point for let's say |
366 |
1 second. Ok, you remember from the back of your head that you need to use the |
367 |
built-in <code>wait()</code> function for that, but which value do you need to |
368 |
pass exactly to achieve that 1 second break? |
369 |
Would it be <code>wait(1000)</code> |
370 |
or probably <code>wait(1000000)</code>? Of course now you reach out for the |
371 |
reference documentation at this point and eventually find out that it |
372 |
would actually be <code>wait(1000000)</code>. Not very intuitive. And |
373 |
the large amount of zeros required does not help to make your code necessarily |
374 |
more readable either, right? |
375 |
</p> |
376 |
<p> |
377 |
So what about actually writing what we had in mind at first place: |
378 |
</p> |
379 |
<p> |
380 |
<code> |
381 |
wait(1s) |
382 |
</code> |
383 |
</p> |
384 |
<p> |
385 |
It couldn't be much clearer. |
386 |
</p> |
387 |
<p> |
388 |
Or you want a break of 23 milliseconds instead? Then let's just write that! |
389 |
</p> |
390 |
<p> |
391 |
<code> |
392 |
wait(23ms) |
393 |
</code> |
394 |
</p> |
395 |
<p> |
396 |
Now let's consider another example: Say you wanted to reduce volume of some voices by 3.5 decibel. |
397 |
You remember that was something like <code>change_vol(??note??, ??volume??)</code>, |
398 |
but what would <code>??volume??</code> be exactly? Digging out the docs yet again you |
399 |
find out the correct call was <code>change_vol($EVENT_ID, -3500)</code>.<br> |
400 |
<br> |
401 |
We can do better than that: |
402 |
</p> |
403 |
<p> |
404 |
<code> |
405 |
change_vol($EVENT_ID, -3.5dB) |
406 |
</code> |
407 |
</p> |
408 |
<p> |
409 |
You rather want a slight volume increase by just 56 milli dB instead? |
410 |
</p> |
411 |
<p> |
412 |
<code> |
413 |
change_vol($EVENT_ID, +56mdB) |
414 |
</code> |
415 |
</p> |
416 |
<p> |
417 |
Or let's lower the tuning of a note by -24 Cents: |
418 |
</p> |
419 |
<p> |
420 |
<code> |
421 |
change_tune($EVENT_ID, -24c) |
422 |
</code> |
423 |
</p> |
424 |
<p> |
425 |
I'm sure you got the point. We are naturally using standard measuring |
426 |
units in our daily life without noticing their importance, but they actually help us a |
427 |
lot to give some otherwise purely abstract numbers an intuitive meaning to us. |
428 |
Hence it just made sense to add measuring units as core feature of the NKSP |
429 |
language, their built-in functions, variables and whatever you do with them. |
430 |
</p> |
431 |
|
432 |
<h3>Calculating with Units</h3> |
433 |
<p> |
434 |
Having said that, these examples above were just meant as warm up appetizer. |
435 |
Of course you can do much more with this feature than just passing them |
436 |
literally to some built-in function call as we did above so far. |
437 |
You can assign them to variables, too, like: |
438 |
</p> |
439 |
<p> |
440 |
<code> |
441 |
declare ~pitchLfoFrequency := 1.2kHz |
442 |
</code> |
443 |
</p> |
444 |
<p> |
445 |
You can use them in combinations with integers or real numbers, and of course |
446 |
you can do all mathematical calculations and comparisons that you would |
447 |
naturally be able to do in real life. For instance the following example |
448 |
</p> |
449 |
<code> |
450 |
on init |
451 |
declare $a := 1s |
452 |
declare $b := 12ms |
453 |
declare $result := $a - $b |
454 |
message("Result of calculation is " & $result) |
455 |
end on |
456 |
</code> |
457 |
</p> |
458 |
<p> |
459 |
would print the text <code>"Result of calculation is 988ms"</code> to the terminal |
460 |
(notice that <code>$a</code> and <code>$b</code> actually used different units here).<br> |
461 |
<br> |
462 |
Or the following example |
463 |
</p> |
464 |
<code> |
465 |
on init |
466 |
declare ~a := 2.0mdB |
467 |
declare ~b := 3.2mdB |
468 |
message( 4.0 * ( ~a + ~b ) / 2.0 + 0.1mdB ) |
469 |
end on |
470 |
</code> |
471 |
</p> |
472 |
<p> |
473 |
would print the text <code>"10.5mdB"</code> to the terminal.<br> |
474 |
<br> |
475 |
Or let's make this little value comparison check: |
476 |
</p> |
477 |
<p> |
478 |
<code> |
479 |
on init |
480 |
declare ~foo := 999ms |
481 |
declare ~bar := 1s |
482 |
if (~foo < ~bar) |
483 |
message("Test succeeded") |
484 |
else |
485 |
message("Test failed") |
486 |
end fi |
487 |
end on |
488 |
</code> |
489 |
</p> |
490 |
<p> |
491 |
which will succeed of course |
492 |
(notice again that <code>~foo</code> and <code>~bar</code> used different units here as well).<br> |
493 |
<br> |
494 |
So as you can see the units are not just eye candy for your code, they |
495 |
are actually interpreted actively by the script engine appropriately such that all your |
496 |
calculations, comparisons and function calls behave as |
497 |
you would expect them to do from your real-life experience. |
498 |
</p> |
499 |
|
500 |
<h3>Unit Components</h3> |
501 |
<p> |
502 |
In the examples above you might have noticed that the units' components |
503 |
were shown in different colors. That's not a glitch of the website, |
504 |
that's intentional and in fact NKSP code on this website is in general, |
505 |
automatically displayed in the same way as with e.g. Gigedit's instrument |
506 |
script editor. So what's the deal? |
507 |
</p> |
508 |
<p> |
509 |
If you take the value <code>6.8mdB</code> as an example, you have in front |
510 |
the <code>??numeric component?? = 6.8</code> of course, followed |
511 |
by the <code>??metric prefix?? = <span class="up">md</span></code> for |
512 |
"milli deci" (which is always simply some kind of multiplication factor) |
513 |
and finally the fundamental <code>??unit type?? = <span class="ut">B</span></code> for "Bel" (which actually gives the number its final meaning). |
514 |
</p> |
515 |
<p> |
516 |
So here's where language design comes into play. From language point of view both |
517 |
the <code>??numeric component??</code> and the optional <code>??metric prefix??</code> |
518 |
are runtime features which may change at any time, |
519 |
whereas the optional <code>??unit type??</code> is always |
520 |
a constant, "sticky", parse-time feature that you may never change at runtime. |
521 |
That means if you define a variable like e.g. <code>declare $foo := 1s</code> |
522 |
that variable <code>$foo</code> is now firmly tied to the unit type "seconds" for your entire script. |
523 |
You may change the variable's numeric component and metric prefix later on at any time like e.g. |
524 |
<code>$foo := 8ms</code>, but you must not change the variable ever to a different |
525 |
unit type later on like <code>$foo := 8Hz</code>. Trying to switch |
526 |
the variable to a different unit type that way will cause a parser error. |
527 |
Changing the fundamental unit type of a variable is not allowed, because it |
528 |
would change the semantical meaning of the variable. |
529 |
</p> |
530 |
<note class="remark"> |
531 |
What may look like a lousy limitation of the technical implementation |
532 |
is in fact an intentional language design decision and is actually a feature, |
533 |
called <i>determinism</i>. |
534 |
The price of this limitation of forcing unit types to be a constant parse time |
535 |
feature of variables and expressions comes with the profit of buying substantial |
536 |
error checks at parse time, and that in turn helps you to write more |
537 |
reliable instrument scripts in a shorter amount of time. For instance no |
538 |
matter how complex your mathematical formulas are in your scripts, the parser |
539 |
will always be able to check already at parse-time whether the |
540 |
final, evaluated results of your formulas and overall code that you pass to |
541 |
built-in functions, will finally be of correct unit type expected by the |
542 |
respective function that you are going to call with them as function arguments. |
543 |
Or in other words: the parser is able to check the correct meaning of your formulas at parse-time. |
544 |
So the parser will stop you immediately |
545 |
from doing such and similar mistakes by raising a parser error immediately while you are typing |
546 |
your script code. So you neither |
547 |
have to load the script into the sampler, nor do you have to run and test the |
548 |
code just to spot such kind of mistakes. You will always see them instantly |
549 |
in the code editor while you are typing your code. |
550 |
</note> |
551 |
<p> |
552 |
So getting back and proceed with an early example, this code would be fine: |
553 |
</p> |
554 |
<p> |
555 |
<code> |
556 |
on note |
557 |
declare ~reduction := -3.5dB { correct unit type } |
558 |
change_vol($EVENT_ID, ~reduction) |
559 |
end note |
560 |
</code> |
561 |
</p> |
562 |
<p> |
563 |
That's Ok because the built-in function <code>change_vol()</code> |
564 |
optionally accepts the unit <code>B</code> for its 2nd argument. |
565 |
Whereas the following would immediately raise a parser error: |
566 |
</p> |
567 |
<p> |
568 |
<code> |
569 |
on note |
570 |
declare ~reduction := -3.5kHz { WRONG unit type for change_vol() call! } |
571 |
change_vol($EVENT_ID, ~reduction) |
572 |
end note |
573 |
</code> |
574 |
</p> |
575 |
<p> |
576 |
That's because using the unit type Hertz for changing volume with the |
577 |
built-in function <code>change_vol()</code> does not make any sense, |
578 |
that built-in function expects a unit type suitable for volume changes, |
579 |
not a unit type for frequencies, and hence it is clearly a |
580 |
programming mistake. So getting this error in |
581 |
practice, you may have simply picked a wrong variable by accident for |
582 |
a certain function call for instance and the parser will immediately |
583 |
point you on that undesired circumstance. |
584 |
</p> |
585 |
<p> |
586 |
As another example, you may now also use units with the built-in random number |
587 |
generating function like e.g. <code>random(100Hz, 5kHz)</code>. The function |
588 |
would then return an arbitrary value between <code>100Hz</code> and <code>5kHz</code> |
589 |
each time you call it that way, so that makes sense. But trying e.g. <code>random(100Hz, 5s)</code> |
590 |
would not make any sense and consequently you would immediately get a parser |
591 |
error that you are attempting to pass two different unit types to the <code>random()</code> function, |
592 |
which is not accepted by this particular built-in function. |
593 |
And these kinds of parse-time errors are always detected, |
594 |
no matter whether you are literally passing constant |
595 |
values like in the simple example here, but also through every other means like |
596 |
variables and complex mathematical expressions. |
597 |
</p> |
598 |
<p> |
599 |
The following tables list the unit types and metric prefixes currently supported by <i>NKSP</i>. |
600 |
</p> |
601 |
<p> |
602 |
<table> |
603 |
<tr> |
604 |
<th>Unit Type</th> <th>Description</th> <th>Purpose</th> |
605 |
</tr> |
606 |
<tr> |
607 |
<td><code>s</code></td> |
608 |
<td>short for "seconds"</td> |
609 |
<td>May be used for time durations.</td> |
610 |
</tr> |
611 |
<tr> |
612 |
<td><code>Hz</code></td> |
613 |
<td>short for "Hertz"</td> |
614 |
<td>May be used for frequencies.</td> |
615 |
</tr> |
616 |
<tr> |
617 |
<td><code>B</code></td> |
618 |
<td>short for "Bel"</td> |
619 |
<td>May be used for volume changes and other kinds of relative changes |
620 |
(e.g. depth of envelope generators).</td> |
621 |
</tr> |
622 |
</table> |
623 |
|
624 |
<table> |
625 |
<tr> |
626 |
<th>Metric Prefix</th> <th>Description</th> <th>Equivalent Factor</th> |
627 |
</tr> |
628 |
<tr> |
629 |
<td><code>u</code></td> |
630 |
<td>short for "micro"</td> |
631 |
<td>10<sup>-6</sup> = 0.000001</td> |
632 |
</tr> |
633 |
<tr> |
634 |
<td><code>m</code></td> |
635 |
<td>short for "milli"</td> |
636 |
<td>10<sup>-3</sup> = 0.001</td> |
637 |
</tr> |
638 |
<tr> |
639 |
<td><code>c</code></td> |
640 |
<td>short for "centi"</td> |
641 |
<td>10<sup>-2</sup> = 0.01</td> |
642 |
</tr> |
643 |
<tr> |
644 |
<td><code>d</code></td> |
645 |
<td>short for "deci"</td> |
646 |
<td>10<sup>-1</sup> = 0.1</td> |
647 |
</tr> |
648 |
<tr> |
649 |
<td><code>da</code></td> |
650 |
<td>short for "deca"</td> |
651 |
<td>10<sup>1</sup> = 10</td> |
652 |
</tr> |
653 |
<tr> |
654 |
<td><code>h</code></td> |
655 |
<td>short for "hecto"</td> |
656 |
<td>10<sup>2</sup> = 100</td> |
657 |
</tr> |
658 |
<tr> |
659 |
<td><code>k</code></td> |
660 |
<td>short for "kilo"</td> |
661 |
<td>10<sup>3</sup> = 1000</td> |
662 |
</tr> |
663 |
</table> |
664 |
</p> |
665 |
<p> |
666 |
Of course there are much more standard unit types and metric prefixes than |
667 |
those, but currently we only support those listed above. Simply because |
668 |
I found these listed ones to be actually useful for instrument scripts. |
669 |
</p> |
670 |
<note class="important"> |
671 |
When changing tuning, which is commonly expected by musicians in "Cents", |
672 |
like e.g.: <code>change_tune($EVENT_ID, -24c)</code>, you might have noticed |
673 |
already from the markup color here, that this is actually not handled as a unit |
674 |
type by the <i>NKSP</i> language and that's why it is not listed as |
675 |
a unit type in the table above. So tuning changes in "Cents" is actually just a value |
676 |
with metric prefix "centi" and without any unit type, since tuning changes |
677 |
in "Cents" is really just a relative multiplication factor for changing the pitch of |
678 |
a note depending on the current base frequency of the note.<br> |
679 |
<br> |
680 |
This might look a bit odd to you, it is semantically however absolutely correct |
681 |
to handle tuning changes in "Cents" that way by the language. You can still also use expressions like |
682 |
"milli Cents", e.g.: <code>change_tune($EVENT_ID, +324mc)</code>, which is also |
683 |
valid since we (currently) allow a combination of up to 2 metric prefixes with <i>NKSP</i>.<br> |
684 |
<br> |
685 |
The obvious advantage of not making "Cents" a dedicated unit type is that we can |
686 |
just use the character "c" in scripts both for tuning changes, as well as for conventional |
687 |
"centi" metric usage like <code>1cs</code> ("one centi second"). |
688 |
The downside of this design decision (that is "Cents" being defined as metric prefix) on the other hand |
689 |
means that we loose the previously described parse-time stickyness feature that we |
690 |
would have with "real" unit types, and hence also loose some of the described |
691 |
error detection mechanisms that we have with "real" unit types at parse time.<br> |
692 |
<br> |
693 |
<u>In practice that means:</u> you need to be a bit more cautious when doing calculations |
694 |
with tuning values in "Cents" compared to other tasks like volume changes, because with every |
695 |
calculation you do in your scripts, you might accidentally drop the "Cents" from your unit, which |
696 |
eventually will cause e.g. the <code>change_tune()</code> function to |
697 |
behave completely differently (since a value without any metric prefix |
698 |
will then be interpreted by <code>change_tune()</code> to be a value in "milli cents", |
699 |
exactly like this function did before introduction of units feature in <i>NKSP</i>). |
700 |
</note> |
701 |
|
702 |
<h3 id="unit_conversion">Unit Conversion</h3> |
703 |
<p> |
704 |
Even though you are not allowed to change the unit type of a variable itself |
705 |
by assignment at runtime, that does not mean there was no way to get rid of |
706 |
units or that you were unable to convert values from one unit type to a |
707 |
different unit type. You can do that very easily actually with <i>NKSP</i>, |
708 |
exactly as you learned in school; i.e. by multiplications and divisions. |
709 |
</p> |
710 |
<p> |
711 |
Let's say you have a variable <code>$someFrequency</code> that you |
712 |
use for controlling some LFO's frequency by script, and for some reason you really |
713 |
want to use the same value of that variable (for what reason ever) |
714 |
to change some volume with <code>change_vol()</code>, then all you have |
715 |
to do is dividing the existing unit type away, and multiplying it |
716 |
with the new unit type: |
717 |
</p> |
718 |
<p> |
719 |
<code> |
720 |
on note |
721 |
declare $someFrequency := 100Hz |
722 |
change_vol($EVENT_ID, $someFrequency / 1Hz * 1mdB) |
723 |
end note |
724 |
</code> |
725 |
</p> |
726 |
<p> |
727 |
Which would convert the variable's original value <code>100Hz</code> |
728 |
to <code>100mdB</code> before passing it to the <code>change_vol()</code> |
729 |
function. So this actually did 3 things: |
730 |
</p> |
731 |
<p> |
732 |
<ol> |
733 |
<li>the divsion (by <code>/ 1Hz</code>) dropped the old unit type (Hertz),</li> |
734 |
<li>the multiplication (by <code>* 1mdB</code>) added the new unit type (Bel)</li> |
735 |
<li>and that multiplication also changed the metric prefix (to milli deci) before the result is finally passed to the <code>change_vol()</code> function.</li> |
736 |
</ol> |
737 |
</p> |
738 |
<p> |
739 |
And since <code>change_vol()</code> would now receive the value |
740 |
in correct unit type, this overall solution is hence legal and accepted by the parser without any complaint. |
741 |
And this type of unit conversion does not break any parse-time determinism |
742 |
and error detection features either, since it is not touching the variable's |
743 |
unit type directly (only the temporary value eventually being passed to the <code>change_vol()</code> function here), |
744 |
and so the result of the unit conversion expressions above |
745 |
can always reliably be evaluated by the parser at parse-time. |
746 |
</p> |
747 |
<note class="important"> |
748 |
There are some intended limitations when performing unit type conversions though. |
749 |
For instance you are never allowed to multiply some unit type with another unit type |
750 |
in <i>NKSP</i>, neither different unit types like e.g. <code>100Hz * 1B</code>, nor |
751 |
with the same unit type like e.g. <code>4s * 8s</code>. That's because we don't have |
752 |
any practical usage for e.g. "square seconds" or other kinds of mixed unit types |
753 |
in instrument scripts. |
754 |
So trying to create a number or variable with more than one unit type will always |
755 |
raise a parser error. So keep that in mind and use common sense when writing |
756 |
calculations with units. And like always: the parser will always point you on |
757 |
misusage immediately. |
758 |
</note> |
759 |
|
760 |
<h3>Array Variables</h3> |
761 |
<p> |
762 |
And as we are at limitations regarding units: |
763 |
Currently <b>unit types</b> are not accepted for array variables yet. <b>Metric prefixes</b> |
764 |
are allowed though! |
765 |
</p> |
766 |
<p> |
767 |
<code> |
768 |
declare %foo[4] := ( 800, 1m, 14c, 43) { OK - metric prefixes, but no unit types } |
769 |
declare %bar[4] := ( 800s, 1ms, 14kHz, 43mdB) { WRONG - unit types not allowed for arrays yet } |
770 |
</code> |
771 |
</p> |
772 |
<p> |
773 |
Main reason for that current limitation is that unlike with scalar variables, |
774 |
accessing array variables at runtime with an index by yet another (runtime changeable) |
775 |
variable might break the previously described parse-time determinism of unit types. |
776 |
That means if we just take the array variable <code>%bar[]</code> declared above |
777 |
and would access it in our scripts with another variable like: |
778 |
</p> |
779 |
<p> |
780 |
<code> |
781 |
%bar[$someVar] |
782 |
</code> |
783 |
</p> |
784 |
<p> |
785 |
then what would that unit type of that array access be? Notice that the array variable |
786 |
<code>%bar[]</code> was initialized with 3 different unit types for its individual elements. |
787 |
So the unit type of the array access would obviously depend on the precise |
788 |
value of variable <code>$someVar</code>, which most probably will change at runtime and |
789 |
hence the compiler would not know at parse-time yet. |
790 |
</p> |
791 |
<note class="remark"> |
792 |
This limitation will most probably be lifted later on by allowing exactly one unit type |
793 |
for an array variable, so that the array would be initialized with exactly the same unit |
794 |
type for all its elements to retain the parse-time determinism that we were talking about. |
795 |
</note> |
796 |
|
797 |
<h2 id="finalness">Finalness</h2> |
798 |
<p> |
799 |
Here comes another new core language feature of <i>NKSP</i> that you certainly don't |
800 |
know from <i>KSP</i> (as it does not exist there), and which definitely requires an |
801 |
elaborate explanation of what it is about: "finalizing" some value. |
802 |
</p> |
803 |
|
804 |
<h3>Default Relativity</h3> |
805 |
<p> |
806 |
When changing synthesis parameters, these are commonly <i>relative</i> changes, depending |
807 |
on other modulation sources. For instance let's say you are using <code>change_vol()</code> |
808 |
in your script to change the volume of voices of a note, then the actual, final volume |
809 |
value being applied to the voices is not just the value that you passed to <code>change_vol()</code>, |
810 |
but rather a combination of that value and values of other modulation sources of volume |
811 |
like a constant gain setting stored with the instrument patch, as well as a continuously |
812 |
changing value coming from an amplitude LFO |
813 |
that you might be using in your instrument patch, and you might most certainly also use |
814 |
an amplitude envelope generator which will also have its impact on the final volume of course. |
815 |
All these individual volume values are multiplied with each other in real-time by the sampler's engine core |
816 |
to eventually calculate the actual, final volume to be applied to the voices, like illustrated in the following |
817 |
schematic figure. |
818 |
</p> |
819 |
<img src="nksp_multi_mods_rel.png" caption="Relative Modulation (Default Behaviour)"> |
820 |
<p> |
821 |
This <i>relative</i> handling of synthesis parameters is a good thing, because multiple |
822 |
modulation sources combined make up a vivid sound. However there are situations where this |
823 |
combined behaviour for synthesis parameters is not what you want. Sometimes you want to be |
824 |
able to just say in your script e.g. "Make the volume of those voices exactly -6dB. Period. I mean it!". |
825 |
And that's exactly what the newly introduced "final" operator <code>!</code> does. |
826 |
</p> |
827 |
|
828 |
<h3>Final Operator</h3> |
829 |
<p> |
830 |
<code> |
831 |
on note |
832 |
declare $volume := -6dB |
833 |
change_vol($EVENT_ID, !$volume) { '!' makes value read from variable $volume to become 'final' } |
834 |
end note |
835 |
</code> |
836 |
</p> |
837 |
<p> |
838 |
By prepending an exclamation mark <code>!</code> in front of an expression as shown in the code above, |
839 |
you mark that value of that expression to be "final", |
840 |
wich means the value will bypass the values of all other modulation sources, so the |
841 |
sampler will ignore all other modulation sources that may exist, and |
842 |
will simply use your script's value exclusively for that synthesis parameter, |
843 |
as illustrated in the following figure: |
844 |
</p> |
845 |
<img src="nksp_multi_mods_fin.png" caption="Force 'Finalness' by Script"> |
846 |
<p> |
847 |
You can of course revert back at any time to let the sampler process that synthesis parameter |
848 |
relatively again by calling <code>change_vol()</code> and just passing |
849 |
a value for volume without "finalness" (i.e. without <code>!</code> operator) this time. |
850 |
</p> |
851 |
<p> |
852 |
In the previous code example, the "finalness" was applied to the temporary value |
853 |
being passed to the <code>change_vol()</code> function, it did not change |
854 |
the information stored in variable <code>$volume</code> at all though. So this is different |
855 |
from: |
856 |
</p> |
857 |
<p> |
858 |
<code> |
859 |
on note |
860 |
declare $volume := !-6dB { store 'finalness' directly to variable $volume } |
861 |
change_vol($EVENT_ID, $volume) |
862 |
end note |
863 |
</code> |
864 |
</p> |
865 |
<p> |
866 |
In the latter code example the actual "finalness" is stored directly now |
867 |
to the <code>$volume</code> variable instead. Both approaches |
868 |
make sense depending on the actual use case. For instance if you only |
869 |
need "finalness" in rare situations, then you might use the prior |
870 |
solution by using the "final" operator just with the respective function call, |
871 |
whereas in use cases where you would always apply the |
872 |
<code>$volume</code> "finally" and probably need to pass it to several |
873 |
<code>change_vol()</code> function calls at several places in your script, |
874 |
then you might store the "finalness" information directly to the variable instead. |
875 |
</p> |
876 |
<note class="remark"> |
877 |
<i>KSP</i> is also using the exclamation mark in front of variable names of string arrays. |
878 |
Our usage of the exclamation mark character for this "finalness" feature |
879 |
does not cause a language conflict with |
880 |
that aspect though, because variable names (i.e. containing exclamation mark) are |
881 |
resolved by the language before our unary <code>!</code> "final" operator is resolved in |
882 |
expressions. |
883 |
</note> |
884 |
|
885 |
<h3>Mixed Finalness</h3> |
886 |
<p> |
887 |
Like with the other new language features described previously above, we also |
888 |
have some potential ambiguities that we need to deal with when applying "finalness". |
889 |
For instance consider this code: |
890 |
</p> |
891 |
<p> |
892 |
<code> |
893 |
on note |
894 |
declare $volume := !-6dB { store 'finalness' directly to variable $volume } |
895 |
change_vol($EVENT_ID, $volume + 2dB) { raises parser warning here ! } |
896 |
end note |
897 |
</code> |
898 |
</p> |
899 |
<p> |
900 |
Should the resulting, expected volume change of <code>-4dB</code> be applied as |
901 |
"final" value or as <i>relative</i> value instead? |
902 |
Because the problem here is that <code>!-6dB</code> obviously means "final", |
903 |
whereas </code>+ 2dB</code> is actually a <i>relative</i> value to be added. |
904 |
</p> |
905 |
<p> |
906 |
In the current version of the sampler the value to be applied in this case would be "final", so you will not get a parser error, |
907 |
however you will get a parser warning to make you aware about this ambiguity. |
908 |
So to fix the example above, that is to to get rid of that parser warning, you can simply add an exclamation |
909 |
mark in front of the other number as well like: |
910 |
</p> |
911 |
<p> |
912 |
<code> |
913 |
on note |
914 |
declare $volume := !-6dB { store 'finalness' directly to variable $volume } |
915 |
change_vol($EVENT_ID, $volume + !2dB) { '!' fixes parser warning } |
916 |
end note |
917 |
</code> |
918 |
</p> |
919 |
<p> |
920 |
Also built-in functions will behave similarly as described above. Certain built-in functions |
921 |
accept <i>finalness</i> for all of their arguments, some functions accept <i>finalness</i> for only certain |
922 |
arguments and some functions won't accept <i>finalness</i> at all. Like with the other new core language |
923 |
features always use common sense and quickly think about whether it would make sense if a |
924 |
certain function would accept <i>finalness</i> for its argument(s). Most of the time your guess will be |
925 |
right, and if not, then the parser will tell you immediately with either an error or warning, and the |
926 |
<a href="01_nksp_reference.html">NKSP built-in functions reference</a> will help you out with |
927 |
details in such rare cases where things might not be clear to you immediately. |
928 |
</p> |
929 |
|
930 |
<h3>Implied Finalness</h3> |
931 |
<p> |
932 |
Here comes the point where the feature circle of this article closes: the unit type "Bel" used |
933 |
in the examples for the "final" operator above is somewhat special, since the unit type "Bel" is |
934 |
in general used for <i>relative</i> quantities like i.e. volume changes. Tuning changes (i.e. in "Cents") are |
935 |
also relative quantities. |
936 |
</p> |
937 |
<p> |
938 |
However other unit types like "seconds" or "Hertz" are <i>absolute</i> |
939 |
quantities. That means if you are using unit types "Hertz" or "seconds" in your scripts, then their |
940 |
values are automatically applied as <i>implied</i> "final" values, as if you were using the <code>!</code> |
941 |
operator for them in your code. The parser will raise a parser warning though to point you on that |
942 |
circumstance. |
943 |
</p> |
944 |
<p> |
945 |
The following table outlines this issue for the currently supported unit types. |
946 |
</p> |
947 |
<p> |
948 |
<table> |
949 |
<tr> |
950 |
<th>Unit Type</th> <th>Relative</th> <th>Final</th> <th>Reason</th> |
951 |
</tr> |
952 |
<tr> |
953 |
<td>None</td> |
954 |
<td>Yes, by default.</td> |
955 |
<td>Yes, if <code>!</code> is used.</td> |
956 |
<td>If no unit type is used (which includes if <b>only</b> a metric prefix is used like e.g. <code>change_tune($EVENT_ID, -23c)</code>) then such values can be used both for relative, as well as for 'final' changes.</td> |
957 |
</tr> |
958 |
<tr> |
959 |
<td><code>s</code></td> |
960 |
<td>No, never.</td> |
961 |
<td>Yes, always.</td> |
962 |
<td>This unit type is naturally for absolute values only, which implies its value to be always 'final'.</td> |
963 |
</tr> |
964 |
<tr> |
965 |
<td><code>Hz</code></td> |
966 |
<td>No, never.</td> |
967 |
<td>Yes, always.</td> |
968 |
<td>This unit type is naturally for absolute values only, which implies its value to be always 'final'.</td> |
969 |
</tr> |
970 |
<tr> |
971 |
<td><code>B</code></td> |
972 |
<td>Yes, by default.</td> |
973 |
<td>Yes, if <code>!</code> is used.</td> |
974 |
<td>This unit type is naturally for relative changes. So this unit type can be used both for relative, as well as for 'final' changes.</td> |
975 |
</tr> |
976 |
</table> |
977 |
</p> |
978 |
<note class="remark"> |
979 |
Since unit types like <i>seconds</i> and <i>Hertz</i> are naturally always used for absolute values |
980 |
in real life, |
981 |
it might be considerable to drop the mentioned parser warnings which currently occur |
982 |
if those units are used in scripts without having used the <code>!</code> operator. |
983 |
</note> |
984 |
|
985 |
<h3>Array Variables</h3> |
986 |
<p> |
987 |
As with unit types, the same current restriction applies to "finalness" in conjunction with |
988 |
array variables at the moment: you may currently <b>not</b> apply "finalness" to the elements of array variables yet. |
989 |
</p> |
990 |
<p> |
991 |
<code> |
992 |
declare %foo[3] := ( !-6dB, -8dB, !2dB ) { WRONG - finalness not allowed for arrays (yet) ! } |
993 |
</code> |
994 |
</p> |
995 |
<p> |
996 |
The reason is also exactly the same, because <i>finalness</i> is a parse-time required information |
997 |
and an array access by using yet another variable like e.g. <code>%foo[$someVar]</code> might |
998 |
break that parse-time awareness of "finalness" for the compiler. |
999 |
</p> |
1000 |
<note class="remark"> |
1001 |
Likewise we might certainly lift that restriction later on by |
1002 |
allowing <i>finalness</i> to be applied to arrays by initializing <b>all</b> members of an array to be all "final". |
1003 |
</note> |
1004 |
|
1005 |
<h2>Backward Compatibility</h2> |
1006 |
<p> |
1007 |
You might be asking, what do all those new features mean to your existing instrument scripts, |
1008 |
do they break your old scripts? |
1009 |
</p> |
1010 |
<p> |
1011 |
The clear and short answer is: <b>No</b>, of course <u>they do <b>not</b> break your existing scripts</u>! |
1012 |
</p> |
1013 |
<p> |
1014 |
Our goal was always to preserve constant behaviour for existing sounds, |
1015 |
so that even ancient sound files in GigaSampler v1 format still would sound |
1016 |
exactly as you heard them originally for the 1st time many, many years ago |
1017 |
(probably with GigaSampler at that time). |
1018 |
And that means the same policy applies to instrument scripts as well of course. |
1019 |
</p> |
1020 |
<p> |
1021 |
You can also arbitrarily mix your existing instrument scripts by just partly using the new |
1022 |
features described in this article at some sections of your scripts, while |
1023 |
at the same time preserving your old code at other code sections. So these features |
1024 |
are designed that they won't break anything existing, and that they always |
1025 |
collaborate correctly in an arbitrary, mixed way with old <i>NKSP</i> code. |
1026 |
</p> |
1027 |
|
1028 |
<h2>Status Quo</h2> |
1029 |
<p> |
1030 |
That's it! For now ... |
1031 |
</p> |
1032 |
<p> |
1033 |
This is the current development state regarding these new <a href="01_nksp.html">NKSP</a> |
1034 |
core language features. It might not be the final word though. I am aware certain |
1035 |
aspects that I decided can be argued about (or maybe even entire features). |
1036 |
And that's actually one of the reasons why I decided to write this (even for my habits) |
1037 |
quite long and detailed article, which also explained the reasons for individual language design |
1038 |
decisions that I took. |
1039 |
</p> |
1040 |
<p> |
1041 |
You can however share your thoughts and arguments about these new features with us |
1042 |
on the <a href="https://sourceforge.net/projects/linuxsampler/lists/linuxsampler-devel">mailing list</a> |
1043 |
of course! |
1044 |
</p> |
1045 |
<note class="important"> |
1046 |
Keep in mind, the earlier you come up with suggestions for changes, the higher the chance |
1047 |
that it might actually become changed and vice versa! (See "Backward Compatibility" above) |
1048 |
</note> |
1049 |
</body> |
1050 |
</html> |