# Multiple output equal power XFade?



## tomaslobosk (May 19, 2015)

Hi everyone!
I'm making a custom script to equal power crossfade between specific groups, each group is a dynamic layer.
e.g. Group 1: p, Group 2: mp, Group 3: mf & Group 4: f

EP_XFade function from KSPMathV701.ksp only has 2 output variables, so I can't equal power crossfade between all 4 groups, only in pairs.

Is there a workaround to get this working?, greetings!


----------



## d.healey (May 19, 2015)

Why don't you use modulators?


----------



## tomaslobosk (May 19, 2015)

because IMHO they aren't as accurate as true equal power xfades :(


----------



## Big Bob (May 19, 2015)

Hi Tomi,

As you swing your crossfade variable XV from say 0 to 100%, I would think that you would want to smoothly xfade from p to mp to mf to f. Or, more specifically you would want to xfade for a specified overlap region between each volume layer. For example perhaps something like this:


```
0 - 14%  p only
15 - 28    p X mp   { crossfade p and mp }
29 - 42   mp only
43 - 56    mp X mf
57 - 70   mf only
71 - 84    mf X f
85 - 100  f only
```


If this is the kind of thing you are trying to do, don't you actually only want to hear at most two layers at a time? 

The way you have worded your post, it sounds like you are thinking that somehow it will be required to have 3 or even 4 layers sounding at once. If so, I'm not quite sure what you are trying to do. Perhaps you could elaborate a little on your intended requirement?

Rejoice,

Bob


----------



## tomaslobosk (May 19, 2015)

Thanks Bob for your quick answer!!!... a picture is worth a thousand words:







hope this answer your questions 

EDIT: But I must say... your answer is better: longer intervals with no crossfades.


----------



## Big Bob (May 19, 2015)

Hi Tomi,

Well, if you actually want to implement it the way you show in your pix, it looks to me like there are still only two layers sounding at any one time.

I think you could achieve this by xfading mp and p for 0 to 33%, then flipping the A/B roles and continuing for another 33%, then flip AB again for the last 33%.

To elaborate, from 0 to 33%, p would be the 'down curve' or cosine while mp would be the 'up curve' or sine. Between 33 and 66%, mp would become the cosine and mf would be the sine. Lastly, between 66 and 100%, mf would switch to the cosine and f would be the sine.

Basically your scheme reduces the solo layers to zero size whereas my post describes the situation where the solo layers occupy some non-zero width.

So, in any case, it seems to me that you still only need to crossfade two layers at a time throughout the entire 0 to 100% XV range, no? :lol: 

Rejoice,

Bob

BTW You should be able to do this using the Math Library EP_XFade routine plus some surrounding code.


----------



## tomaslobosk (May 19, 2015)

Exactly, I need two layers sounding at any one time...
Now I'm trying to do it based on your answers!, so thank you very much, i'll post the results 

Greetings, Tomás.


----------



## Big Bob (May 20, 2015)

Hi Tomás,

If I get a chance later today, I'll post some illustrative code for doing it both ways. By that I mean with zero and non-zero solo zone widths. In fact, I'll just make the Solo Zone size a compile-time constant. When you set it to zero, you'll get the curves you depicted.

BTW What do you intend to use to control the xfade? If you are planning on using just a MIDI CC with only 128 values, the crossfades may be a bit crude. With 4 layers. the xfade zones can only be 32 steps or less. It might be better to use either the pitch wheel or one of the NRPNs because they at least have 14 bit resolution.

To be continued ...

Bob


----------



## d.healey (May 20, 2015)

TomiLobosK @ Tue May 19 said:


> because IMHO they aren't as accurate as true equal power xfades :(



They can be "true equal power", just change the shape in the modulation window - I usually go with an S shape. If you are planning on controlling your crossfades with a CC then you won't lose any resolution because both the CC and modulation values go from 0-127. It's also a good idea to add a bit of smoothing (lag) time to the modulator.


----------



## tomaslobosk (May 20, 2015)

Thank you very much Bob! I'll check your code later 
I was thinking to control the xfade with CC, but indeed... it isn't smooth :(... I saw in your last code (Instrument Crossfade Multiscript) that you used some kind of smoothing, is this applicable in this case?

Edit: May I suggest to you to extend the EP_XFade function in your KSP Math Library to multiple (>2) outputs?, huge time-saver when doing this kind of XFades.



> They can be "true equal power", just change the shape in the modulation window - I usually go with an S shape. If you are planning on controlling your crossfades with a CC then you won't lose any resolution because both the CC and modulation values go from 0-127. It's also a good idea to add a bit of smoothing (lag) time to the modulator.



But you are missing all the math fun! haha :lol:


----------



## Big Bob (May 20, 2015)

Hi Tomás,

Here's a coding example you can look at. If you compile this script with SoloZone size set to zero, it should produce the function you depicted in your graph. On the other hand, if you compile with SoloZone set to some non-zero value, there will be no xfade in these zones and it will behave more like what I described in my table.


```
import "KSPMathV701.ksp"

on init
  message('')
  SetMathMode(0,0)
  declare const SoloZone := 0
  declare const XFPmax := 3000 + 4*SoloZone
  declare Gx[4] := (0,1,2,3)  { group indices for p, mp, mf, f }
  declare XSet[6] := (0,1,2,1,2,3)    { crossfade pairs: cos,sin }
  declare MuteSet[6] := (2,3,0,3,0,1) { muted pairs }
  
  declare ui_knob XFade (0,10000,1)
  declare ui_knob Morph (0,1000,1)
  
  declare idx   { index of active cursor zone }
  declare mv    { morphing variable }
  declare XFP   { xfade cursor position, 0..XFPmax }
end on

on ui_control(XFade)
  XFP := XFade*XFPmax/10000
  call do_xfade
end on

on ui_control(Morph)
  mv := Morph
  call do_xfade
end on

function do_xfade
  declare Ea
  declare Eb
  declare VRa  { down curve, ie cosine }
  declare VRb  { up curve, ie sine }
  declare xv
  select XFP
    case 0 to SoloZone
      xv := 0
      idx := 0
    case SoloZone+1 to SoloZone+999
      xv := XFP - SoloZone
      idx := 0
    case SoloZone+1000 to 2*SoloZone+1000
      xv := 1000
      idx := 2
    case 2*SoloZone+1001 to 2*SoloZone+1999
      xv := 2*SoloZone+2000 - XFP
      idx := 2
    case 2*SoloZone+2000 to 3*SoloZone+2000
      xv := 0
      idx := 4
    case 3*SoloZone+2001 to 3*SoloZone+2999
      xv := XFP - (2000+3*SoloZone)
      idx := 4
    case 3*SoloZone+3000 to 4*SoloZone+3000
      xv := 1000
      idx := 4
  end select
  EP_XFade(xv,mv,VRb,VRa)
  Ea := epVR(V2E,VRa)
  Eb := epVR(V2E,VRb)
  set_engine_par(ENGINE_PAR_VOLUME,Ea,Gx[XSet[idx]],-1,-1)    { cos group }
  set_engine_par(ENGINE_PAR_VOLUME,Eb,Gx[XSet[idx+1]],-1,-1)  { sin group }
  set_engine_par(ENGINE_PAR_VOLUME,0,Gx[MuteSet[idx]],-1,-1)  { mute groups }
  set_engine_par(ENGINE_PAR_VOLUME,0,Gx[MuteSet[idx+1]],-1,-1)
end function
```

The internal resoluation of the script is 1000 steps per crossfade or 3000 total for the 3 xfades. In addition, there are 4 enclosing solo zones so the total resolution of the the internal xfade variable, named XFP, will be 3000+4*SoloZone. For this demo script, I used an xfade knob with a resolution of 10000 and mapped it to the XFPmax range in its callback handler.

To size the Solo zones, think in terms of what fraction of the crossfade width you want. The xfade widths are always 1000 steps so if you make SoloZone = 500, these zones will each be one-half that of the crossfade width, etc.



> Edit: May I suggest to you to extend the EP_XFade function in your KSP Math Library to multiple (>2) outputs?, huge time-saver when doing this kind of XFades.



Well, you could easily parameterize the do_xfade function in the example code. However, I'll think about maybe generalizing this a little for a future library release. But, I think for now, this is not too difficult to do externally.



> I saw in your last code (Instrument Crossfade Multiscript) that you used some kind of smoothing, is this applicable in this case?



Yes, you could add a low-pass filter to deal out the ep data like I did with the multiscript. Let me know if you'd like to try for that and I'll post the KSE source code for the MS for you to study.

Rejoice,

Bob


----------



## tomaslobosk (May 20, 2015)

Amazing job Bob, thank you!

Here is my first attempt:


```
import "KSPMathV701.ksp"
on init
    message('')
    make_perfview
    set_ui_height(2)
    SetMathMode(0,DG) 
    
    declare $mv:=0

    declare ui_value_edit $Slider (0,3000,1)
    make_persistent($Slider)

    declare ui_knob $VL1 (0,10000,1)
    $VL1:=10000
    make_persistent($VL1)

    declare ui_knob $VL2 (0,10000,1)
    $VL2:=0
    make_persistent($VL2)
 
    declare ui_knob $VL3 (0,10000,1)
    $VL3:=0
    make_persistent($VL3)

    declare ui_knob $VL4 (0,10000,1)
    $VL4:=0
    make_persistent($VL4)
end on

on ui_control($Slider)
    if $Slider>=0 and $Slider<1000
        $VL3:=0
        $VL4:=0
        EP_XFade($Slider,mv,VL2,VL1)
    end if
       
    if $Slider>=1000 and $Slider<2000
        $VL1:=0
        $VL4:=0
        EP_XFade($Slider-1000,mv,VL3,VL2)
    end if
    
    if $Slider>=2000 and $Slider<=3000
        $VL1:=0
        $VL2:=0
        EP_XFade($Slider-2000,mv,VL4,VL3)
    end if
end on
```

Yay! my code is very similar to yours: 1000 steps per crossfade, and 3000 steps for all crossfades... only mine lacks solo zones.

Knobs were put there for demonstrative purposes only!

However, what i'm trying to do requires that CC[1] controls $Slider, VL1 controls CC[100] , VL2 controls CC[101] , VL3 controls CC[102] and VL4 controls CC[103].

CC[100-101-102-103] are used to modulate group's (1-2-3-4) amplifier respectively.

It works!, but it's not smooth enough.


----------



## Big Bob (May 20, 2015)

You are also using epVR aren't you? You can't directly control Kontakts volume knobs with just the Volume ratio, it has to be converted to dB somewhere along the line you know. IIRC kontakt simply maps CCs linearly to the knobs they are controlling. ie CC = 64 will rotate the knob 50% of full scale, etc.

Rejoice,

Bob


----------



## tomaslobosk (May 20, 2015)

I'm not controlling volume knobs directly, I'm mathematically converting [0 - 10000] output values to [0 - 127] CC(100-101-102-103) values to use them as modulators of group's amplifiers... does this make sense??


----------



## d.healey (May 20, 2015)

TomiLobosK @ Wed May 20 said:


> I'm not controlling volume knobs directly, I'm mathematically converting [0 - 10000] output values to [0 - 127] CC(100-101-102-103) values to use them as modulators of group's amplifiers... does this make sense??



Just use modulators then you don't need to script this. There is no advantage to scripting this from what you have said, if anything your instrument will be less efficient because it is performing extra tasks.


----------



## Big Bob (May 20, 2015)

Oh, I thought you intended to use the eps to control the group volumes. Since this is apparently not the case, I think I have to agree with David.



> Just use modulators then you don't need to script this



I mean apart from the 'fun with the math', what advantage is there to doing it the hard way :lol:


----------



## mk282 (May 20, 2015)

Modulators will be more efficient than scripting, yes.


----------



## tomaslobosk (May 20, 2015)

Honestly... I don't wanna draw all these curves!, specially when dealing with more dynamic layers hehe :lol:

EDIT: But yeah, you're right, increasing the number of dynamic layers will make everything a LOT less smoother... am I the only one who thinks that kontakt should support equal power crossfades natively?


----------



## d.healey (May 20, 2015)

You don't have to, here are some presets  they are S-shaped rather than just equal power but with a little lag time they produce some really smooth dynamic layer crossfades.


----------



## tomaslobosk (May 20, 2015)

Thanks David, I've downloaded these in the past... unfortunately they aren't equal power curves, they are more like sine, cosine curves... correct me if i'm wrong.
EDIT: My mistake! you said it! hehe :lol:
EDIT 2: I would love to have some table-based equal power curves, 'cos these haven't worked for me in the past.


----------



## d.healey (May 20, 2015)

make some, you only need to do it once then save them as a preset, you can get the script you've been writing to produce the table values for you and then you just enter them into the modulation table - it will be tedious but at least it's a one time only job  then upload them here.


----------



## tomaslobosk (May 20, 2015)

I was thinking to do that, but i don't really know how enter values in the modulation tables :(, if you know how, tell me and i'll do it for sure!


----------



## d.healey (May 20, 2015)

Look up modulation shaper in the Kontakt reference manual it gives detailed instructions. Basically you click and drag, right click and drag for straight lines, ctrl+click to delete a bar. May be different on Mac.


----------



## tomaslobosk (May 20, 2015)

I mean, enter values to tables with scripting... no way am I doing that by hand! :shock:

EDIT: GOT IT!, now just wait and see 8)


----------



## tomaslobosk (May 20, 2015)

just made them David, check them out:

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


----------



## d.healey (May 21, 2015)

Looks good, how did you do it?


----------



## tomaslobosk (May 21, 2015)

Basically I made all tables in Excel evaluating Sin and Cos functions, exported them to a .txt file and imported them into Kontakt:


----------



## d.healey (May 21, 2015)

Brilliant! I never new about that!


----------



## tomaslobosk (May 21, 2015)

Neither did I... until yesterday! :lol: hahaha


----------



## polypx (Jun 6, 2015)

Big Bob @ 2015-05-20 said:


> Yes, you could add a low-pass filter to deal out the ep data like I did with the multiscript. Let me know if you'd like to try for that and I'll post the KSE source code for the MS for you to study.



Bob, I would very much like to see a (hopefully simple) version of the above script you posted with LPF smoothing. 

cheers,
Dan


----------



## Big Bob (Jun 6, 2015)

Hi Dan,

Are you talking about the source code I posted at the end of this thread?

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

Rejoice,

Bob


----------



## polypx (Jun 6, 2015)

Hi Bob!

I did look at that MS version, but it's a fair bit more complicated than the script above. I was hoping that if I saw the above one with smoothing added, I might understand the changes made more easily. 

I believe the cc_filter function is the heart of the smoothing in that other script, so maybe I need to knuckle down and work my way through the logic of that.

Thanks !

cheers
Dan


EDIT - also, my goal is to try and smooth the input from a slider (ie. XFade) or knob specifically, rather than from a CC. I often find slider control of Kontakt's parameters a bit too rough, and would like to smooth GUI input generally.


----------



## Big Bob (Jun 6, 2015)

Hi Dan,

Sorry but the 'above' script existed only as posted. However, you might want to take a look at the document I wrote about 4 years ago titled 'Inertial Knob Mathematics'. 

http://www.bigbobsmusicworld.com/kontakt-documents

I wrote this when I was helping Mario implement an Inertial Knob for one of his projects. The technique and the math involved in scripting a lag filter is essentially the same as that for an inertial knob (since they are both based on a digital simulation of a LPF).

I've kind of been toying with the idea of documenting these scripting concepts in a more general way but I'm not sure how much interest there is in this sort of thing.

Rejoice,

Bob


----------



## polypx (Jun 6, 2015)

Thanks Bob! Super helpful document, especially for the explanation of scale and time constants needed for a particular range. The concept is much clearer in my head now -- next, the application of that. 

cheers! 
Dan


----------



## Big Bob (Jun 6, 2015)

> The concept is much clearer in my head now -- next, the application of that.



That's always the fun part isn't it? :lol: But, I'm sure you will prevail. 

Rejoice,

Bob


----------

