1. IMPORTANT:
    We launched a new online community and this space is now closed. This community will be available as a read-only resources until further notice.
    JOIN US HERE

HOW TO: MODULATION IN KONTAKT VIA KSP

Discussion in 'Scripting Workshop' started by EvilDragon, Jan 6, 2016.

  1. Reid115

    Reid115 NI Product Owner

    Messages:
    40
    Is there no way to have a per-voice constant modulator? For example, if you make a "random bipolar" modulator that modulates a filter cutoff knob, every new note will have a different cutoff value. When a new note is played, it leaves the cutoff value for the previous voices untouched, and only assigns the new value to the new note. This is what I want, but a constant. The "constant" modulator isn't per-voice, because the constant must be set with the intensity slider, thus affecting all voices. The knob can't directly be set either, because again, this affects all voices. The only open-ended per-voice modulator is an envelope. My idea was to make an AHDSR envelope, set Attack, Hold, and Decay to 0, and use the sustain knob as the per-voice constant. The problem is that there's no infinite release -- it caps off at 25 seconds (even if you try to push it higher with the INTMOD trick). So when the note is released, the constant will start to decay. It may not be noticeable if the note's volume envelope release is far shorter than 25 seconds, but it's not a real solution.
     
  2. medusa

    medusa NI Product Owner

    Messages:
    239
    "from script" modulator, in 6.6.0 and later
     
  3. Reid115

    Reid115 NI Product Owner

    Messages:
    40
    Wow.... thanks.
     
  4. Reid115

    Reid115 NI Product Owner

    Messages:
    40
    So "from script" is what I want but it behaves a little weird for knobs that scale non-linearly. When I use set_event_par_arr() to send a value of -1000k/1000k to a centered pan knob, the result is 100%L/100%R, as expected. But when I send 1000k to the volume envelope attack knob, it behaves like I sent -1000k (only decreases the attack). Clicking invert changes nothing. It only increases the attack value if I send -1000k and invert it. This makes it impossible to do per-voice bipolar modulation -- if I have to keep toggling the invert button, it will affect all voices. I also have the issue of needing to undo the attack knob scaling. If I send an inverted -1000k with the attack knob set half-way (~180 ms), it will modulate all the way to the right (15.0k ms); if the attack knob is set all the way left (0 ms), it barely moves. I want the value I send to basically be the raw knob value -- 0-1000000 or whatever, 500k being the middle. Thoughts?
     
  5. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    Hmmmm over here if I send 0-1000000 to a from script modulator which modulates envelope attack time, it seems to work as a CC modulator. Meaning, 0% gives you 0 ms, 100% gives you whatever you have set the Attack knob to.
     
  6. medusa

    medusa NI Product Owner

    Messages:
    239
    Envelope times have always behaved a little strange when responding to a CC or modulator. If it's INVERT, it subtracts from the knob time, which is often what you want say with Velocity->Attack. If you set it positive, (not INVERT), it modulates from nothing UP TO the knob time, which is different. There's no way to get the modulator to ADD TO the time.
     
  7. Reid115

    Reid115 NI Product Owner

    Messages:
    40
    Got it working now. Basically instead of setting the knob value with set_engine_par() and the mod value separately, I manually set the knob to the desired max value (5000 ms in my case), and I calculate both knob value and mod value together with one call to set_event_par_arr(). This introduced the problem of no longer being able to read the display value, so I created an empty group just to set and read from that knob. Here's the relavent code:

    Code:
    on init
        { ... }
     
        declare ui_knob $attack_knob (0, 10000, 1)
        make_persistent($attack_knob)
        set_control_par(get_ui_id($attack_knob), $CONTROL_PAR_PARENT_PANEL, get_ui_id($grain_panel_row_2))
        move_control_px($attack_knob, 0, 0)
        set_text($attack_knob, "Attack")
        set_knob_unit($attack_knob, $KNOB_UNIT_MS)
        declare $attack
        declare polyphonic $attack_result
    end on
    
    function attack_changed
        $attack := $attack_knob * 100
        { 877000 = 5k ms }
        set_engine_par($ENGINE_PAR_ATTACK, $attack * 877 / 1000, 3, find_mod(3, "EMPTY_ADSR"), -1)
        set_knob_label($attack_knob, get_engine_par_disp($ENGINE_PAR_ATTACK, 3, find_mod(3, "EMPTY_ADSR"), -1))
    end function
    on ui_control ($attack_knob)
        call attack_changed
    end on
    
    on note
        ignore_event($EVENT_ID)
     
        { ... }
     
        { WHATEVER MODULATION YOU WANT }
        $attack_result := $attack
        if ($attack_grain_edit # 0) { ~attack_grain set by ui_value_edit, 0-100 }
            select ($attack_grain_polarity)
                case 0 { bipolar }
                    $attack_result := $attack_result + real_to_int(int_to_real(random(-5000, 5000)) * ~attack_grain)
                case 1 { unipolar + }
                    $attack_result := $attack_result + real_to_int(int_to_real(random(0, 10000)) * ~attack_grain)
                case 2 { unipolar - }
                    $attack_result := $attack_result + real_to_int(int_to_real(random(-10000, 0)) * ~attack_grain)
            end select
        end if
     
        { PLAY NOTE }
        $new_id := play_note($new_note, $EVENT_VELOCITY, $pos_result, $size_result)
        if ($sample_mode = 0)
            dont_use_machine_mode($new_id)
        end if
        change_vol($new_id, get_event_par($EVENT_ID, $EVENT_PAR_VOLUME), 1)
        change_tune($new_id, get_event_par($EVENT_ID, $EVENT_PAR_TUNE), 1)
        change_pan($new_id, get_event_par($EVENT_ID, $EVENT_PAR_PAN), 1)
        set_event_mark($new_id, $this_mark)
        set_event_par($new_id, $EVENT_PAR_0, $this_mark)
    
        set_event_par_arr($new_id, $EVENT_PAR_MOD_VALUE_ID, $attack_result, 6) { attack }
    end on
    
    on persistence_changed
        { ... }
     
        call attack_changed
    end on
     
    Last edited: Nov 19, 2021
  8. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    That would work if the scaling of how from script modulator was linear, but I'm not sure if it is.
     
  9. Reid115

    Reid115 NI Product Owner

    Messages:
    40
    Which part are you referring to? If you're talking about ~attack_grain, that's set by a ui_value_edit -- the "from script" mod intensity slider is always set to max. Edited for clarity.