# Bob's Math Library - Best fit function for ep to sample start



## Compy (Jul 9, 2012)

Morning all! I've been having a play with Bob's library to try and find the best fit curve for converting engine parameter to sample start. As there doesn't seem to be a direct function I've tried a few logical candidates, and DRTime gets me close but no cigar. 

So was just wondering whether there was an existing function with better fit that anyone has come across that I've not spotted...or whether I should have gone to bed 2hrs ago and just haven't seen it... :oops: 

Paul


----------



## polypx (Jul 10, 2012)

As far as I understand the play_note start offset is in microseconds, and the source module start_offset modulator is in percent.


----------



## Big Bob (Jul 10, 2012)

Hi Compy,

I didn't know there was an ep for controlling Sample Start offset :shock: 

Why would you need such an ep when you can control SS directly from play_note?



> source module start_offset modulator is in percent



Hey Dan, this is something new to me too. :roll: Where does one find such a thing? I took another quick look at the KSP reference guide for both K4 and K5 and I don't find anything relating to modulating the source module SS offset. :oops: 

Am I on Candid Camera or am I just confused again? :lol: 

Rejoice,

Bob


----------



## Compy (Jul 10, 2012)

Hi polypx, you are correct. And I also should have said for context that I'm using the source module sample start modulator here, which is as you say in percent.

The issue however arises as this modulator doesn't use a linear scale internally. 

You can confirm this by looking at the modulation slider: If you set it's value to somewhere around 50% of the slider travel you'll see a value of 25% for sample start. Other quick tests: If you set it to 25% slider range you get just 6% sample start, and 75% slider gives you around 61% of sample start.

If you were to quickly script a knob with values that run from 0 thru 1000000 and point it at the modulator you'll see that the modulation slider response to that is linear through both its own positive and negative ranges, it's the scale the modulator uses that isn't. So the need here is to convert engine parameter to a usefully corresponding percentage. e.g. 100000 in gets you 10% out.

I did some quick not-overly-accurate measurements myself just using a knob and checking percent values to try to get an idea of the curve. I added 500000 to it myself to keep the modulation positive, so I'll supply both values here for reference.

Param-with-500k'''''Param-minus-500k'''''modulator-%
'525000''''''''''''''25000'''''''''''''''''0.01%
'550000''''''''''''''50000'''''''''''''''''0.10%
'575000''''''''''''''75000'''''''''''''''''0.34%
'600000'''''''''''''100000'''''''''''''''''0.80%
'650000'''''''''''''150000'''''''''''''''''2.70%
'700000'''''''''''''200000'''''''''''''''''6.50%
'750000'''''''''''''250000''''''''''''''''12.50%
'800000'''''''''''''300000''''''''''''''''21.60%
'850000'''''''''''''350000''''''''''''''''34.40%
'900000'''''''''''''400000''''''''''''''''51.20%
'950000'''''''''''''450000''''''''''''''''72.90%
1000000'''''''''''''500000'''''''''''''''100.00%

SO: when I plot this it looks like a kind of inverse exponential curve (am thinking at this point I probably should have just tried some kind of exponential conversion...ah, the benefits of sleep  ). From memory this looked a bit like the first half of one of the decay curves EvilDragon plotted once in the spreadsheet he'd kindly made available during a previous discussion we were all having regarding this type of conversion, hence me starting there. 

It's probably possible to gerrymander this into some kind of appropriate output form...but I figured I'd ask if there's an alternative or if I'd missed something before I get going!

Thanks
Paul


----------



## Compy (Jul 10, 2012)

Hi Bob, just saw we posted about the same time. Any confusion you have here is almost certainly just a result of my lack of appropriate explanation :mrgreen: 

No, as far as I know there isn't a specific KSP engine parameter for this. I merely wanted to convert the linear input values from a slider to the non-linear output of the sample start modulator and using your library seemed the quickest way. [EDIT - Effectively I'm just using a constant on the source module assigned to sample start and addressing it with $ENGINE_PAR_EXTMOD_INTENSITY]

The reason for wanting to do this is that I have several (actually a good number of) groups, and I want to control the start point only on one of them [EDIT - whichever I choose at the time] , and this seemed like the easiest way to see what was going on when it comes to debugging [EDIT - and ending up wiht as little clutter in the ON NOTE section as possible]. If there's a better approach scripting it for multiple groups I'd be equally as happy, all advice accepted here.

Cheers
Paul


----------



## Big Bob (Jul 10, 2012)

Hi Compy,

From the data you posted, the function looks very much like Kontakt's 'classic' cubic function.

For example, if you use:

percent := 100*[(ep -500000)/500000]^3

doesn't that seem to fit your data? For ep values below 500000, the invert button will probably activate. 

As soon as I get a little break, I'll check this out to verify it and I'll post my findings.

Rejoice,

Bob


----------



## Big Bob (Jul 10, 2012)

Hi Compy,

I have verified that the function is indeed cubic. Therefore, you should be able to use something like this:

*import* "KSPMathV406.txt"

*on init*
``message('')
``SetMathMode(0)
``*declare* ui_knob SS (-100,100,1)
````set_knob_unit(SS,KNOB_UNIT_PERCENT)
``*declare* ep
*end* on

*on ui_control*(SS)
``Root3(10*SS,ep)
``ep := ep/2 + 500000
``set_engine_par(ENGINE_PAR_INTMOD_INTENSITY,ep,0,find_mod(0,'CV_PITCH'),-1)
*end* on

Of course you will have to substitute whatever modulator name you are using in the set_ep line.

Rejoice,

Bob


----------



## Compy (Jul 10, 2012)

Ah Bob, you are a star! I'd just seen your previous post re it being a cubic function, and had literally just plumbed that into the spreadsheet to confirm that to myself when you posted a coded solution! Genius stuff, much appreciated. 

Not much more to say than that, you are a gentlemen sir!

All the best
Paul


----------



## Big Bob (Jul 10, 2012)

Hi Paul,

Glad to be able to help, however, I should also mention that it will probably be better to code the knob range 10 times higher rather than mulitplying the knob value by 10. That way you can track Kontakt's percent display more accurately by including the tenths of a percent as illustrated in the following script:

*import* "KSPMathV406.txt"

*on init*
``message('')
``SetMathMode(0)
``*declare* ui_knob SS (-1000,1000,10)
````set_knob_unit(SS,KNOB_UNIT_PERCENT)
``*declare* ep
*end* on

*on ui_control*(SS)
``Root3(SS,ep)
``ep := ep/2 + 500000
``set_engine_par(ENGINE_PAR_INTMOD_INTENSITY,ep,0,find_mod(0,'CV_PITCH'),-1)
*end* on

Rejoice,

Bob


----------



## Compy (Jul 10, 2012)

Tee hee, you are making me chuckle out loud right now...

I was just in the middle of editing the code to do exactly that with regard to getting the tenths of percentages when you posted your update...it's like you are watching me, except you are 2 minutes into the future ahead of me :mrgreen: ~o) 

I just checked behind me to make sure I haven't left my webcam on :D 
Excellent stuff.
Paul


----------



## Compy (Jul 10, 2012)

Quick update for anyone arriving at this solution later: For me at least the
set_engine_par(ENGINE_PAR_INTMOD_INTENSITY,ep,0,find_mod(0,'CV_PITCH'), -1) 
worked out of the box with a new instrument with a modulator constant added driving sample start (late version K4).


----------



## Raptor4 (Jul 11, 2012)

Hi guys,
It is a very interesting topic and again a big admiration for the Master Bob ! 
A few months ago I asked that question too, and somehow it stayed unanswered (probably I have not formed it well).
Anyway, during this time I decided to create a precised array (mapper) something like this: %SS[1001] := (0, 320, 450, 550, 630, 710, 780, etc...). It took a few days to program it (I have created a small helper tool for doing that).
That "mapper" array works fine in my main project I'm still working on. Right now I tried the Bob's GREAT solution using the Math Lib so I could produce the code offered by Bob. It works fine as well!
My question is - what's better regarding the CPU and the KSP behavior:
1. To use my direct array (mapper) which uses 1000 pre-mapped array values and gets 60 rows in the script declaration ?
2. To use the Bob's Math solution offered here which gets 120 rows in script ?

Thanks again for the great work Bob !
Cheers o[])


----------



## Compy (Jul 11, 2012)

Hi Raptor - I suspect the absolute answer here as only you have access to both Bob's method and your own is to test it and measure it yourself. I'd guess that for the most part you are going to only be calling one (or two??) of these at a time at the most, so logically you wouldn't then need to be overly concerned about concurrent scalability. 

You may or may not know that there is a CPU profiling mode in Kontakt. If this is new news then give it a go and see if provides you any useful insight: Open Kontakt and look to the top left bar that starts 'Files','Library'...Head over to the 'Monitor' tab, then to 'Engine' and at the bottom, CPU profiling Mode.

I know Bob has previously measured the time it takes to run his routines as I've seen them documented at the back of Bob's Math Library Technical Guide...which he's conveniently just put up a new link to in the 'Square Root' post that followed this one! Those figures were on an older generation machine (Intel Core 2 Duo), with K2 and K3, plus you'd need to understand how Bob measured it the first time round...the good news is, as ever he's already got a method and done it once before, so if he'll share that should set you on your way.

https://dl.dropbox.com/u/80404485/Kontakt/Math%20Library/Docs/KSPMathTechGuide_V215.pdf (https://dl.dropbox.com/u/80404485/Konta ... e_V215.pdf)

That's as much value as I can add right now, hope that's of use.
All the best
Paul


----------



## Big Bob (Jul 11, 2012)

Hey guys,

Can I ask sort of a dumb question here :oops: 

Why do you want to do this? I mean why is it important to 'linearize' control panel knob position versus Intensity percentage?

Isn't it sufficient to just display the correct % with the knob? If so, why can't you just use something like this:

*on init*
``message('')
``*declare* ui_knob SS (0,1000000,1)
````set_knob_unit(SS,KNOB_UNIT_PERCENT)
``*declare* ep
*end* on

*on ui_control*(SS)
``set_engine_par(ENGINE_PAR_INTMOD_INTENSITY,SS,0,find_mod(0,'CV_PITCH'),-1)
``set_knob_label(SS,get_engine_par_disp(ENGINE_PAR_INTMOD_INTENSITY,0,find_mod(0,'CV_PITCH'),-1))
*end* on

I presume there is some reason why this isn't what you want but, just in case you were not aware of this technique I thought I would ask.

Matthias asked for a square root function to handle some situation where he needed to 'linearize' the Intensity slider in some area where he reports a quadratic rather than a cubic curvature. I've been asking him to specify where this condition prevails but so far he hasn't replied. 

Is anyone else aware of where you can assign a modulator such that the Intensity slider has a quadratic curvature? If so would you please post some info for me. I'm trying to determine whether including a Root2 routine in the next library update would be worthwhile.

Thanks.

Rejoice,

Bob


----------



## Compy (Jul 11, 2012)

Hey Bob. For me, as far as my requirement goes that was sorted and completed yesterday, solution perfect, I'm not looking to do anything else here. 

I think Raptor is just wondering how to tell whether the solution he came up with of interpolating an array is more or less CPU efficient than calling a conversion routine. I'd guess to all intents and purposes if calling your function was somewhere around 10us on a machine that's now nearly two generations old, then it's all a wash for the amount of time it'll take :D (I'm sure someone will correct me on that in very short order :mrgreen: )

Paul


----------



## polypx (Jul 11, 2012)

> Isn't it sufficient to just display the correct % with the knob?



Hey Bob,

I've been following this thread, and I can already think of something simpler now I have linear control over the start time offset: No matter how long the sample I've loaded, I can now divide it into n equal sections. 

This could be handy for chopping a beat into 16, or something like that perhaps?

cheers
Dan


----------



## Big Bob (Jul 11, 2012)

Hi Paul,



> Hey Bob. For me, as far as my requirement goes that was sorted and completed yesterday, solution perfect, I'm not looking to do anything else here.



yes but you are dodging my question which is, WHY do you need to linearize the control knob (as long as it displays the correct value)? Maybe Dan's post is a clue in that maybe you are trying to calculate the percent of modulation in the script rather than using a manually set knob?

Hi Dan,



> I've been following this thread, and I can already think of something simpler now I have linear control over the start time offset: No matter how long the sample I've loaded, I can now divide it into n equal sections.
> 
> This could be handy for chopping a beat into 16, or something like that perhaps?



Well that's wonderful I think, but you haven't told us what you came up with :lol: 

Hi R4,



> My question is - what's better regarding the CPU and the KSP behavior:
> 1. To use my direct array (mapper) which uses 1000 pre-mapped array values and gets 60 rows in the script declaration ?
> 2. To use the Bob's Math solution offered here which gets 120 rows in script ?



Sorry I missed seeing this post before. If by 120 rows in the script you mean 120 lines of code and you are only using the Root3 function, you ae probably doing something wrong like perhaps you don't have code optimization turned on?

For example, if I compile the sample code I posted for Paul, the script compiles to 48 lines of code and that includes 11 lines for the application. So the Math library adds about 37 lines of code. So you are either using more library functions or you are doing something wrong.

As to execution time, the library is generally pretty fast, especially in Fast mode. However, for the Root3 function, there isn't much speed improvement for fast mode. All this is discussed pretty thoroughly in the Technical Guide Addendum.

But, probably the best way to settle the issue though is what Paul suggested, resort to running a comparison timing test. :lol: 

Rejoice,

Bob


----------



## Compy (Jul 11, 2012)

Hmmm! Interesting! I'd have to say I don't think I'm dodging any question, though reviewing the thread and looking back, whilst I said what I wanted I suppose I didn't say what I wanted it for, though largely because I didn't think anyone would be bothered or interested...so maybe that's what's got you to thinking that. 

In reality, its exactly as you could probably imagine: I wanted to get control of the sample start so that there was a linear relationship between an input and the output so that I had both a method for data input via the slider and a method for scriptable control for trying more esoteric things, whilst at the same time not having to stuff yet more code into my ON_NOTE section or spend any time try to work out which of the groups I'm actually affecting.

So, first order of business was to get a slider that tracked linearly from 0 thru 100% (using values 5000000 thru 1000000) - Doff of the hat, many thanks to you there. The rest then is work in progress, having only had the solution for 12hrs or so, but Dan has already mentioned one possible use, effectively being able to index into a sample given that you can already know the length of the sample among other things. Rest assured, I value and appreciate the input of this community, and yourself in this instance specifically, so as soon as there's anything new and exotic to share you'll all hear about it...Right now though: There just isn't.

Hopefully that's addressed your issue....and as far as a slider with a quadratic function, well I'm probably as likely to spot that as I was the slider with the cubic function :D 

All the best
Paul


----------



## Raptor4 (Jul 11, 2012)

> perhaps you don't have code optimization turned on


That was the issue. Now I enabled the optimization and compiled the code again, after that I pasted it in a new document in the KSE (v1.5.1 Win), so it has 50 lines exactly. I was familiar with your user manual instructions but I thought I have to enable the optimization regarding your ICB notes. When paste the optimized code in the Kontakt instrument KSP editor it works as expected. I just changed the UI knob range to 0,1000,10 cause I do not need the "invert" mode.
I love your optimized solutions Bob - thank you very much !
Regarding doing some tests I do not have an idea how to compare your Math model with my array SS mapper, both work well... :? 
Anyway, thanks for the next GREAT solution - I love your Math library, it's a great tool !

R4 o=<


----------



## Big Bob (Jul 11, 2012)

Hi Paul,



> Hopefully that's addressed your issue....



Yes indeed, I understand that scripted control will want to be able to control the Intensity slider as though it were linear. I just wanted to be sure that you didn't just want a manual knob on the control panel that displayed the right thing and might have not known about get_engine_par_disp :lol: 

Hi R4,



> That was the issue. Now I enabled the optimization and compiled the code again, after that I pasted it in a new document in the KSE (v1.5.1 Win), so it has 50 lines exactly.



I'm glad to hear that another problem has bitten the dust :lol: 

As to the quadratic modulation thing, I guess only Matthias knows where one runs into that and he hasn't checked back in since Sunday. :roll: 

Rejoice,

Bob


----------



## Compy (Jul 12, 2012)

:mrgreen: Heh, thanks for the double check, it's all good!

Oh...One last thing tho (he says in his best Columbo voice): where did the 'CV_PITCH' come from in:

set_engine_par(ENGINE_PAR_INTMOD_INTENSITY,ep,0,find_mod(0,'CV_PITCH'), -1)

I don't think I've ever seen that before. Any more where that came from? 

Cheers
Paul


----------



## polypx (Jul 12, 2012)

"CV_PITCH" is the default name that Kontakt created when you routed a "Constant" to the Start Time.


----------



## Compy (Jul 12, 2012)

Duh, course it is!! I just opened the edit window and took a look...
Think it was that it didn't immediately jump out at me as it points to sample start (and my mind would have expected CV_Start or some such). Can't even blame it on lack of sleep this time :D 
DOH!!
Cheers Dan


----------

