# Exponential Script



## gmet (Feb 21, 2009)

I am writing a plugin for Sibelius (I know it's not Kontakt!) and need some help with an equation for an exponential curve. The purpose is to write CC info for crescendos.

Known values:

Start level & End Level (Vol Change)
Time (this sets the spacing of the midi messages)
Rate (0.5 to 3)
Volume Inc (+1 or -1 depending on start and End Level)

I use the following equation in a while loop:

if (Linear = True)
Current Volume = Current Volume + Volume Inc
else
Current Volume = Current Volume + Exp Inc

However I am stumped as to how to work out an equation for an exponential curve (Exp Inc).

Any ideas?

Justin


----------



## PolarBear (Feb 21, 2009)

I don't have an actual solution but I think an exponential curve for volume control isn't the best thing to do as you can't do quick calculations...

I dunno if that's of any worth to you, but here is some more explanation:
http://www.dr-lex.be/info-stuff/volumecontrols.html

I'd look out for functions that can be expressed as easily calculatable equations with simple (finite, not approximating) operations.


----------



## Thonex (Feb 21, 2009)

I'm 101% sure Big Bob knows :lol:


----------



## Big Bob (Feb 21, 2009)

I don't know about this 101% stuff  but, Justin, you could probably get by with NI's favorite 'pseudo-exponential' curve based on the cubic function.

The basic relationship between Volume output, V0, and CC input over its full range is given by:


```
V0/Vm = (CC/127)^3   where Vm is the maximum volume level of the synth.
```
To use this as you have described you first need to solve this equation for the CC value:

```
CC = 127*(V0/Vm)^1/3
```

If you want to have the CC cover only a subrange of 0 to Vm, you must modify the equation by replacing CC with:

```
CCs + CC*(CCe - CCs)/127
   where CCs = 127*(Vs/Vm)1/3 and CCe = 127*(Ve/Vm)^1/3
```
In these equations, Vs is the Start volume desired when CC = 0 and Ve is the End volume when CC = 127.

Maranatha,

Bob


----------



## gmet (Feb 21, 2009)

Thanks for the quick replies guys - much appreciated.

Bob - many, many thanks for the potential solution, however first I will have to get my head around it, and then see if it will translate into Simkin (Sibelius Script language).

Regards,

Justin


----------



## gmet (Feb 21, 2009)

I have hit a couple of snags already!!

Simkin does not have the cube symbol (see list of symbols below).

Also I can specify the start and end volumes in either 0-127 (CC) or 0-100 (%).
The script goes from the start vol ($Current_Volume), round a while loop until it reaches the maximum specified value. The script then spaces all the messages out equally along the time scale.

It would also be useful to be able to specify the rate at which it rises.

I hope this all makes sense coming from a mathmatical idiot to a genius!

Justin


----------



## PolarBear (Feb 21, 2009)

Big Bob @ Sat Feb 21 said:


> ```
> V0/Vm = (CC/127)^3   where Vm is the maximum volume level of the synth.
> ```


If you don't have that you could simply write the same as

```
V0/Vm = (CC/127) * (CC/127) * (CC/127)   where Vm is the maximum volume level of the synth.
```
Simple mathematical transformation  Or in that * and / doesn't need the braces:

```
V0/Vm = (CC * CC * CC) / 2048383   where Vm is the maximum volume level of the synth.
```
savign you some calculation time.


----------



## gmet (Feb 21, 2009)

Guys,

I hope I am not being too stupid, but is this what you mean:
(I have included some of the other code to make sense of the while loop)



> UseExp //Use exponential curve instead of linear
> LowVolume //user entered value 0-127
> HighVolume //user entered value 0-127
> 
> ...



Justin


----------



## Big Bob (Feb 21, 2009)

Hi Polar Bear,

Your idea works fine for calculating the cube but, Justin may end up needing the inverse formula which then will require that a cube-root be extracted.

Hi Justin,

I'm out of time today and my Sundays are usually pretty busy with church activities. However, as soon as I can, I'll try to get back to you on this.

God Bless,

Bob


----------



## gmet (Feb 22, 2009)

Bob, PolarBear - thanks again for your help, however my lack of math knowledge is letting me down!

I think I might need to try and explain myself a bit clearer.

The total volume range of every instrument is 0-127 (silent to _fff_), however if I am writing a crescendo from say _mf_ (84) to _ff_ (113) then I need an exponential curve between those two values, not that portion of the entire total volume range curve (I hope this makes sense)

The best I could come up with is the following, however it just returns the value of zero every time for the exponential curve increment:



> LowVolume //user entered value 0-127
> HighVolume //user entered value 0-127
> Range = HighVolume - LowVolume;
> 
> ...



Obviously, depending on the Low and High values, the while loop varies in how many times it returns a value - Sibelius just takes all returned data and spaces it out equally along the specified time line.

Bob - you guessed correctly that inverse formula would also be desirable!, however do not rush on my behalf - I appreciate your help whenever you have time.

Regards,

Justin


----------



## gmet (Feb 22, 2009)

Hi Bob,

Thanks agian for dropping in. I ought to explain that these scripts do not work in 'real time'. I input all the note & dynamics info into the score and then run the plugin to add CC information to the score. The score is then played back.

Sibelius can host VSTs, however it only deals with midi information which it sends to those VSTs (in my case Kontakt).

The scripting language is Simkin (an example of it is the code a couple of posts up).

All values are on the 0-127 scale.

If I write a crescendo and run the current plugin it just writes linear values from the lowest to the highest specified values. e.g.
Low = 43, High = 120.
The plugin keeps going round the loop until it reaches the High value and writes CC=43, CC=44, CC=45 ..........etc......CC=119, CC=120 (where CC is the specified controller). In other words the linear increment is always 1. The number of values returned by the plugin are then written onto the score equally spaced along the crescendo line.

What I would like to do is have an exponential curve instead of a linear curve. So I need to work out the increments to enable the plugin to write an exponential curve from the lowest to the highest value. Again it would start with the Low value and keep going round the loop until it reaches the High value.

Just to confirm that the plugin in takes a couple of seconds to run which is irrelavent as it is not done in real time.

I hope this gives you the information you need, if not thanks again for your help so far.

Regards,

Justin


----------



## gmet (Feb 22, 2009)

Sorry, forgot to add that generally I am using CC1 (Mod) on X-Fade patches for the CC values so volume output or dB level is not an issue.

Justin


----------



## Big Bob (Feb 22, 2009)

Hi Justin,

Let me paraphrase what I think you are saying. For any given crescendo, you can specify a CC value that it begins at and a CC value that it ends at (such as 34 to 108). Your 'plugin' script then merely generates the values 34, 35, 36, 37, ... 107, 108 and stops. Then Sibelius sprinkles these 75 values uniformly in time between the beginning and end of the crescendo (in the MIDI sequence to be generated).

Do I assume correctly that you can generate any string of values (from 0 to 127) between your limits (from 34 to 108 for the current example) that you wish? For instance: 34, 34, 34, 35, 35, 36, ... 107, 108? In other words can the increment be different between each loop pass? If not, there is no way to produce an exponential series between your two limits. 

If the increment between each integer must be fixed (such as one or two or whatever) for instance like the series 34, 36, 38, 40, ... 106, 108 (an increment of two), any such constant increment can only produce a linear ramp. In order to produce a non-linear ramp (exponential or otherwise), the increment value must change for each loop pass. Worse than that, if the number type is restricted to the *integers* between your start and end limits, then many numbers in the series will have to repeat (as I tried to illustrate with the number series above 34, 34, 34, 35, 35, etc). I might also mention that at the beginning of the curve there will be lots of repeated integers but near the end of the curve many values will be skipped.

Nevertheless, if this is what you want, then I can suggest a way of determining the increment for each loop pass based on the Start and End values and, of course, the desired contour. Please let me know if I have the right picture or if I'm still confused :? 

To be continued...

Maranatha,

Bob


----------



## gmet (Feb 22, 2009)

Big Bob @ 23rd February 2009 said:


> For any given crescendo, you can specify a CC value that it begins at and a CC value that it ends at (such as 34 to 108). Your 'plugin' script then merely generates the values 34, 35, 36, 37, ... 107, 108 and stops. Then Sibelius sprinkles these 75 values uniformly in time between the beginning and end of the crescendo (in the MIDI sequence to be generated).


Correct



> Do I assume correctly that you can generate any string of values (from 0 to 127) between your limits (from 34 to 108 for the current example) that you wish? For instance: 34, 34, 34, 35, 35, 36, ... 107, 108? In other words can the increment be different between each loop pass?


Yes, however I would suppose that the formula for the increment would have to be re-calculated on each loop pass.



> if the number type is restricted to the *integers* between your start and end limits, then many numbers in the series will have to repeat (as I tried to illustrate with the number series above 34, 34, 34, 35, 35, etc). I might also mention that at the beginning of the curve there will be lots of repeated integers but near the end of the curve many values will be skipped.


repeated numbers are fine and I use the 'Round' command to always get whole numbers.

I think you are probably on the right track,

It is now 01.10 AM in England so I won't check back until tomorrow.

Best,

Justin
[/quote]


----------



## PolarBear (Feb 22, 2009)

Hmm... from an outside point of view, I don't get, how the timing is done... Let's have CC val of 34 at say second 01. I want it to be linear at CC val 108 at second 03. Now the while loop calculates those numbers. Equally spread, ok.

Now I want the same thing, 34 to 108, from second 01 to second 09. The while loop calculates the same values, equally spread alongside a much longer interval.

For linear this might be ok if it is only +1 at a time. But with exponential or linear greater than +1 you'll get "steps" where it is like 34, 38, 38, 38, 38, 42, 42, 42, 42, 46, 46, 46, 46, ... 104, 104, 104, 104, 108, there. This will result in a very unnatural sound of any non-linear curve? Doing a 6 seconds exponential increase will maybe look like 34, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 95, 95, 95, 95, 95, 95, 101, 101, 101, 101, 105, 105, 105, 106, 106, 107, 108.

You get the idea I hope.


----------



## Big Bob (Feb 22, 2009)

Yeah Bear, I get the idea but nevertheless I think this is what Justin wants. :roll: I too wonder about its usefullness, although, I don't think the series will look quite like what you illustrated but rather slower to rise at first and faster later as I indicated in my last post. I'm going to quit for the night now also but I'll cobble something together for him tomorrow and we'll see if it's really what he wants. :lol: 

BTW Justin,

Since you made the statement that you always round-off, are you saying that your scripting language includes floating-point numbers? My earlier impression was that it only supported integers.

Goodnight all,

Bob


----------



## PolarBear (Feb 22, 2009)

It's how you think exponentially. You chose slow start and fast end, and I just look at it the inverted way... fast start and slow end. both are possible with Sonar for example.

Well, actually I don't know... probably it will result in something equally spread... but be still the same issue.

34, 86, 86, 86, 86, 97, 97, 97, 97, 103, 103, 103, 103, 105, 105, 105, 105, 106, 106, 106, 106, 107, 107, 107, 107, 108


----------



## Big Bob (Feb 23, 2009)

Hi Polar Bear,

Since Justin is talking about volume control (ie crescendo/de-crescendo), I don't think he would want a convex curve such as you are illustrating. One might call that a log or pseudo-log curve but such a convex curve is just the opposite of what you want for volume control (since it would be even worse than linear). Thus, I have assumed that what Justin wants is a concave curve similar to an audio taper.

Justin,

I think what you are asking for is to be able to map an input number range from 0 to 127 to the same output range but in a non-linear fashion. Moreover, you seem to want the option to have either a linear mapping function or an exponential (inverse log) mapping function (that hopefully the ear will hear as more linear).

Here is a way that you can implement such a mapping. I'll illustrate with KSP script code (in KS-source format) but hopefully you can easily translate this into your plugin scripting language.

*on init*
``*declare* *const* Linear := 0
``*declare* *const* Exponential := 1
``*declare* *const* K := 127*127
``*declare* *const* Round := K/2
``*declare* Ramp[128]
``*declare* start_value
``*declare* end_value
*end on*


*function* Map(mode)
``*declare* n
``
``*for* n := start_value *to* end_value
````*if* mode = Linear
``````Ramp[n] := n
````*else* _{ Psuedo-Exponential }_
``````Ramp[n] := (n*n*n + Round)/K
````*end if* 
``*end for*
*end function* _{ Map }_


After you have set the start and end values you want, you then 'call' the Map function and specify the 'mode' (linear or exponential). This will fill the Ramp array (between the start and end limits) with the desired series of values. Then all you have to do is send these Ramp values (from index positions start_value through end_value) to Sibelius. Depending on how that is actually done, you might be able to alter the for-loop to send these values directly instead of storing them in the Ramp array.

This is just a straight-forward implementation of the equation I gave you which simulates and exponential curve with a cubic, which, if you were working with floating-point numbers would be;

```
Ramp[n] = (n/127)^3  rounded
```

However, I illustrated it with fixed-point integers.

Hope this helps you.

God Bless,

Bob


----------



## joris1974 (Feb 23, 2009)

Justin,

I took a look at your initial post, and although I see a lot of ideas already blooming, I figure I'd give it a shot. So, if I understand correctly, you're moving your volume from an initial value Vi to a final value Vf over a period of time T, and you are doing this by increments in a loop. Right? So the function you're trying to follow is :

V(t)=a*exp(b*t/T)

easily enough, you get a=Vi and b=log(Vf/Vi) from the boundary conditions.

Now for the increments, let's say your loop moves by an interval of time dt, hopefully small ; you'll get :

V(t+dt)=V(t)*exp(b*dt/T)

assuming, again, that dt is small, a Taylor development yields to the 2nd order (which may be good enough) :

V(t+dt)=V(t)*(1+b*dt/T+1/2*(b*dt/T)^2)

So that's your increment formula. Now calculating b requires the natural log, which ManuScript doesn't have. However, and maybe the bit twiddlers out there can confirm, I think you can have a good estimate of log2 (base-2 log) using bitwise operators, which are available in the utils.* class package. Since Sibelius 4 and on have floating point arithmetic, just multiply the log2 by log(2)~0.693147. I haven't worked on Sib. plugins in ages, so I'm afraid my offering of a solution falls short...

Best,
Joris


----------



## gmet (Feb 23, 2009)

Firstly I must apologise for the delay in replying (the time zone + a full time job get in the way!) 

Bob, Joris & Bear - thanks very much indeed for your input, I am constantly amazed at the generosity on this forum. 

Bob - your script solution looks like what I need (although I'll leave the discussion on the best mathematical formulae between the experts). 

I think I ought to try and be clearer about my aim as I don't think it is totally clear. The instruments I use are already X-fade patches i.e. the volume curve is already programmed. The idea of the script is so that crescendos and diminuendos sound more musical (i.e. musicians can produce linear, early or late cresc/dim depending on the music). So for the crescendos, imagine I am riding the mod wheel and get louder at a constant speed (linear), get loud early and then tail off (inverse exponential) or creep up and then a late dramatic increase (exponential). This would obviously work the other way round for a diminuendo.

Unfortunately, however, I misread the function of the original while loop. I will try to explain it in KSP as I don't think the "for n := start_value to end_value" will work as it will create a loop inside another loop.

*on init* 
``*declare* start_value 
``*declare* end_value
``*declare* volchange
``volchange = start_value - end_value _{the start and end values can be inverted to create a dim instead of cresc}_
``*declare* VolInc
````*if* (volchange < 0)
``````VolInc = -1
````*else*
``````VolInc = 1
````*end if*
``*declare* Spacing
``Spacing = Round(Duration_of_Cresc/(VolInc*volchange)) 
*end on* 

*function* Map(mode)
``*while* (write_position < end_position) _{while the current write position is less than the end position}_

````write_midi_value(write_position,Current_Volume)_{write the current midi volume in position}_
````write_position := write_position + Spacing _{increment to the next position}_

``````*if* mode = Linear 
````````Current_Volume :=``Current_Volume + VolInc _{+/- 1 depending on cresc or dim}_
``````*else* _{ Psuedo-Exponential }_ 
````````Current_Volume :=``Current_Volume + (Exponential_Increment*VolInc) _{* +/-1 depending on cresc or dim}_
``````*end if* 
``````
``*end while*
*end function* _{ Map }_ 

Thanks for your continued patience with this mathmatical idiot!

Regards,

Justin


----------



## gmet (Feb 23, 2009)

Sorry - should have also mentioned the following as I think it may help:

Sibelius script (ManuScript) supports floating point numbers. Conversion to integers is achieved with the 'RoundUp(Expr)', 'RoundDown(expr) and 'Round(expr)' functions which can be applied to any expression.

Justin


----------



## PolarBear (Feb 23, 2009)

*on init* 
(...)
``Spacing = Round(Duration_of_Cresc/(VolInc*volchange)) 
(...)
*end function* _{ Map }_ 

That is the crucial line for my concerns.

This means: Volume change of +70 (or -70 in another case) will result in 70 calculated values. Now in order to get "exponentials" or pseudo-exponentials done quite well we need to define some "resolution" in order to minimize the influences of artifacts but not overdo it with unneeded calculations...

Any ideas for an ideal controller-changes-per-second value? Somthing like 22kHz? Meaning 22000 possible changes/values per second? What are sequencers usually doing?

All the best,
PolarBear


----------



## gmet (Feb 23, 2009)

PolarBear - having thought about this again it would actually make sense to have more increments returned/calculated the slower the tempo, so there are no sudden jumps. It will be less distinguishable at faster tempos.

Justin


----------



## PolarBear (Feb 23, 2009)

Well this is not BPM dependant but more related to your ear being able to detect such jumps. Which is why it must be defined "per second".

In any case, if you are going to use hardware MIDI transmission in your setup, you seem to be bound to at most 1000 MIDI messages (or transmitted CC values for our matter) per second. Which should be enough I think. See also:
http://www.five12.com/doc/CcGen.html


----------



## Big Bob (Feb 23, 2009)

Hi Justin,

I've sort of run out of the time I can devote to this issue but, I leave you in good hands. *Polar Bear *and *Joris1974* are both math wizards and, on top of that, they seem to have a better grasp of what you are trying to do. Now, I really must get back to my overflowing 'in-basket' :lol: 

I sincerely hope you end up with what you want.

God Bless,

Bob


----------



## PolarBear (Feb 23, 2009)

Hmm... actually I hoped for you to step in with some kind of solution now Bob as I think you had the best grasp of what Justin was asking about since already the start of this thread...  Well... I'm not that kind of wizard you might think.

Good luck with your in-basket!


----------



## joris1974 (Feb 23, 2009)

Hi Justin and all

Well, wizardry I do not provide... I wish! Thank you for the compliment, though, Bob. Now I've gotta get myself a fancy pointy hat and order custom headphones for it :lol: 

Seriously, as far as the timing scale goes, I believe Sibelius uses a tempo-independent unit for note durations ; if you have used the "live start" and "live duration" under properties, I think a quarter note/crotchet is set to 256 "ticks" for lack of a better word. Check the ManuScript pdf under "durations", so that you can 1) use this unit as your time unit (so tempo doesn't matter) and 2) position your "~Cxx,yy" messages correctly in time. Now, if you really need more steps on a swell, say on a whole note at q=60 than you would at q=120, then use the actual time (in ms) which would be achieved by invoking utils.GetLocationTime or utils.GetObjectTime methods (bar.*.Time also exists, I think). My best advice would be to take a look at the continuous controller playback plugin, because the technique is essentially the same - only the "increment" changes - for which you can try some of the ideas suggested by our fine fellow members. If you have anything that runs but doesn't work as intended, I'd be happy to take a look and try to remember ManuScript. BTW, the Taylor expansion method that I suggested would work in both time frameworks (ticks and ms), as long as your total duration T is expressed in the same unit.

Joris


----------



## gmet (Feb 24, 2009)

Bob, thanks for your help so far. Joris and PolarBear, thanks for your continued help.

After a day of head scratching I now have a script that sort of does what I want. It uses Bobs solution, however I think there needs to be a relationship between the 'Spacing' (number of calculated values), and the equation itself, as the exponential curve reaches its peak too early. Here is the script in KSP form, although I have foregone the declarations as they are not needed in ManuScript.

Also is an image of the linear and exponential curves created.

*on init* 
``volchange = start_value - end_value 
``*if* (volchange < 0) _{the start and end values can be inverted to create a dim instead of cresc}_
````CrescDim = -1
``*else*
````CrescDim = 1
``*end if*
``tempo = obj.CurrentTempo _{tempo in BPM}_
``linelength = obj.Duration _{each beat is 1/256}_
``Spacing = Round(linelength /(CrescDim*volchange)) 
``K = 127*127
``Round = K/2
``Rate = 1 _{Ramp Rate}_
*end on* 

*function* Map(mode)
``*while* (writepos < endpos) _{while the current write position is less than the end position}_

````write_midi_value(write_position,Current_Volume)_{write the current midi volume in position}_
````write_position := write_position + Spacing _{increment to the next position}_``

*if* (CurveType``= Linear)
``````````VolInc = CrescDim
````````*end if*

*if* (CurveType``= Exponential)
``````````VolInc = ((Current_Volume*Current_Volume*Current_Volume + Round)/K)*Rate
````````*end if*

*if* (CurveType``= Inverse Exponential)
``````````VolInc = ? _{I really don't know how to work this one out!}_
````````*end if*
````````
````Current_Volume = Current_Volume + VolInc
``````
``*end while*
*end function* _{ Map }_ 

I would really appreciate it if you could alter my code rather than presenting a new theory in language I don't understand! 

Justin

EDIT: forgot to mention - I tried 1000 equations per second and Sibelius couldn't cope. I would guess that 128 is really the max as a mod wheel wouldn't create any more integers than this anyway.


----------



## gmet (Feb 24, 2009)

I have now resolved the issue of the exponential increments reaching the peak too early- I have essentially added a ramp rate. The final pice of my jigsaw is to get the inverse of the following solution by Bob (for an inverse exponential ramp):



> Ramp[n] := (n*n*n + Round)/K



which is a translation of:



> Ramp[n] = (n/127)^3 rounded



Justin


----------



## Big Bob (Feb 24, 2009)

Hi Justin,

If you want the convex counterpart of the concave cubic, couldn't you just reflect Ramp[n] across the linear line of symmetry? In other words, couldn't you just replace each Ramp[n] with 2*n - Ramp[n] or change your Ramp[n] assignment line to:

```
Ramp[n] := 2*n - (n*n*n + Round)/K
```

Just a quick thought as I was passing by :roll: 

God Bless,

Bob


----------



## gmet (Feb 24, 2009)

> If you want the convex counterpart of the concave cubic, couldn't you just reflect Ramp[n] across the linear line of symmetry? In other words, couldn't you just replace each Ramp[n] with 2*n - Ramp[n]



That was just poking fun at me!, however this is brilliant:



> change your Ramp[n] assignment line to:
> 
> ```
> Ramp[n] := 2*n - (n*n*n + Round)/K
> ```



Thanks again Bob,

My problem is now solved,

Best,

Justin


----------



## Big Bob (Feb 24, 2009)

> That was just poking fun at me!, however this is brilliant:



Now, now Justin, I wouldn't poke fun at you. I was just trying to get into the spirit of the other posts (but I just couldn't bring myself to dump any cube-root algorithms on you) :lol: 

I'm very glad that this simple idea did the job for you.

You have a beautiful day my friend.

Maranatha,

Bob


----------



## gmet (Feb 25, 2009)

Justin M @ 25th February 2009 said:


> [Thanks again Bob,
> 
> My problem is now solved,



Bob, PolarBear & Joris, I spoke too soon!

The equations give me image A {Ramp[n] := (n*n*n + Round)/K }
and image B {Ramp[n] := 2*n - (n*n*n + Round)/K}

I know it is totally down to my poor descriptions, however what I actually wanted was A and C.

Justin

(p.s. I did this in photoshop by flipping the images - I wish I knew how to do this with maths!)


----------



## Big Bob (Feb 25, 2009)

We meet again :lol: 

There is something wrong with the B pix. I realize you said that you created these in PS (BTW did you mean A, B, and C or just C?) If I take the B pix to represent the actual mathematical results you are getting from the new formula, 'it doesn't compute' as they used to say :roll: .

For example, plug n = 0 into the equation and the result should be zero but your B pix indicates that the result is 127. That can't be right :? 


```
2*n - n*n*n/K = 2*0 - 0*0*0/K = 0 - 0 = 0
```

Now try n = 127:


```
2*127 - 127*127*127/K = 254 - 127 = 127
```

Yet, pix B shows that at n = 127 you get a value of zero. ???

However, I should tell you that the formula I gave you will not produce the result you show in pix C. It will give you a somewhat different convex shape. If you draw the straight linear response line from 0 to 127, the new formula I gave you should produce a point by point reflection of the old curve (as if the linear response line was a mirror and the new curve is what you would see in such a mirror). If you want the curve shown in pix C instead, I can give you its formula but until you can explain why the second formula produces such strange results, I don't think I ought to give you 3rd formula. Let's first get #2 to work properly.

Maranatha,

Bob

EDIT: I think I'm going to quit for the day so while your sleeping, I'll put formula #3 under your pillow (you know, like the tooth fairy) :lol: 

```
If Pix A is given by:  Y = (n*n*n + Round)/K   for  n = 0..127, 
then: Pix C would be: Y = 127 - [(127 - n)*(127 - n)*(127 - n) + Round]/K
```

Now you can sort all this out with your morning coffee (tea?)


----------



## joris1974 (Feb 25, 2009)

Hi all,

I was just about to jump on the bandwagon when I saw that Bob had already given the answer. However, for the increment itself, shouldn't it be just :
[(127-n)^3+round]/K ?

... or maybe I'm just tired!

BTW, Justin do you know how your ramps compare to the early/late options that I believe to be available for hairpins (on Sib. 5). I may be wrong about this, but I remember that those options are available for tempo lines, trills and gliss., so, logically on hairpins as well. That would be interesting to see what kind of ramps Sibelius uses besides the default linear...

Joris


----------



## gmet (Feb 26, 2009)

Thanks guys (this thread is becoming an epic!)

Bob, I never thought of you as a fairey, but the surprise was just right after taking my wippets and ferrets for a stroll along the Old Kent Road this morning (After my black pudding and tea). :lol: 

I should have mentioned that all the diagrams in my previous post started at zero (so the math was as you had expected).

Joris, you were indeed right about the equation - thanks. Unfortunately the early/late options in Sibelius are only for accel/rall etc.

Here is an actual image (from Cubase) of the returned values with all the equations so far (linear, exponential and inverse exponential - both crescendo & diminuendo, and various note lengths). It serves my requirements on the 0-127 scale, however as soon as I change the start and end values (e.g. 32-96) I get very unexpected results. Is there something that needs to change to scale the output for other start and end values (i.e. when the overall volume change is different)?

Regards,

Justin


----------



## gmet (Feb 26, 2009)

Hi Bob,

I appreciate that this subject is probably dragging on a bit for you!

In regards to the A,B,C image; there was no problem with your equations. A slopes up from 0, B slopes down from 0 and C is what I now have.



> If you are simply traversing the curve between n = 32 and n = 96 as I suggested originally, then what you should see is just that section of the curve.


If the crescendo goes from volume 0-127 then the curve is fine. If the crescendo is from say 32-96 then I don't want to traverse the 0-127 curve between 32-96 section.

What I would want is a curve based on the new volume difference (in that case 64), starting at 32 and doing its own exponential curve to 96.

There must be something in the equations that I can set as a variable depending on the range of the curve.

Justin

b.t.w. - I have learned so much on this little journey that it will be worth it in the long run!

I have also attached an image of the plugin as it stands at the moment.


----------



## gmet (Feb 26, 2009)

Hans Adamson @ 26th February 2009 said:


> Hello Justin,
> 
> I am trying to follow this thread. Where can I find the images mentioned?
> 
> ...



Hi Hans - as far as I am aware you can't see any attachments of any description unless you're logged in.

Glad you're taking an interest.

Justin


----------



## Hans Adamson (Feb 26, 2009)

Justin M @ Thu Feb 26 said:


> What I would want is a curve based on the new volume difference (in that case 64), starting at 32 and doing its own exponential curve to 96.


So the script is not to be applied in real-time? Or do you in this case want an exponential curve between 32 and 127, although you are only using the portion up to 96?


----------



## gmet (Feb 26, 2009)

Hans,

None of the plugins in Sibelius work in real time, they merely add information ready for playback. I want the exponential curves to go between the start and end values, not a part or section of a bigger curve. Here is what I _think_ it might look like:

So 0-32 becomes Ramp[n] = (n/32)^3 rounded

32-96 becomes Ramp[n] = (n/64)^3 rounded

25-75 becomes Ramp[n] = (n/50)^3 rounded

I know that looks like I have just answered my own question, however I don't know how to convert that into a workable code.

Justin


----------



## Hans Adamson (Feb 26, 2009)

I am not a mathematician or programmer, but took a stab anyway:

VO/Vm*127 = cc1 + [(n-cc1) / (cc2 - cc1)]^3 / (cc2 -cc1)^3 ) 

VO = Output volume
Vm = Maximum volume
cc1 = ramp start point
cc2 = ramp end point
n = any cc value along the ramp between cc1 and cc2

Edit: VO/Vm*127 = cc1 + [(n-cc1) / (cc2 - cc1)]^3 / (cc2 -cc1)^2 )

Or maybe rather Edit 2: VO/Vm*127 = cc1 + (n-cc1)^3 / (cc2 -cc1)^2

Well, anyway interesting... 8)


----------



## Big Bob (Feb 26, 2009)

You could be right Hans but, since I don't really know what Justin wants, how would I know? :oops: 

But, I'm going to stop second guessing. I'm going to wait until I see a set of illustrative numerical tables. I think the reason this is taking so much effort is that the requirements have never been defined in any clear and rigorous way. At least not to me. This is why I stated early on that my lack of knowledge about Sibelius could be a problem because I have merely been trying to provide what I thought was the desired transfer function as a formula (without regard for how Justin or Sibelius intended to use it). 

Since Justin is struggling with the math, we need to find a way to allow him to express what he wants. But that way must be rigorous enough so it can be translated into the math functions needed. This is why I am suggesting a few sparse tables because they require very little math skill to fill in. In fact, if Justin can't fill in the two end-point values and at least a rough approximation for the center value, then he probably doesn't really know what we are shooting for here :lol: 

Maranatha,

Bob


----------



## gmet (Feb 26, 2009)

Bob, Hans - Thanks for your continued patience, I am working on it. It's just taking a while!

Justin


----------



## gmet (Feb 26, 2009)

OK - here we go. Due to the rounding the Inv Exp figures might not be exact but I hope it gives you the idea.

Justin


----------



## Big Bob (Feb 26, 2009)

Hi Justin,

Now we're cooking 8) . But before I give you the math function, let me verify my understanding of what you want by predicting the sparse table for 32 to 96 for the exponential curve (since you didn't illustrate that range).

```
X     Y
    32   32
    64   40
    96   96
```

If you agree with my 'prediction', then I think I know what you want and will post it for you shortly.

God Bless,

Bob

EDIT: Whoops :oops: I first now saw your footnotes which of course clarify that what I just posted is indeed what you would want. So hang on, as soon as I get a few minutes, I'll post your function for you.


----------



## Big Bob (Feb 26, 2009)

OK, I was in the middle of something I had to finish first. Now for Formula #4 :lol: 


```
Ramp[n] = S + (E-S)*[(n - S)/(E - S)]^3    where S = start value, E = End value
or  Ramp[n] = S + (n - S)^3 / (E - S)^2
```

If you have floating point available, then you may be able to use this formula as is. If not, let me know and I'll re-express so that you can use only integer arithmetic.
Also, the above is only the exponential form, if you can't deduce the inverse, let me know.

BTW: I hope you haven't been trying to read this post while I've been editing it :lol:


----------



## Hans Adamson (Feb 26, 2009)

Big Bob @ Thu Feb 26 said:


> OK, I was in the middle of something I had to finish first. Now for Formula #4 :lol:
> 
> 
> ```
> ...


Hot dog!

That's my formula...
VO/Vm*127 = cc1 + (n-cc1)^3 / (cc2 -cc1)^2


----------



## Big Bob (Feb 26, 2009)

> Great Stuff Bob, it must be hugely frustrating for you to deal with somebody way below your intelligence level!



Actually, I haven't run into Alfred E. Newman types :lol: on this forum so I wouldn't know what it would be like to deal with someone way below my intelligence level :roll: Don't sell yourself short Justin, no one knows everything about everything and that sure includes me. We just do what we can to help each other, no?



> I presume for the crescendo I will add 'startvol +' to the beggining and for the diminuendo 'endvol -'.



Actually I think the formula can be left as it is. For decrescendo you simply set S > E, the formula should still work.

And, since I wouldn't want you to lose another tooth tonight, I'll just leave the inverse exponential for you now.

```
Ramp[n] = E - (E - n)^3 / (E - S)^2
```
Again, this formula should work for both crescendo and decrescendo. And, BTW, your latest graphics do depict what you should get with these formulae.

God Bless,

Bob


----------



## gmet (Feb 26, 2009)

Thanks everyone (Joris, PolarBear & Hans) for your help but especially to you Bob for all you contribute here on the forum. Once I have finished I will post some results as I did with my last head scratching idea, hopefully to prove it makes a difference:

http://www.vi-control.net/forum/viewtopic.php?t=9548

Until my next bout of inspiration, which won't be soon I assure you,
have a beautiful day my friend. 

Regards, 

Justin

p.s. just realised it is 00:50 here in sunny London - better go to bed!


----------



## Big Bob (Feb 26, 2009)

> Hot dog!
> 
> That's my formula...
> VO/Vm*127 = cc1 + (n-cc1)^3 / (cc2 -cc1)^2



Hey Hans,

Sorry I missed your post that slipped in between. Congratulations o-[][]-o 
You had the answer before I even understood the question :oops: 

And Justin,

I sure hope all the effort you put into this is crowned with success, pleasant dreams :lol: 

God Bless,

Bob


----------



## Hans Adamson (Feb 26, 2009)

Big Bob @ Thu Feb 26 said:


> > Hot dog!
> >
> > That's my formula...
> > VO/Vm*127 = cc1 + (n-cc1)^3 / (cc2 -cc1)^2
> ...


 :D :D :D 

You are still the teacher Bob. 8)


----------



## PolarBear (Feb 27, 2009)

Hans Adamson @ Thu Feb 26 said:


> So the script is not to be applied in real-time?


There is no way for this (or even linear volume changes) to be calculated on the fly without knowing the duration for it. you could perhaps set a few fixed-width values for duration that you trigger somehow otherwise if you really need that (like 0.3 seconds, 0.5 seconds, 1 second or similar). The other way would be to have the curve applied directly after the endpoint passed at the positions between start and end, and "approximate" it in real-time only by a linear curve.

However I'm not sure if you understood you correctly on this matter...

In any case... now you can also add something like this to your crossfade portfolio:





Just calculate the "exp cresc" from 0 to 63 and the "inv exp cresc" from 64 to 127, both for half the desired duration.

I didn't read all posts completely anymore, but it looks like the matter is solved now completely? Or do you need some help with the inv and cresc/decresc equations?

All the best,
PolarBear


----------



## PolarBear (Feb 27, 2009)

Now hey... geeky stuff ahead.

I found a way to quickly approximate the numbers without the need for calculating values above 127, and to do this task using only a while-loop and two different increments. And I think the resolution is big enough for about any short to mid-long duration even.

Actually I just did this for me, but maybe Bob and some other wiz's are interested.

If you have start point with value 1 set to step 35 of 127 and increment inc1 and increment inc2 set to
inc1 = 0 and inc2 = 1 for result values <16
inc1 = 1 and inc2 = 1 for result values <32
inc1 = 1 and inc2 = 2 for result values <64
inc1 = 2 and inc2 = 3 for result values <128
(the light blue line in the pic)

you approximate the green x^3 derivate line we implemented in this thread (red being a 6 segment linear approximation rounded to the next lower integer) and blue x = y. (Click on picture or link belowfor higher res).




[url=http://666kb.com/i/b6sonx02b3vwsl4jl.gif]http://666kb.com/i/b6sonx02b3vwsl4jl.gif[/url]

One could it refine even more with 3 different increments for the beginning, but is it really that noticable to have volume changes lower than 0.5 per step on average given the speed this will run at? (You looked at the hi-res picture, compare that to the lo-res one, is it really, really needed?)

Well, simple solution could also be to have
values < 26 set 0
values < 32 set 1
values < 38 set 2
and start the approximation from there.

Or just
values < 26 set 0
values < 35 set 1 (start of approximation)

But again... all this effort to have a little 1 standing somewhere? It's about speed hehe  And actually, max increase of 3 per step - that can fit any duration IMHO.

:D :D

Now Justin, what was that interjection with your 2nd order Taylor approximation again about? (I'm joking here, haha)  Then again, it may not be of much worth as we need to extrapolate to floating point in any case we want anything else but fades from 0 to 127.


----------



## Big Bob (Feb 27, 2009)

Hi Polar Bear,

I guess this thread never wants to retire in peace :lol: But, since I thought it was retired, I have now gone back to working on my 'kline bottle' which I intend to exhibit at the next World's Fair :lol: 

Have fun everyone.

Bob


----------



## ComposerDude (Feb 27, 2009)

Polar - nice work, especially the closeness of fit to the theoretical curve.

Bob - For your Kline bottle, I imagine you'll draw the blueprints on a Mobius strip first.

-Peter


----------



## PolarBear (Feb 27, 2009)

Hehe... thanks  Just also remember the "theoretical curve" is completely arbitrary...


----------



## Big Bob (Feb 27, 2009)

> Bob - For your Kline bottle, I imagine you'll draw the blueprints on a Mobius strip first.



Actually, I drew mine on a napkin that someone had scribbled e = mc^2 on :roll: But I forgot to mention that the World's Fair I was talking about was the new 4th-dimensional World's Fair to be held yesterday, so I think this should work out just fine. :lol:


----------



## gmet (Mar 1, 2009)

PolarBear - that was way over my head, but thanks anyway!

Justin


----------



## PolarBear (Mar 1, 2009)

Well basically it's just a 4-segment (well, actually 5-segment) linear ramp. The geeky stuff of it - you can calculate that with while-loop and plus operator.

You can express that also with multiplications which might look a bit easier... slopes are:
0.0*x up to step 35
0.5*x up to step 65 (result values below 16)
1.0*x up to step 81 (result values below 32)
1.5*x up to step 102 (result values below 64)
2.5*x up to step 127

But nevermind. It's of little practical value to you.


----------

