KSP - controlling several send knobs on separate buses

Discussion in 'KONTAKT: Sampling, Programming & Scripting' started by KrisY, Jul 25, 2018.

  1. KrisY

    KrisY Noob in frenzy loop

    80
    5
    Mar 28, 2018
    Denmark
    Hello. I have a script that have UI-elements that control different functions. One of them is a switch that (if set to "1") activates a while loop, which is supposed to fade up the volume of several send knobs on an instrument bus. There are several IR convolution reverbs, and each of them is tied to a switch on the UI.

    Ok, so one knob controls some send knobs, and another knob controls other send knobs. They are the same send effect knobs, but on different buses. I have several groups that are routed through separate buses to create bigger groupings.

    The script is supposed to let one knob control the sends on certain buses. The other switch controls the other buses. They should be able to do their thing separately of each other. Independently of each other´s functions, so to speak. But if one is turned on, the other stops working.

    Why??

    Here is the script:
    (only the on controller part, as I am keeping this issue separate from the rest of the script while testing my errors out.)

    Code:
    on controller
    
    
    
        if (%CC[64] > 63)                    { just needed for the while loop to stop if pedal is released, IE it stops the loop }
            $susPedalOn := 1                { ... and starts the deceasing vol. This is instead of using the "stop_wait" command, not in earlier versions }
    
            else
    
            $susPedalOn := 0
    
        end if
    
    
    
        {FIRSTLY, A IF STATEMENT FOR WHAT TO HAPPEN ON CONTROLLER IF A SWITCH IS ON, OR OFF, as seen in the "else" statement}
    
        if ($fxPedalIRstrResonance_MuteButton = 1)
    
            if (%CC[64] > 63)
    
                while ($increasingVol < $maxVolumeSendLevel and $susPedalOn # 0)
                    wait(2000)
    
                    { send 4(3) - string resonance send fade IN }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1815,-1,7,$NI_BUS_OFFSET + 0) 
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 3)
    
                inc($increasingVol)
                end while
    
            end if
    
            if (%CC[64] < 64)
    
                while ($increasingVol > $minVolumeSendLevel and $susPedalOn # 1)
                    wait(1000)
    
                    { send 4(3) - string resonance send fade OUT }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 3)
    
                dec($increasingVol)
                end while
    
            end if
    
        else
    
            { send 4(3) - string resonance send fade OUT }
            set_engine_par($ENGINE_PAR_SENDLEVEL_3,0,-1,7,$NI_BUS_OFFSET + 0)
            set_engine_par($ENGINE_PAR_SENDLEVEL_3,0,-1,7,$NI_BUS_OFFSET + 3)
    
    
        end if
    
    
    
    
        {AND NOW ANOTHER IF STATEMENT WITH WHILE LOOPS FOR ANOTHER SET OF FUNCTIONS - IF THAT VARIABLE IS PRESSED...}
    
        if ($fxIRBox_MuteButton = 1)
    
            if (%CC[64] > 63)
    
                while ($increasingVol < $maxVolumeSendLevel and $susPedalOn # 0)
                    wait(2000)
    
                    { send 4(3) - string resonance send fade IN }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1815,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 3)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 6)
    
                inc($increasingVol)
                end while
    
            end if
    
            if (%CC[64] < 64)
    
                while ($increasingVol > $minVolumeSendLevel and $susPedalOn # 1)
                    wait(1000)
    
                    { send 4(3) - string resonance send fade OUT }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 3)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 6)
    
                dec($increasingVol)
                end while
    
            end if
    
        else
    
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 0) 
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 3)
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 6)
    
    
        end if
    
    
    end on

    The repetition of while loops for the same thing (although not for the same objects), may be causing one object to interrupt the other.

    Or am I missing something?

    Thanks upfront!
     
  2. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
    Yes it's likely because of wait(). You might wanna look into using task functions within SublimeKSP...
     
    KrisY likes this.
  3. OP
    OP
    KrisY

    KrisY Noob in frenzy loop

    80
    5
    Mar 28, 2018
    Denmark
    Thanks for the reply!

    But how could it be because of the "wait" command? They are within 2 separate while loops and conditions. Apart they are functioning fine, but when they are both active only one works.

    What I can gather is that the conditions for both loops are identical, but the initial conditions:

    "if ($fxPedalIRstrResonance_MuteButton = 1)"

    ... and

    "if ($fxIRBox_MuteButton = 1)"

    ... are different. Both using the same procedure and conditional code.

    Perhaps I need to restructure it? The initial point here is the actual buttons. The one´s referenced in the above 2 lines. "$fxPedalIRstrResonance_MuteButton" and "$fxIRBox_MuteButton". Making "if (%CC[64] > 63)" the initial condition might make it different. I would start with that and then have 2 nested conditions, the variables just mentioned ($fxPedal...) inside of that.

    Any thoughts on that?

    Thanks for listening.
     
  4. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
    If one condition triggers while the wait loop is not done from the previously triggered condition, you're in a pickle. You need to use task functions for this.
     
    KrisY likes this.
  5. OP
    OP
    KrisY

    KrisY Noob in frenzy loop

    80
    5
    Mar 28, 2018
    Denmark
    Okay, I see. Is there a direct link to such a function? I don´t really know what that is.
     
  6. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
  7. OP
    OP
    KrisY

    KrisY Noob in frenzy loop

    80
    5
    Mar 28, 2018
    Denmark
    I found the solution to this one. My script attempted to call multiple while loops with wait commands. As EvilDragon suggested, the solution was a tcm.wait. As it were, my solution was far simpler as my loops were unnecessary altogether.

    I re-wrote the while-loop so the if-statements with UI button switches are inside of the while, like most do. For this specific problem my issue is solved, as one while loop is interrupting the other and it actually does. The pedal does fade up the volume of the 2 separate send knobs as I intended:

    [​IMG]

    For more complex combos where multiple loops are absolutely unavoidable, the tcm.wait awaits :).

    Thanks for the info.

    Here´s my code, after edits:

    Code:
    on controller
    
        if (%CC[64] > 63)        { just needed for the while loop to stop if pedal is released, IE it stops the loop }
            $susPedalOn := 1    { ... and starts the deceasing vol. This is instead of using the "stop_wait" command, not in earlier versions }
    
            else
    
            $susPedalOn := 0
    
        end if
    
    
        if (%CC[64] > 63)
    
            while ($increasingVol < $maxVolumeSendLevel and $susPedalOn # 0)
                wait(2000)
    
                if ($fxPedalIRstrResonance_MuteButton = 1)
              
                    { send 4(3) - string resonance send fade IN }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1815,-1,7,$NI_BUS_OFFSET + 0) 
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 3)
    
                end if
    
                if ($fxIRBox_MuteButton = 1)
    
                    { send 4(3) - BOX resonance send fade IN }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1815,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 3)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1680,-1,7,$NI_BUS_OFFSET + 6)
    
                end if
    
            inc($increasingVol)
            end while
    
        end if
    
        if (%CC[64] < 64)
    
            while ($increasingVol > $minVolumeSendLevel and $susPedalOn # 1)
                wait(1000)
    
                if ($fxPedalIRstrResonance_MuteButton = 1)
    
                    { send 4(3) - string resonance send fade OUT }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_3,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 3)
              
                end if
    
                if ($fxIRBox_MuteButton = 1)
    
                    { send 4(3) - BOX resonance send fade OUT }
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 0)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 3)
                    set_engine_par($ENGINE_PAR_SENDLEVEL_0,$increasingVol*1800,-1,7,$NI_BUS_OFFSET + 6)
    
                end if
    
            dec($increasingVol)
            end while
    
        end if
    
      
        { sends stay on 0 if buttons are switched off. }
        if ($fxPedalIRstrResonance_MuteButton = 0)
    
          
            set_engine_par($ENGINE_PAR_SENDLEVEL_3,0,-1,7,$NI_BUS_OFFSET + 0)
            set_engine_par($ENGINE_PAR_SENDLEVEL_3,0,-1,7,$NI_BUS_OFFSET + 3)
    
    
        end if
    
        if ($fxIRBox_MuteButton = 0)
    
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 0) 
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 3)
            set_engine_par($ENGINE_PAR_SENDLEVEL_0,0,-1,7,$NI_BUS_OFFSET + 6)
    
        end if
    
    end on
    
    
     
  8. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
    The last thing you should do is probably just make sure that the pedal thing is executed only twice (pedal down vs pedal up), rather than just comparing if CC 64 is larger than 63 or not (that will trigger this thing for every intermediary level on a continuous sustain pedal!). So, start your CCB with something like this:

    Code:
    if sh_right(CC[64], 6) # pedal_state
        pedal_state := 1 - pedal_state
    end if

    Explanation: sh_right is bitwise right shift, which is the same as division by 2^N, N being the second argument of this function. 2^6 is 64, which is what we need to divide with. Bitwise operations are cheaper/faster to execute than divisions. So when this happens, just flip the value of pedal_state variable (0 = pedal up, 1 = pedal down). Now you can execute the rest of your code by querying the pedal_state variable, rather than the comparison that you did. You can also remove the and $susPedalOn # 0 part, it's not going to be necessary in this case, I don't think.

    Also don't do two ifs there. Do and if-else. Cleaner.

    Code:
    if pedal_state = 1
        ...
    else
        ...
    end if

    Do this if pedal_state thing within the bitshifting part (right after flipping the pedal_state value)! This will ensure that the following send level shenanigans will only be executed once every time the pedal state flips, rather than whenever CC64 is received.

    Also I'm pretty sure your code can be even more optimized by avoiding duplicating because of a simple increment vs decrement difference... Hint: you can use pedal_state as increment or decrement by doing something like counter := counter + (-1 + (2 * pedal_state)) so now when pedal is down (pedal_state is 1) it will increment, when pedal is up, it will decrement.


    And a question: why do you have different multiplication factors in pedal down vs pedal up case? In pedal up case you have 1800 everywhere, in pedal down you have 1615 in a few places. Curious.
     
    Last edited: Mar 16, 2019
    KrisY likes this.
  9. OP
    OP
    KrisY

    KrisY Noob in frenzy loop

    80
    5
    Mar 28, 2018
    Denmark
    Yes, it must look weird, and unnecessary. I wanted the fade-up to be slightly slower than the fade-down. Since this script fades up 2 separate send-knobs, it made sense to have different values for the two, going up. The difference will be adding to the realism, it sounds good. But down it will be affected by the IR sample that adds box sound and resonance, and that will cloud it. I might have to adjust these values more after some playing.

    Yes, absolutely, and the current code, using $susPedalOn #1 attempted to do that, but it will trigger anyway on the occasions when using a continuous pedal or programming from a DAW. The script should probably be adjusted to only answer to a more efficient "1" or "0". It doesn´t make sense to repeat it. Also, a simple way to restrict triggering here would be to use a variable with the latest value for CC64:

    Code:
    
    if (%CC[64] > 63 and $lastcc64value <= 63)
        $susPedalOn := 1
    else
        $susPedalOn := 0
    end if
    
    while ($increasingVol < $maxVolumeSendLevel and $susPedalOn = 1)
    
        do the hustle...
    
    end while
    
    while ($increasingVol > $minVolumeSendLevel and $susPedalOn = 0)
    
        do the reverse hustle...
     
    end while
    
    $lastcc64value := %CC[64]
    
    
    In regards to the if-statements, I´ll need to not use if-else, as the else has no meaning in my case. This example is not my full matrix of if:s. There are 3 if statements, for 3 different buttons being on or off, so the if:s need to be separate or they will interfere with each other.

    As for the Bitshift method, thanks for the tip and it seems to be able to do the thing efficiently, but I do not currently understand the method or what it is even. Lower cpu loads are always welcome though. I may have to revisit this, in which case I´ll be going over your message in more detail.
     
    Last edited: Mar 16, 2019
  10. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
  11. EvilDragon

    EvilDragon KSP Wizard

    5,793
    3,636
    May 25, 2010
    Croatia
    I meant the two ifs you did on CC[64], not the subsequent ones. You only need one if-else branch on CC 64 query (or if you go with my method, pedal_state variable, which you should just steal and run with it!)
     
    Last edited: Mar 16, 2019
    KrisY likes this.

Share This Page