# Help Building Gaussian Random Script



## UmFuFu (Mar 22, 2008)

A very nice person from the NI forums directed me over here (and gave a bit of help as well), but...

I'm wondering if anyone has any insight into how to make a gaussian random number generator in Kontakt.

Many thanks in advance!!


Ben


----------



## Thonex (Mar 22, 2008)

Hi.... and welcome to the forum!!! :D 

There is a random number generator command in KSP, but I don't know what a Gaussian random generator is.

There are some great programmers who come here... and I'm sure one of them will chime in.

Cheers,

T


----------



## UmFuFu (Mar 22, 2008)

Thank you!
Hopefully my first post it isn't too much of a doozy.

I know their are methods for generating a gaussian stream from random number generators, but that's about all i know.


Thanks for the welcome.

Ben


----------



## ComposerDude (Mar 22, 2008)

Some basic theory re Gaussian Random numbers is at:

http://www.taygeta.com/random/gaussian.html


----------



## Thonex (Mar 22, 2008)

Why would you want to program a gaussian random number generator as opposed to using the built-in KSP random command?


----------



## kotori (Mar 23, 2008)

Hi Ben,

Welcome to the forum. I will include my reply on the NI Forum for reference:


kotori said:


> Calculating something really accurate can be difficult due to the limitations of integer arithmetics. The simplest method is maybe to make use of the Central Limit Theorem and make an approximation by calculating the average of a small number of (I've seen people use 12) uniformly distributed random numbers.
> 
> See: http://www.dspguide.com/CH2.PDF





Thonex @ Sun Mar 23 said:


> Why would you want to program a gaussian random number generator as opposed to using the built-in KSP random command?


I'll let Ben answer that himself too, but one reason could be if you want to introduce some kind of random variation that you want to be close to a certain value most of the time and deviate more more seldomly. For example take the case of humanized tuning - although it might span a range of -30 to 30 cents it can be that values close to zero are more probable than for example -30. Using random(-30, 30) would yield a uniform distribution with as many 0 as -30. A gaussian random number has a bell-shaped probability density function.

Here is a sample script with a randg function that generates normally distributed numbers. To use it install and run my script editor/compiler, copy and paste this code, press F5 to compile (the compiled code is then automatically placed on the clipboard), switch to Kontakt and paste the compiled code into the Kontakt script editor using Ctrl+V. For some reason (rounding problems?) zero is over-represented, but I don't have time to look into that at the moment.

*function* *randg*(a, b, result)
``result := (random(a, b) + random(a, b) + random(a, b) + random(a, b) + ...
`````````````random(a, b) + random(a, b) + random(a, b) + random(a, b) + ...
`````````````random(a, b) + random(a, b) + random(a, b) + random(a, b)) / 12`````````````````
*end function*

*function* show_randg_probability_density_function
``*declare* i
``*declare* value``
``*declare* ui_table table[128](3, 6, 1500)
``*for* i := 0 *to* 40000
````*randg*(-100, 100, value)
````value := value / 1````
````inc(table[value + 64])````````
``*end for*``
``message('')
*end function*

*on init*````
``*declare* x
``show_randg_probability_density_function
*end on*

*on note*``
``*randg*(-100, 100, x)
``message('random number = ' & x)
*end on*


----------



## UmFuFu (Mar 23, 2008)

Thanks AGAIN kotori!
This script will be helpful for getting me started no doubt.

Regarding my desire for gaussian, you pretty much nailed it. 
In my experience gaussian sounds much more natural than uniform. Uniform randomness is almost never found in nature (probably never) and you can really hear the difference.

So I wanted to plug gaussian spreads to various parameters, pitch, pan, etc.


Ben


----------



## Thonex (Mar 23, 2008)

Ok.... I see what you mean. Like center weighted random.

Thank NIls for sharing that code. I'll take a closer look when I get a moment.

Cheers,

T


----------



## UmFuFu (Mar 23, 2008)

Exactly...
And thank you!


----------



## kotori (Mar 23, 2008)

Fixed the problem which caused zero to be generated too often. The modified randg definition looks like this:
*function* *randg*(a, b, result)
``result := (random(0, b-a) + random(0, b-a) + random(0, b-a) + random(0, b-a) + ...
`````````````random(0, b-a) + random(0, b-a) + random(0, b-a) + random(0, b-a) + ...
`````````````random(0, b-a) + random(0, b-a) + random(0, b-a) + random(0, b-a)) / 12 + a
*end function*

I generated 500 000 random numbers in the range -128 to 128 and counted the frequency of each value. The image below shows the result. 8)


----------



## UmFuFu (Mar 23, 2008)

Wow man, holy crap!
That looks great.

I haven't had a chance to try this ouò@ù   tÇm@ù   tÇn@ù   tÇo@ù   tÇp@ù   tÇq


----------



## UmFuFu (Mar 23, 2008)

This forum is cool.


----------



## Big Bob (Mar 24, 2008)

Hey Nils,

I just had an interesting thought. For those situations where one would be repeatedly calling randg with the same argument range, I think you could use a 'sliding' average to avoid having to get 12 new random numbers for each 'result'.
Interestingly, I think this would also produce a normal distribution in the result.

You could keep an array of the last 12 random numbers and their Sum, and after a new result is delivered, you could simply replace the oldest random number in the array with a new one (and of course update the Sum and Oldest pointer index). Of course the overhead of all this might take longer than cranking out 12 new random numbers :lol: However, possibly the quality could be improved then by increasing the number 12. Just a 'random' thought. :wink: 

Have a Super Day My Friend,

God Bless,

Bob


----------



## kotori (Mar 24, 2008)

Hey Bob,

Good to see you around. Yes, that should work too, although consecutively generated random numbers would not be independant - any new number would be close to the previous one. This can be both desirable, acceptable or undesirable. So it depends on what one wants. In terms of performance there is probably not a big difference since I assume that introducing a ksp loop would add some overhead.

Cheers,
Nils


----------



## Big Bob (Mar 24, 2008)

Hi Ben,

As promised, here's another version of 'randg' you can try out in your spare time :D
Please read the header comments for details. 

_{ This version of randg only fetches 'rpop' random values when the user enters }_
_{ a new range (b - a) for the result. Each subsequent call to randg with the }_
_{ same range will need to fetch a single new random value. As Nils pointed out, }_
_{ this method also produces a 'normal' distribution but adjacent calls will not }_
_{ be allowed to change much. Effectively, this algorithm applies some smoothing }_
_{ to the output data, which may or may not sound more musical. Let us know what }_
_{ you discover Ben. }_
*function* *randg*(a,b,result)
``*declare* *const* rpop := 48````_{ Random population size }_
``_{ Larger numbers may produce a somewhat better quality normal distribution }_
``_{ at the expense of 'setup' time for each new input range. Higher numbers }_
``_{ will also tend to decrease the standard deviation (sigma) making the }_
``_{ the normal curve steeper by increasing the population at the mean. }_``
``*declare* n````````````_{ Loop index }_
``*declare* old``````````_{ Pointer index to oldest random value in rand array }_``
``*declare* *rand[*rpop]```_{ Array to hold the last 'rpop' random values }_
``*declare* range````````_{ Range of user's last request for random data }_``
``*declare* sum``````````_{ Sum of last 'rpop' random values }_
``
``*if* range # b - a````````````_{ If range has changed since last call }_
````range := b - a
````old := 0
````sum := 0
````*for* n := 0 *to* rpop - 1````_{ Get a whole new set of random data }_
``````*rand[*n] := random(0,range)
``````sum := sum + *rand[*n]
````*end for*
``*end if*
``result := sum/rpop + a``````_{ Deliver the biased average }_
``sum := sum - *rand[*old]``````_{ Now replace the oldest random number }_
``*rand[*old] := random(0,range)
``sum := sum + *rand[*old]
``old := (old + 1) mod rpop```_{ Update pointer for oldest }_
*end function* _{ randg }_




How about letting us all know how these two methods compare musically?

God Bless,

Bob


----------



## UmFuFu (Mar 24, 2008)

Hey Bob,
I'll get on it.
THANK you so much!!


Ben


----------



## Thonex (Mar 25, 2008)

Wow Bob!!!

That looks great.

I while ago I had done a (what I called center weighted) script that did more of a staircase bell curve... but you could only tell it was a staircase when it was heavily populated :D 

Needless to say this is much more elegant.... and professional :lol: 

Cheers to you and Nils for these little gems.

T


----------



## Big Bob (Mar 25, 2008)

Hi Nils,

Thanks for posting the excellent graphics, I always say that one picture is worth 10,000 words :D . It reminds me a little of applying a moving average to stock market data. But as you said, it remains to be seen whether the smoothing makes it better or worse musically, maybe it will depend on how it is used?

So Ben, now that Nils and I have stirred up all the trouble we can :wink:, it's up to you to report the pros and cons of these two methods in some useful musical context :lol: 

God Bless,

Bob

BTW I thought of another scenario where my series of trumpet notes might have a more abrupt change in intonation, and that's when I completely miss some high note I'm trying to hit (that's starting to happen all too often these days) :oops:


----------



## Big Bob (Mar 25, 2008)

Thonex @ Mon Mar 24 said:


> Wow Bob!!!
> 
> That looks great.
> 
> ...



Thanks Andrew but all the credit should go to Nils. He was the one that came up with the idea of using the central-Limit theorem and a very straight-forward way of producing a nice normal (gaussian) distribution. I merely suggested a possible way to avoid having to calculate 12 new random numbers for each single random result. It simply occured to me that using a moving average we could re-use the last 11 random numbers and only have to get one new one for each new result (and the resultant series would still have to have a normal distribution). 

However, it was Nils that pointed out that the moving average approach would prevent adjacent numbers from being too far apart (and thus not be purely random as his method was). I hadn't even thought about that problem :oops: , I was concentrating on reducing compute time and still retaining normalcy (and possibly allowing us to use a larger set size than 12 without speed penalty) . 

Now if it turns out that the 'smoothing' effect of my suggestion works out to have some musical advantage, it will be a pure accident since that wasn't the reason I first proposed it.

But Andrew, I'm sure Nils would agree with me that your enthusiastic posts are always welcome and they certainly keep us all well motivated.

God Bless you my Friend,

Bob


----------



## kotori (Mar 25, 2008)

Big Bob @ Tue Mar 25 said:


> But Andrew, I'm sure Nils would agree with me that your enthusiastic posts are always welcome and they certainly keep us all well motivated.


Indeed. What would this forum be without Andrew. And as I said earlier, sometimes your implementation can be more suitable than mine so there's no need to be too humble. :wink:


----------



## UmFuFu (Mar 25, 2008)

Hello All!

I just want to apologize and express my lameness for not being able to try this stuff out in a timely manner.

It turns out I got slammed with work this week, not to mention never having coded a Kontakt Script before.

But regardless, I'm very excited about this and will get to it soon. Hopefully you're enthusiasm wont vanish with my tardiness. 

Thank you all!!

Ben


----------



## Big Bob (Mar 25, 2008)

Hey Ben,

I'm sure you have plenty of other things to do besides this so I hope I didn't make you feel pressured to report back quickly. Just take all the time you need, but when you finally get some time to check things out, please let us know what you discover.

God Bless,

Bob


----------



## ComposerDude (Mar 26, 2008)

+1 re Big Bob and Nils. From the perspective of a professional software designer, they're doing some very nice work. And thanks to VI for hosting this forum for the cross-pollination of ideas.

-Peter


----------

