# For Kontakt 4 User: often needed functions of Bobs Math library as arrays (= less CPU!)



## Dynamitec (Dec 10, 2010)

Hi everyone,

*MathFunctionsCacheCrazyVersion.zip:*
In case someone might use this. Make sure you'll have Kontakt 4, all other version will crash importing such massive arrays  Also make sure you'll use "Apply from ... Clipboard" or the new text link feature, otherwise your Kontakt editor will get somewhat slow. Also make sure to remove the arrays you don't use 
This version is only for those who use massive amounts of crossfades or envelope modulation (like I did for example in Electri6ity for example). 

*MathFunctionsCacheSmallerAndNotAsCrazy.zip*
This versions shows an easy way to cache some of the often needed functions of Bobs math library. Make sure you'll have his library in the same folder, since it's imported into that file. You'll use the functions exactly like you would use Bobs functions. This works in K4 only, too (because of the array size).


----------



## EvilDragon (Dec 10, 2010)

Extremely useful! Also provides cleaner code!


Until NI implements math functions natively, this is the best we can get!


----------



## andreasOL (Dec 10, 2010)

Hey, Thanks!

Indeed, there's much NI could do...


----------



## kotori (Dec 12, 2010)

Here is a longer example that can be pasted into KScript Editor and compiled and run:

*function* interpolated_lookup(array, index, scale_factor, result)
``_(* index is an array index that has been scaled up by scale_factor to allow for decimal values
eg. if the scale factor is 10 and the index is 45 the real index is 45/10=4.5 which means
that the function will return the average of the array elements at index 4 and 5 *)_
``*declare* mix
``*declare* j
``mix := index mod scale_factor
``j```:= index``/``scale_factor``
``result := (array[j]*(scale_factor-mix) + array[j+1]*mix + scale_factor/2) / scale_factor```````````````````````````
*end function*

*function* sin(v, result)
``_(* v is the angle - a number between 0 and 100 000 corresponding to the range 0 to pi/2 *)_
``*declare* sin_table[52] := (0, 314, 628, 941, 1253, 1564, 1874, 2181, 2487, 2790, 3090, 3387, ...
````````````````````````````3681, 3971, 4258, 4540, 4818, 5090, 5358, 5621, 5878, 6129, 6374, ...
````````````````````````````6613, 6845, 7071, 7290, 7501, 7705, 7902, 8090, 8271, 8443, 8607, ...
````````````````````````````8763, 8910, 9048, 9178, 9298, 9409, 9511, 9603, 9686, 9759, 9823, ...
````````````````````````````9877, 9921, 9956, 9980, 9995, 10000, 10000)````````````````````````````````
``interpolated_lookup(sin_table, v, 2000, result)`````_{ the maximum array index is 50, so the scale factor becomes 100 000/50 = 2000 }_
*end function*

*function* cos(v, result)
``_(* v is the angle - a number between 0 and 100 000 corresponding to the range 0 to pi/2 *)_
``*declare* cos_table[52] := (10000, 9995, 9980, 9956, 9921, 9877, 9823, 9759, 9686, 9603, 9511, ...
````````````````````````````9409, 9298, 9178, 9048, 8910, 8763, 8607, 8443, 8271, 8090, 7902, ...
````````````````````````````7705, 7501, 7290, 7071, 6845, 6613, 6374, 6129, 5878, 5621, 5358, ...
````````````````````````````5090, 4818, 4540, 4258, 3971, 3681, 3387, 3090, 2790, 2487, 2181, ...
````````````````````````````1874, 1564, 1253, 941, 628, 314, 0, 0)``````````````````````````
``interpolated_lookup(cos_table, v, 2000, result)`````_{ the maximum array index is 50, so the scale factor becomes 100 000/50 = 2000 }_
*end function*

*on init*
``*declare* ui_table table[128](6,6,10000)
``*declare* j
``*for* j := 0 *to* 127
````*if* j mod 2 = 0
``````sin(100000 * j / 127, table[j])
````*else*
``````cos(100000 * j / 127, table[j])
````*end if*
``*end for*
*end on*


----------



## Hans Adamson (Dec 12, 2010)

Thanks Benjamin!
/Hans


----------



## gmet (Dec 13, 2010)

Benjamin, Nils - thanks for this very useful stuff.

The latest version of Bob's math I have is 2.12 - where is 2.15?

Justin


----------



## Big Bob (Apr 19, 2011)

Hi Nils and Benjamin,

In trying to catch up with posts that were made while I was offline, I came across this one and I have a couple of questions.

Nils,

What is your main motive for using a smaller array? Is it simply to avoid the lengthy assignment statement and/or typing in all the values? The reason I ask is that, especially in the case of the sine/cosine functions, the total number of input values (1001) is far less than the current maximum array size of 32K.

If the main reason for using the lookup table is to reduce CPU hit, why not get the fastest runtime performance with one larger array (Since the interpolation process provides a slower runtime performance than a single 1001 element array would, in addition to introducing some error).

Benjamin,

Since both your example code and Nils' code seem to fill in the array 'manually', I'd like to ask if there is some reason for not using the Math Library to populate the array?

For example, it seems one could do something like this:

*import* "KSPMathV215_KSM.txt"

*on init*
``*declare* ui_value_edit angle(0,1000,1)
``angle := 0
``*declare* ui_label show (2,1)
``BuildAngleTable
``*declare* sine
``*declare* cosine
``_{ Declare and populate the Sin array }_
``*declare* Sin[1001]
``*declare* n
``*for* n := 0 *to* 500
````SinCos(n,Sin[n],Sin[1000-n])
``*end for*
``message('') 
*end on*

*function* FastSinCos(ang,sine,cosine)
``sine := Sin[ang]
``cosine := Sin[1000 - ang]
*end function*

*on ui_control*(angle)
``FastSinCos(angle,sine,cosine)
``set_text(show,'sin=' & sine & ', cos=' & cosine) 
*end on*

Of course there are a few problems with filling large arrays in the ICB but these can easily be side-stepped by rearranging the Math Functions and/or actually filling the arrays in the 'on pgs_changed' callback for example.

I'm just wondering if there is something more fundamental that I'm missing here. I'm in the process of updating the Math Library and I have been thinking about incorporating the lookup table idea into the Library itself. So, this thread caught my interest.

Any words of wisdom concerning the above?

Rejoice,

Bob


----------



## Big Bob (Apr 21, 2011)

Or better yet, use a temporary table filler like this to create an FSin array.

*import* "KSPMathV401_KSM.txt"

*on init*
``*declare* ui_button Fill
``*declare* n
``*declare* FSin[1001]
``message('') 
*end on*

*on ui_control*(Fill)
``*for* n := 0 *to* 500
````SinCos(n,FSin[n],FSin[1000-n])
````wait(1)
``*end for*
``save_array(FSin,1)
``Fill := 0
*end on*




Then, write a *FastSinCos* routine like the one in the simple test script shown next.


*on init*
``*declare* ui_value_edit angle(0,1000,1)
````angle := 0
``*declare* ui_label show (2,1)
``*declare* sine
``*declare* cosine
``*declare* FSin[1001]
````read_persistent_var(FSin)
````load_array(FSin,1)
``message('') 
*end on*

*function* FastSinCos(ang,sine,cosine)
``sine := FSin[ang]
``cosine := FSin[1000 - ang]
*end function*

*on ui_control*(angle)
``FastSinCos(angle,sine,cosine)
``set_text(show,'sin=' & sine & ', cos=' & cosine) 
*end on*





Using this technique, the Math Library code for SinCos need not be included in the final script at all. A similar thing can be done for Get_db using a 10,000 element array to hold all the possible input values.

Of course, for the math functions that have a wider range of possible input values than 32K, the situation gets trickier but still something similar plus some clever reduction logic should still be feasible if one is willing to accept some increased error. I would be willing to look into this for the most commonly needed functions if I knew what they were :lol: 

Thus, the reason for my post asking what math functions you guys are using lookup tables for or, alternatively, which math functions would greatly benefit from being sped up? But, so far only Andreas has responded with *SinCos* and *Get_db *which I presume would be typical of anyone doing some form of equal-power crossfading. Actually those two functions would be among the simplest to speed up with the foregoing technique.

Others may not be quite so easy, so I'd like to know which functions might be the most likely to benefit from a speed up.

Rejoice,

Bob


----------



## Dynamitec (Apr 23, 2011)

Hi Bob,



> Since both your example code and Nils' code seem to fill in the array 'manually', I'd like to ask if there is some reason for not using the Math Library to populate the array?



I had problems with that solution: 1) using persistent arrays that big can make loading instruments seriously slow, 2) using the PGS callback (called from on init) didn't work for me either. In some cases the pgs callback was exited before all values were filled (Kontakt bug?!)


----------



## EvilDragon (Apr 24, 2011)

1) Even in 4.2.2?


----------



## Big Bob (Apr 24, 2011)

Hi Benj,



> 2) using the PGS callback (called from on init) didn't work for me either. In some cases the pgs callback was exited before all values were filled (Kontakt bug?!)



This one I'm not concerned about any more because I think using load_array is the better solution anyway. One can easily create (or re-create) the .nka files with simple Library utilities. This both eliminates the excess code baggage and any slowdown introduced during the ICB or post-init operation.



> 1) using persistent arrays that big can make loading instruments seriously slow,



This one I am concerned about :o 

Can you elaborate more on this please. So far, I haven't noticed this but I don't have a ready-made instrument/script of nearly the sizes that you often come up with :lol: . Is it only the loading time that is affected? Once the instrument is loaded is there any lingering speed problems with using large arrays? Is there any way to make arrays (that are loaded with the load_array command) non-persistent? I'm just assuming (from what Nils has said in some prior posts) that NI automatically makes any such array (loaded with the load_array command) persistent. The persistence is not a requirement for use in this application so if that is the problem and it can be optionally not used that would help.

What about Mario's question, have you rechecked this behaviour with the latest K4 version? I would appreciate any and all further information on this topic because I think I have pretty well worked out a major upgrade to speed up all Math Library routines but its success will depend on a few large arrays saved as .nka files.

Rejoice,

Bob


----------

