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