Why isn't sin() function working in KSP?

realdealpeel
realdealpeel Member Posts: 23 Member
edited October 2024 in Scripting Workshop

I have $v := (sin(($v/10)-8)+1)/2in the script below. But the sin(x) function isn't working despite sin(x) being in the KSP manual. In fact, none of the trigonometric functions appear to be working, at least in a note on without some special activating code or something NOT described in the KSP manual.

on init
   set_script_title("Humanize Timing & Velocity")

   declare ui_knob $Timing (0,100,1)
   set_knob_unit ($Timing, $KNOB_UNIT_PERCENT)
   set_text ($Timing,"Note On")
   $Timing := 0
   make_persistent ($Timing)
   move_control ($Timing,3,2)
   declare $new_event

   declare ui_knob $v (0,100,1) 
   set_knob_unit ($v, $KNOB_UNIT_PERCENT)
   set_text ($v,"Velocity")
   $v := 0
   make_persistent ($v)
   move_control ($v,4,2)
end on

on note
   ignore_event($EVENT_ID)
   wait(random(0, $Timing * 1000))
   $new_event := play_note($EVENT_NOTE, $EVENT_VELOCITY, 0, -1)

   if($EVENT_VELOCITY > 1)
      $v := $EVENT_VELOCITY + (random(-$v,$v))
      if ($v >= 96)
         $v := (sin(($v/10)-8)+1)/2
      end if
      change_velo($new_event, $v)
   end if
end on

Best Answers

Answers

  • realdealpeel
    realdealpeel Member Posts: 23 Member

    I have not been able to get ANY of the advanced functions (sin, cosine, power, exponents, sqrt etc) and I have no idea why. Went with a different approach and settled on linear equations. At velocities below 32, the "eccentricity" of the randomness added to the velocity linearly decreases, and same thing for 96 and up. This makes writing for low dynamics more realistic, and makes writing for high dynamics more predictable.

    I don't know if posting this is even allowed, but this is actually an edited version of the Humanize script that comes with Kontakt. The only problem is the stock script is flawed. If more than one note is played at the same time, the velocity randomness is applied to all notes equally. This means that if you have different dynamics in each hand of a marimba for example, they will all be stuck to one dynamic. That's fixed with this.

    The other functions are omitted (pan, volume, tune) since they're not useful for percussion stationary acoustic percussion.

    I'm not a programmer by any means so use at your own risk.

    on init
       set_script_title("Humanize Timing & Velocity")
    
       declare ui_knob $Timing (0,100,1)
       set_knob_unit ($Timing, $KNOB_UNIT_PERCENT)
       set_text ($Timing,"Note On")
       $Timing := 0
       make_persistent ($Timing)
       move_control ($Timing,3,2)
       declare $new_event
    
       declare ui_knob $e (0,100,1) {velocity eccentricity}
       set_knob_unit ($e, $KNOB_UNIT_PERCENT)
       set_text ($e,"V Eccen.")
       $e := 0
       make_persistent ($e)
       move_control ($e,4,2)
       declare $v
       declare $m {-minimum, maximum}
    end on
    
    on note
       ignore_event($EVENT_ID)
       wait(random(0, $Timing * 1000))
       $new_event := play_note($EVENT_NOTE, $EVENT_VELOCITY, 0, -1)
    
       $v := $EVENT_VELOCITY
       $m := 127
       if($v <= 32)
          $m := 127 / 31 * $v - 127 / 31
       end if
       if($v >= 96)
          $m := 127 / -31 * $v + 127 * 127 / 31
       end if
       change_velo($new_event, $v + random(-$m, $m) * $e / 200)
    end on
    
  • EvilDragon
    EvilDragon Moderator Posts: 1,031 mod

    These functions only work with real variables (so, those that start with ~ identifier, not those that start with $).

  • realdealpeel
    realdealpeel Member Posts: 23 Member

    Thanks for your response, EvilDragon. I did try this and still getting the "expression expected" error.

  • EvilDragon
    EvilDragon Moderator Posts: 1,031 mod
    edited January 2024 Answer ✓

    Please post the code. You cannot mix floating point and integer variables in one statement, you have to use the casting operators (real() and int()) as needed.

  • realdealpeel
    realdealpeel Member Posts: 23 Member

    This got me there! The script below is non-working because I just tested your advice and will incorporate it into a working script later. But no error finally! The only thing that worked however for me was real_to_int(sin(~z)) 

    real(sin(~z)) and int(sin(~z))still produced the expression expected error. I'm on K6, is this perhaps a K7+ thing?

    Is there any plan in the cue to make KSP more flexible, like how javascript can be? I don't understand practically why integers and real numbers cannot be mixed without "assistance" in KSP when they can be all other languages I've encountered. This is just one example.

    Another would be, why do variables need to be declared at all, and especially in the on init? Why can't they just be defined where needed and the definition acts as the declaration?

    Thanks again, EvilDragon!

    on init
       set_script_title("Humanize Timing & Velocity")
       declare ui_knob $t {timing} (0,100,1)
       set_knob_unit ($t, $KNOB_UNIT_PERCENT)
       set_text ($t,"Note On")
       $t := 0
       make_persistent ($t)
       move_control ($t,3,2)
       declare $n {new event}
       declare ui_knob $e (0,100,1) {velocity eccentricity}
       set_knob_unit ($e, $KNOB_UNIT_PERCENT)
       set_text ($e,"V Eccen.")
       $e := 0
       make_persistent ($e)
       move_control ($e,4,2)
       declare $v
       declare $m := 127 {-minimum, maximum}
       declare ~z
    end on
    
    on note
       ignore_event($EVENT_ID)
       wait(random(0, $t * 1000))
       $n := play_note($EVENT_NOTE, $v, 0, -1)
       $v := $EVENT_VELOCITY
       if($v < 32)
          $m := 127 / 31 * $v - 127 / 31
       end if
       if($v > 96)
          $m := {127 / -31 * $v + 127 * 127 / 31} real_to_int(sin(~z))
       end if
       change_velo($n, $v + random(-$m, $m) * $e / 200)
    end on
    
  • EvilDragon
    EvilDragon Moderator Posts: 1,031 mod
    edited January 2024

    KSP is never going to be like JavaScript, sorry to say. It is a realtime executed language and it has to react fast and with a hard deadline to comply with the audio buffer (it's ran in the realtime audio thread), hence why you need to declare variables in init (which basically means: when script is parsed, in order to preallocate enough memory to be used in advance).


    BTW note that if you just convert sin(x) to integer, you will just get 0 or 1. You need to scale the result up to the range you need, before casting it back to integer.

  • realdealpeel
    realdealpeel Member Posts: 23 Member
    Answer ✓

    All makes sense. Thanks once again. Take care of yourself.

This discussion has been closed.
Back To Top