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. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    I see people are still struggling with this, after all this time. So I thought I could explain this to everyone once and for all, since it's quite an important thing when doing a custom scripted instrument.

    First, let's break things down. Kontakt has two types of modulators - internal and external. Internal are: LFO, envelope, glide, step modulator, envelope follower. External are: pitch bend, aftertouch, MIDI CC, constant, random unipolar/bipolar, etc.

    Next, internal modulators have two parts: the modulator itself (represented by its module in the Modulation section of Kontakt's instrument edit view), and the modulator target strip (found at the destination - source pitch, filter cutoff, amplifier volume, etc.). External modulators only have the modulator target strip.

    Now, how do we KSP this all? This is where KSP offers two commands: find_mod() and find_target(). First one targets either internal modulators or external modulator target strips. Second one targets only (and nothing else but) internal modulator target strips. These commands work by searching for a named reference, the name of a modulator/target strip. Kontakt assigns default names to these, but I find them completely useless, so I heartily recommend everyone to do their own naming.

    Here's my suggestion for a clear-cut modulation naming scheme:

    * use all caps
    * name internal mods either by their purpose (PITCH LFO, FILTER ENV), or number them (LFO 1, LFO 2, ENV 1, ENV 2). I tend to go with the latter.
    * name internal mod target strips in such a way that you include the modulator name and an arrow pointing to the target (LFO 1 -> PITCH, ENV 2 -> CUTOFF 1 (more on why I used 1 here later))
    * name external mods like internal mod target strips (PB -> PITCH, AT -> VOLUME, RANDOM -> STARTPOINT...)

    That should be clear enough for everyone, I think. If you have more than one internal modulator of the same type (say, multi LFO), Kontakt does NOT auto-number them incrementally unfortunately, and this can be a source of a lot of confusion. So make sure you rename them immediately upon instantiating them, and it should all be clearer.

    But, how to rename modulators, or see their names in the first place? For this, you have to go to Script Editor, and press the Edit button there to open the text input area of the Script Editor. Now you can see the names of modulators and target strips when you right-click them. You don't have to have the Script Editor open at all times - but you have to have the text input area open. So after opening the text input area, close the Script Editor to give yourself a better overview of the instrument. I also recommend closing the Wave and Mapping Editors, as well as Group Editor, too (use Monitor->Groups tab in Kontakt's left-side browser instead of Group Editor, it's more spacious anyways).

    IMPORTANT: In Kontakt 4, you could only rename modulators within one group - the renaming operation didn't pass through other editable groups (for example, when Edit All Groups is enabled), so you had to rename every modulator in every group manually (or do one group, then duplicate it - which is what I tend to do anyways, since batch-renaming things can sometimes lead to unexpected results if your modulators were added at different times and in different order, etc.). In Kontakt 5, when you have more than one group selected for editing, the renaming operation WILL be passed through all those selected groups. There are some situations that are very hard to explain in layman's terms when this doesn't happen, but it's mostly related to the above mentioned unexpected results. When you notice this situation, I recommend duplicating one of the existing groups with fully-named modulators, then pasting samples back into it.

    Also, I read somewhere that people notice missing modulators after they've added them, etc. This happens when you select a modulator (it gets a yellow frame around it), then type in the Script Editor, and at some point you press the Delete key on your keyboard. Kontakt wrongly assigns keyboard focus to BOTH the Script Editor AND the instrument edit view - so you get both your character from the script deleted, AND the modulator! So be careful!!!

    Let's notice one more thing regarding Kontakt 5 here. When you right-click the modulator or its target strip, you will see some numbers there (group, slot, idx). This is essentially what find_mod() and find_target() will return when used, these are the numbers that you put in set_engine_par() or get_engine_par(). So if you feel like you don't want to be bothering with this all, you can use the numbers, too. But I find that this really affects script readability in a bad way, so I always use the naming scheme. Then everything makes a lot more sense.

    Before continuing onward, let me explain my naming scheme above for the case where I used "CUTOFF 1" in the modulator target name. In Kontakt, you can have up to 16 internal modulators per group. Each of those modulators can target up to 16 destinations. So let's say you have several filters loaded in Group FX, and you want one single LFO to modulate the filter cutoff in all of them. For find_mod() and find_target() to work we need to have UNIQUE names for EVERYTHING within a single group! This is why I added a number there. In the above situation, Group FX slot 1 filter cutoff would be called CUTOFF 1, slot 2 would be called CUTOFF 2, and so on. So we would have modulation target strips named like so:

    LFO 1 -> CUTOFF 1
    LFO 1 -> CUTOFF 2
    LFO 1 -> CUTOFF 3
    LFO 1 -> CUTOFF 4
    etc.

    This ensures unique naming and no find_mod() errors, provided you didn't do a typo of a modulator in the script, or something :) Note that we need this naming ONLY when there's a multiple of the SAME modulation links across multiple Group FX slots. So, if we have 4 filters or 4 EQs and we want to modulate the same parameter in all of them with just one modulator, that is the case when we use this incremental naming scheme. If we have an EQ in one slot, a filter in another, a Skreamer in yet another, and we have ONE modulator targetting a DIFFERENT parameter in all of them, we don't need to do this (since you would name the modulator targets differently, for example: LFO 1 -> CUTOFF, LFO 1 -> EQ GAIN2, LFO 1 -> SKR TONE...)

    Let's put all this to good use now. Some examples:

    1. CHANGING THE LFO FREQUENCY

    Let's say our LFO is named "LFO 1" and we want to change its frequency. Let's say it's found in group 2, and that our ui_knob/slider is called $LFOFreq. Here's what we do:

    Code:
    set_engine_par($ENGINE_PAR_INTMOD_FREQUENCY,$LFOFreq,1,find_mod(1,"LFO 1"),-1)
    That's all there's to it! Same code is used for other LFO parameters, and all envelope parameters in much the same way. $ENGINE_PAR_INTMOD_FREQUENCY applies to LFOs and step modulators.

    2. CHANGING THE ENVELOPE MODULATION AMOUNT

    Let's say we have an envelope modulating pitch in group 4. Our envelope is called "ENV 2" and our mod target strip is called, naturally, "ENV 2 -> PITCH" (because you're following my naming guidelines, aren't you? :)). Our ui_knob/slider is called $PitchEnv. We can deal with this in several ways, one of which is needlessly more complicated than others. Let's see...

    * UNIPOLAR MODULATION AMOUNT

    Code:
    set_engine_par($ENGINE_PAR_MOD_TARGET_INTENSITY,$PitchEnv,3,find_mod(3,"ENV 2"),find_target(3,find_mod(3,"ENV 2"),"ENV 2 -> PITCH"))
    This will target ONLY the modulation amount slider, which goes from 0 to 100%. Which means unipolar (positive) modulation happens. Notice how the code is structured: first we're telling which engine parameter we want to change, then we tell by what amount, then we point to the group we want to modify, then we tell which modulator we're pointing, and finally which modulator target strip we want to change (we repeat find_mod() here because it's important for KSP to know the modulator to which the target strip is attached to). The range of our ui_knob/slider is 0 to 1000000.

    * BIPOLAR MODULATION AMOUNT

    This is the needlessly more complicated way: using the unipolar mod amount code and then targetting the Invert button with a separate engine parameter call. The range of our ui_knob/slider in this case is -1000000 to 1000000.

    Code:
    set_engine_par($ENGINE_PAR_MOD_TARGET_INTENSITY,abs($PitchEnv),3,find_mod(34,"ENV 2"),find_target(3,find_mod(3,"ENV 2"),"ENV 2 -> PITCH"))
    if ($PitchEnv < 0)
        set_engine_par($MOD_TARGET_INVERT_SOURCE,1,3,find_mod(3,"ENV 2"),find_target(3,find_mod(3,"ENV 2"),"ENV 2 -> PITCH"))
    else
        set_engine_par($MOD_TARGET_INVERT_SOURCE,0,3,find_mod(3,"ENV 2"),find_target(3,find_mod(3,"ENV 2"),"ENV 2 -> PITCH"))
    end if
    See? This is needlessly complicated. Thankfully there's another engine parameter that handles this all for itself. For whatever reason it's not documented, but I think everyone should know about it, since it offers one cool feature many people don't know about. This engine parameter is called $ENGINE_PAR_INTMOD_INTENSITY. Its range is 0-1000000, and this covers the ENTIRE bipolar range of the modulation amount slider, which means 0% is at 500000, 100% is at 1000000 and -100% is at 0. So, our code for bipolar modulation amount slider becomes this:

    Code:
    set_engine_par($ENGINE_PAR_INTMOD_INTENSITY,$PitchEnv,3,find_mod(3,"ENV 2"),find_target(3,find_mod(3,"ENV 2"),"ENV 2 -> PITCH"))
    Our $PitchEnv range for this example is then, of course, 0 to 1000000.

    But... that's not all! It seems that NI didn't build in any range checking for this engine parameter. Which means, we can go beyond the range of -100%~100%! This is especially important for pitch modulation, because sometimes we want to have a stronger modulation that goes beyond 12 semitones range that Kontakt allows at 100% modulation amount. So, just continue with the values, expanding the range. It follows a sort of exponential curve, so engine parameter of 2000000 is not 24 semitones, it's actually 324 semitones! So you don't want to go that high. Here's a table with some useful values:

    -12 to 12 semitones -> 0 to 1000000
    -24 to 24 semitones -> -130000 to 1130000
    -36 to 36 semitones -> -221000 to 1221000
    -48 to 48 semitones -> -293500 to 1293500

    I doubt you'll need more than this. Also note that extreme pitch modulation can sometimes crash Kontakt, since this is not only an undocumented feature, but probably actually an unintentional bug on NI side. So it MIGHT be fixed at some point... but somehow I think this "exploit" is here for a reason. So there you go - this is how to extend modulation range for pitch modulations! This might or might not work for other engine parameters. Explore!

    3. EXTERNAL MODULATORS

    This is as simple as it gets. We can use either unipolar or bipolar modulation amount examples from above, except we do not need to use find_target() at all! Just write -1 instead. Let's say we have aftertouch mapped to modulate LFO 1 frequency in group 10.

    Code:
    set_engine_par($ENGINE_PAR_INTMOD_INTENSITY,$ATVolume,9,find_mod(9,"AT -> LFO 1 FREQ"),-1)
    That's all there's to it!


    I think there's one more thing I'd like to say here, and one thing all KSPers should know. When find_mod() doesn't find a modulator with designated name, it actually returns a value of 0 instead of -1! This is actually a bug on NI side, that I don't know why isn't fixed yet. How does this manifest? Well, it manifests in such a way that it will CHANGE the value of the modulator whose slot ID is 0 REGARDLESS! This is usually amplifier envelope which is assigned by default by Kontakt. Usually it sets the modulation amount of it to 0%, which makes the instrument behave in a very weird way (envelopes don't work and notes are cut short). So, if your instrument starts behaving weirdly after a wrongly targetted find_mod(), you know what to look for!

    ________________


    I hope this has been helpful. I've probably missed some things I wanted to mention, but that's why this is a forum and this is a thread where you can leave your questions and I'll answer from time to time.


    Cheers!
     
    Last edited: Dec 13, 2018
    • Like Like x 8
    • Informative Informative x 3
  2. gwhizoflc

    gwhizoflc New Member

    Messages:
    20
    ED,

    Wow Great post!!! Sticky +1 !

    For me, we could really use definitive terms and a picture when explaining the two parts of internal modulators, but in your post:

    Internal modulators have two parts: the modulator itself (represented by its module in the Modulation section of Kontakt's instrument edit view), and the modulator target strip (found at the destination - source pitch, filter cutoff, amplifier volume, etc.). External modulators only have the modulator target strip.
    So to pick terms and stick with them, "Mod target strips" are the strips under the "Mod tab" in the Source section of the Group Editor? So the "modulator itself" are the "Modulation rack module" that appears in the lower section labelled "Modulation" ?

    And to confirm, find_mod() can only work on "Modulation rack modules", while find_target() can only work on "Mod target strips" in the Group Editor area.

    Also to clarify, we can rename an entire Mod target strip or Modulation rack module by right-clicking within the strip or module away from a control... and we cannot rename individual controls within them. That is because each control is addressed by an ENGINE_PAR_ constant, not by its name.

    On page 210 in the KSP Reference we have the Modulation Engine Parameters (they are called variables in the manual, but they are constants yes?)

    It's not always obvious which ENGINE_PAR to use for which control within a Mod target strip or a Modulation rack module. The first three entries:

    $ENGINE_PAR_MOD_TARGET_INTENSITY
    the intensity slider of a modulation assignment, controls the modulation amount ​
    Q: Applies to the Mod target strip slider only, so we need to use find_target() to get/set it?

    $MOD_TARGET_INVERT_SOURCE
    the Invert button of a modulation assignment, inverts the modulation amount ​
    Q: Applies to the Mod target strip "Invert button" only, so we need to use find_target() to get/set it?
    Setting to 1 is inverted, 0 is normal

    $ENGINE_PAR_INTMOD_BYPASS
    the bypass button of an internal modulator (e.g. AHDSR envelope, LFO) ​
    Q: Applies to the Modulation rack module only, so we need to use find_mod() to get/set it?

    And for LFOs:

    $ENGINE_PAR_INTMOD_FREQUENCY ​
    Q: Applies to the Modulation rack module "Freq" knob, so we need to use find_mod() to get/set it?

    $ENGINE_PAR_INTMOD_FREQUENCY_UNIT ​
    Q: What are the options here for setting units? Does this mean the knob then works by those units, or is it for display only?
    Applies to the Modulation rack module "Freq" knob, so we need to use find_mod() to get/set it?

    $ENGINE_PAR_LFO_DELAY ​
    Q: Applies to the Modulation rack module "Fade in" knob, so we need to use find_mod() to get/set it?

    $ENGINE_PAR_LFO_DELAY_UNIT ​
    Q: What are the options here for setting units? Does this mean the knob then works by those units, or is it for display only?
    Applies to the Modulation rack module "Fade in" knob, so we need to use find_mod() to get/set it?

    THANK YOU for explaining the bug about disappearing Mod tab strips. It also manifests as finding a second Modulator suddenly.
    Q: How to "unselect" the Mod target strip or Modulation rack module, so we can type freely in the Script Editor?
     
  3. dmbaer

    dmbaer New Member

    Messages:
    11
    Wow! When does the book come out? :D
     
  4. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    Not Group Editor. You want to say "instrument edit mode". Group Editor doesn't need to be shown at all to see these. Yes, these are Mod tabs you can see, but not just in Source module - you can see it in Group FX and Amplifier module, too.

    As mentioned in the original post, yes.

    As mentioned at the very beginning, find_mod() works both on external mods (when you do not need to use find_target()!) and on internal mods (where you have to use find_target() if you want to change modulation amount, but not one of parameters of the internal modulator itself!).

    In case of internal modulator, yes. In case of external modulator, no. Same thing for $MOD_TARGET_INVERT_SOURCE (but you don't need to use $MOD_TARGET_INVERT_SOURCE at all if you follow the simpler example in #2 bipolar modulation)

    Yes.

    Yes.

    Regarding units, see page 196, Tempo Unit Variables. It's all there.

    Just click the modulator again so the frame disappears.
     
    Last edited: May 28, 2020
  5. gwhizoflc

    gwhizoflc New Member

    Messages:
    20
    ED!

    You are helping many people who come to this fresh and have only the Ref Manual and Google to help them.
    Without the Group Editor up, we don't know which group the Mod target strips are referring to though? And because the Group InsertFX looks to appear in the same UI "tray" and the same color as the Group Editor, surrounding the Mod target strips, they all seem to be of one unit/organization.

    Well, we are saying the same thing in different ways? Anything that appears in the Modulation rack modules areas will work with find_mod() (regardless if they are internal or external) Anything that appears in the Mod target strips needs to be addressed using find_target().
    Changing "modulation amount" is for me a confusing term, as we don't have anything in KSP with those words. The mouseover of the Mod target strip slider says Modulation Intensity. That is also the term used for the ENGINE_PAR constant. If we want to affect the Modulation Intensity slider in the Mod target strips, we use find_target()

    For these two Engine Parameters:
    $ENGINE_PAR_LFO_DELAY
    $ENGINE_PAR_LFO_DELAY_UNIT

    Are they used to address the LAG value in the Mod target strips, or the Fade In knob of the Modulation rack module?

    Thanks for your patience and help!
     
  6. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    That's why Kontakt has a browser on the left side. That's why that browser has Monitor tab up top. And that tab has a Groups sub-tab which is essentially the same thing. I mentioned it in the first post, too.

    Wrong. External modulators DO NOT need to use find_target() even if they are found in the Mod tabs ABOVE (Source, Group FX, Amplifier).

    Amount=intensity. Basically synonyms.

    ONLY in case of internal mods, NOT external mods. Please don't let me repeat myself again. It's all written as clearly as I could. :)

    The latter. There's no way to adjust lag via KSP.
     
  7. gwhizoflc

    gwhizoflc New Member

    Messages:
    20
    ED!

    OK! Sorry for the thick skull over here. Now the light is penetrating it.

    Just looking at the Mod tabs, and seeing an LFO Mod target strip next to a Pitch Bend Mod target strip, both with the same Invert button and Modulation Intensity sliders, and both in the same area of the UI, it is hard to "get it" that we have to use find_target to reach the LFO, and find_mod() to reach the pitch bend.

    It makes using the term Mod target strip confusing, since we don't use find_target for many things that appear in the area we call target strip.

    Last confusion.
    In the manual on pg 150 for set_engine_par (and find_target hint):

    It sounds like, for LFO modulators, which are internal modulators, the last argument in our example should be the results of find_target, not -1?
    But in this example, find_target(group, mod-idx, target-name) is confusing. First, it talks about modulation slider. Does that mean the controls in general, or specifically the Modulation Intensity slider?

    To find the mod-idx of the internal Mod target strip where the slider appears, we are supposed to use find_target itself, because this is an internal modulator? And then what do we use in target-name as the name for the slider control? Usually we address the controls with $ENGING_PAR.... not a name.
     
  8. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    It talks about the mod intensity slider, of course.

    This was all stated in the initial post. Please read it once again. You use the mod target name (see my suggested naming scheme) in find_target to find it, you use engine parameter to tell KSP what exactly to change (in this case, modulation intensity).
     
  9. Will VDC

    Will VDC NI Product Owner

    Messages:
    57
    Hey ED,

    Great post!


    -I--like you--renamed my modulator 'LFO 1.' When renaming, should the name still appear as it did by default, in this case 'LFO (rectangle)'?

    Screen Shot 2016-01-25 at 10.24.47 AM.png

    I'm also still having difficulty getting a custom knob on my user interface to sync with my LFO. Script comes back without errors, but the knob doesn't affect the parameter within the engine. Make sense?

    Code:
    
    on init
        message ("")
        make_perfview
        set_script_title("Kontakt Skin")
        set_control_par_str($INST_WALLPAPER_ID,$CONTROL_PAR_PICTURE,"skin")
        set_ui_height_px(380)
    
    {Pulse/LFO Knobs}
    {Note/Value Knob}
        { create the control - must be a slider }
        declare ui_slider $note(0,1000000)
        make_persistent($note)
        { hide the slider parts }
        hide_part($note,  $HIDE_PART_BG .or. $HIDE_PART_MOD_LIGHT .or. $HIDE_PART_TITLE .or. $HIDE_PART_VALUE)
        { assign the image file }
        set_control_par_str(get_ui_id($note),  $CONTROL_PAR_PICTURE, "sourceknob_1")
        { place it on the performance view }
        move_control_px($note, 52, 290)
        { control how mouse movements should affect the control }
        set_control_par(get_ui_id($note), $CONTROL_PAR_MOUSE_BEHAVIOUR, -500)
    
    {Connect Pulse / LFO Knobs}
    on ui_control ($note)
        set_engine_par($ENGINE_PAR_INTMOD_FREQUENCY,$note,1,find_mod(1,"LFO 1"),-1)
     
    end on
    
    Thanks!

    WVDC
     
  10. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    The name appears only when you right-click the modulation strip. The text on the modulation strip itself is fixed and doesn't change.


    You're creating a ui_slider. There is no need to use hide_part() - that's just for ui_knobs.


    As for tempo syncing, you need to first set $ENGINE_PAR_INTMOD_FREQUENCY_UNIT, then $ENGINE_PAR_INTMOD_FREQUENCY.
     
  11. Will VDC

    Will VDC NI Product Owner

    Messages:
    57
    Ah! Copy! Thanks, ED.

    Would I set the unit of the internal mod in the initial callback or after the fact when I connect it to the ui_slider?

    Also, what would be an appropriate unit?
     
  12. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    In the UICB. For unit values, check KSP reference, they're all there.
     
  13. Will VDC

    Will VDC NI Product Owner

    Messages:
    57
    Gotcha. Thanks! You're such a help, ED.

    Will I have to do anything special or tricky to get note values/durations (1/4, 1/8, etc.) to show up instead of the frequency (Hz) values?
     
  14. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    Remember that all real-world displayed values are all in 0-1000000 range in KSP. That should sort it out for you.
     
  15. Will VDC

    Will VDC NI Product Owner

    Messages:
    57
    So I take it that it's really only the display value that will need to change?

    Tried again, but to no avail...know I'm missing a step in here, but can't figure where.

    Code:
    on init
        message ("")
        make_perfview
        set_script_title("Kontakt Skin")
        set_control_par_str($INST_WALLPAPER_ID,$CONTROL_PAR_PICTURE,"skin")
        set_ui_height_px(380)
    
    {Pulse/LFO Knobs}
    {Note Knob}
        { create the control - must be a slider }
        declare ui_slider $note(0,1000000)
        make_persistent($note)
        { hide the slider parts }
        hide_part($note,  $HIDE_PART_BG .or. $HIDE_PART_MOD_LIGHT .or. $HIDE_PART_TITLE .or. $HIDE_PART_VALUE)
        { assign the image file }
        set_control_par_str(get_ui_id($note),  $CONTROL_PAR_PICTURE, "sourceknob_1")
        { place it on the performance view }
        move_control_px($note, 52, 290)
        { control how mouse movements should affect the control }
        set_control_par(get_ui_id($note), $CONTROL_PAR_MOUSE_BEHAVIOUR, -500)
    
    end on
    
    on ui_control ($note)
        set_engine_par($ENGINE_PAR_INTMOD_FREQUENCY_UNIT,$note,1,find_mod(1,"LFO 1"),-1)
        set_engine_par($ENGINE_PAR_INTMOD_FREQUENCY,$note,1,find_mod(1,"LFO 1"),-1)
    end on
    
     
  16. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    You are not supposed to use $note for $ENGINE_PAR_INTMOD_FREQUENCY_UNIT - there are constants you need to use with $ENGINE_PAR_INTMOD_FREQUENCY_UNIT, and they are listed in the manual.
     
  17. Will VDC

    Will VDC NI Product Owner

    Messages:
    57
    Got it!

    Code:
      
    on init
      message("Asterious, Copyright 2016 by DayTone Sound and Instruments")
      make_perfview
      set_script_title("Kontakt Skin")
      set_control_par_str($INST_WALLPAPER_ID,$CONTROL_PAR_PICTURE,"skin")
      set_ui_height_px(380)
      declare $i
    declare !note_values[11]
      !note_values[0] := "1/64T"
      !note_values[1] := "1/32T"
      !note_values[2] := "1/32"
      !note_values[3] := "1/16T"
      !note_values[4] := "1/16"
      !note_values[5] := "1/8T"
      !note_values[6] := "1/16D"
      !note_values[7] := "1/8"
      !note_values[8] := "1/4T"
      !note_values[9] := "1/8D"
      !note_values[10] := "1/4"
    
    make_persistent($note)
      hide_part($note,$HIDE_PART_BG .or. $HIDE_PART_MOD_LIGHT .or. $HIDE_PART_TITLE .or. $HIDE_PART_VALUE)
      set_control_par_str(get_ui_id($note),$CONTROL_PAR_PICTURE,"sourceknob_1")
      move_control_px($note,76,290)
      set_control_par(get_ui_id($note),$CONTROL_PAR_MOUSE_BEHAVIOUR,-500)
    end on
    
     declare ui_label $lbl_note(1, 1) 
      move_control_px($lbl_note,40,327)
      set_control_par_str(get_ui_id($lbl_note),$CONTROL_PAR_TEXT,"")
      set_control_par(get_ui_id($lbl_note),$CONTROL_PAR_HIDE,$HIDE_PART_BG)
      set_control_par_str(get_ui_id($lbl_note),$CONTROL_PAR_PICTURE,"")
      set_control_par(get_ui_id($lbl_note),$CONTROL_PAR_WIDTH,50)
      set_control_par(get_ui_id($lbl_note),$CONTROL_PAR_HEIGHT,50)
      set_control_par(get_ui_id($lbl_note),$CONTROL_PAR_FONT_TYPE,1)
      declare $_old_range
      declare $_new_range
      $_old_range := 1000000-0
      if ($_old_range=0)
        $i := 11
      else
        $_new_range := 0-11
        $i := ($note-0)*$_new_range/$_old_range+11
      end if
      set_control_par_str(get_ui_id($lbl_note),$CONTROL_PAR_TEXT,!note_values[$i])
    end on
    
     
  18. gwhizoflc

    gwhizoflc New Member

    Messages:
    20
    I tried 1221000, it seemed to be for -24 to 24 when using LFO Saw
     
  19. EvilDragon

    EvilDragon Well-Known Member

    Messages:
    19,938
    Nope. The numbers are all verified, and pitch modulation range is the same for all internal modulators. I just confirmed this again.
     
    Last edited: Feb 26, 2016
  20. gwhizoflc

    gwhizoflc New Member

    Messages:
    20
    So for a saw wave, the LFO will go from the initial pitch down 2 octaves, or up 2 octaves, depending on the INVERT with 1130000?