What's new

Menu to control which group could be filtered

Hi there, can anyone help me with a code for a drop down menu for my filter section where I can chose between a Main and Bass group?
At the moment the filter controls all layers but I want it separate that I could filter the Bass group maybe a bit more than the Instrument group/s.

Here is what I already have:

declare ui_menu $menu
add_menu_item($menu,"MAIN",1)
add_menu_item($menu,"BASS",2)
set_control_par_str(get_ui_id($menu),$CONTROL_PAR_PICTURE,"FILTER")
set_control_par(get_ui_id($menu),$CONTROL_PAR_POS_X,317)
set_control_par(get_ui_id($menu),$CONTROL_PAR_POS_Y,226)
There is a problem with the picture there is something written in it but I don't know how to fix this.
 
Last edited:
Interesting, you asked for help with one thing on your upper section. Then after the code block you asked for help with something else. That's confusing.

I'll reply to your upper section:

Think of PROGRAMMING first, then you code.

What do you want your program to do?

You want separate filter settings / parameter values for a main group and a bass group.

Considering you have n groups and a bass group, there's 2 ways to achieve this:
1) you insert a filter module in a certain slot in the group level, in ALL groups.
2) you insert a filter module in a certain slot in the instrument insert level

The problem with 2) is that if you play any of the N groups AND the bass group, you won't be able to
change the filter settings, or at least not in the simplest wat (maybe managing these settings event by event) but for the sake of simplicity, let's go with 1)

1) you added a filter module in the same slot x (0-7) in all groups existing in your instrument.

I don't know if the way to choose which groups play is the same menu you mentioned, but let's assume it is NOT. This way you can use a menu to select which group's filter settings you want to change.

Now some actual programming: Since you have filters in all groups, you need a way to connect one or more controls that will represent the filter's parameters (cutoff, resonance) to the filter in the group you actually want to change. How? You need some sort of index that will be selected when the user wants to affect group n.

A ui_menu is a good choice since you can add index values to the menu entries.

Meaning that when you change a knob or slider supposed to change the filter cutoff, all you have to do is

<command to change parameter> <value> <group address> <filter address>

in whatever place that has the code whenever that slider is used.

Now that you have clarity on what and how to do what you want, you can code.

What is the name of the code block that runs when your ui_control is interacted with?

ui_control callback.

what's the syntax?
Code:
on ui_control($filter_slider)
   my code here
  
end on

great, now how do we translate the command to change the filter parameter into actual code?

Code:
on init
    declare ui_menu $filter_menu
        add_menu_item($filter_menu, "Main", 0)
        add_menu_item($filter_menu, "Bass", 1)

    declare ui_slider $filter_cutoff       (0,1000000)
    declare ui_slider $filter_resonance (0,1000000)

    declare const $FILTER_SLOT := 0 { put the filter in the 0th index slot }
end on

on ui_control($filter_cutoff)
    set_engine_par($ENGINE_PAR_CUTOFF, $filter_cutoff, $filter_menu, $FILTER_SLOT, -1)
end on

on ui_control($filter_resonance)
    set_engine_par($ENGINE_PAR_RESONANCE, $filter_resonance, $filter_menu, $FILTER_SLOT, -1)
end on

on ui_control($filter_menu)
    $filter_cutoff        := get_engine_par($ENGINE_PAR_CUTOFF,       $filter_menu,$FILTER_SLOT, -1)
    $filter_resonance := get_engine_par($ENGINE_PAR_RESONANCE, $filter_menu,$FILTER_SLOT, -1)
end on

Yeap, I got ahead of myself and made the menu change update the controls on the UI too.

Hope this is a good starting point for what you want to understand and do.
 
THAT WORKS PERFECT! THANKS!!!

Now I have a last question, my Main group is (0) and the Bass group is (6) is it possible to control all the layers between 0 and 6 (1,2,3,4,5) with the same slider that I use for the Main without adding menu_items for these groups? I already tried something but when I change between Main and Bass both options are working for these groups.
 
@Gablux I tried it like this but only group (0) is still working

declare ui_menu $filter_menu
declare %groups[6] := (0,1,2,3,4,5)
add_menu_item($filter_menu, "MAIN", %groups[6])
add_menu_item($filter_menu, "BASS", 6)
declare const $FILTER_SLOT := 0
 
Again, go back to programming.

I want to control groups 0 - 5 filter parameters when the menu is set to 0 (Main)
I want to control groups 6 - n filter parameters when the menu is set to 1 (Bass)

Ok, so you have a condition that when met in a certain way, you have to do one something
when met in another way, another something. How do you do that and where do you do that ?

First where.
If you are affecting a range of groups when a parameter is changed, where do you do it? In the code block of the parameter change.
What's the difference between changing one group or a range of groups?
If the groups are consecutive, meaning one after another like 1,2,3, etc you can use a loop to set the parameter of the filter in each of these groups.
If the groups were not consecutive, you would need another solution which I am not going to talk about since it is not your case.

The loop should affect the range. How?

Loop from 0 to 5 using $counter:
<change filter cutoff > <$filter_slider_value> <$counter {group index}> <slot address>

You have all you need in the text above, now go look in the KSP manual how to write the syntax in KSP of the loop :)
 
@Gablux I made it like this know:

on ui_control($cutoff)
if ($filter_menu = 0)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, $filter_menu, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 1, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 2, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 3, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 4, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 5, $FILTER_SLOT, -1)
end if
if ($filter_menu = 6)
set_engine_par($ENGINE_PAR_CUTOFF, $cutoff, 6, $FILTER_SLOT, -1)
end if
end on

on ui_control($resonance)
if ($filter_menu = 0)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, $filter_menu, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 1, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 2, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 3, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 4, $FILTER_SLOT, -1)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 5, $FILTER_SLOT, -1)
end if
if ($filter_menu = 6)
set_engine_par($ENGINE_PAR_RESONANCE, $resonance, 6, $FILTER_SLOT, -1)
end if
end on

on ui_control($filter_menu)
$cutoff := get_engine_par($ENGINE_PAR_CUTOFF, $filter_menu,$FILTER_SLOT, -1)
$resonance := get_engine_par($ENGINE_PAR_RESONANCE, $filter_menu,$FILTER_SLOT, -1)
end on
it works but I don't know if this is the right way
 
Last edited:
If it works, it is the right way.

Next question is: can it be improved?
Yes.

First thing, using one of the first 'laws of programming' (I just made that up): if you repeat things, you could probably encapsulate that in a loop.

The way to loop in KSP is using the while (condition) end while statement.

it will not change your program, but it will be easier to look at. Anything easier to look at is easier to maintain later.
 
If it works, it is the right way.

Next question is: can it be improved?
Yes.

First thing, using one of the first 'laws of programming' (I just made that up): if you repeat things, you could probably encapsulate that in a loop.

The way to loop in KSP is using the while (condition) end while statement.

it will not change your program, but it will be easier to look at. Anything easier to look at is easier to maintain later.
so does that mean I should change end if to end while or what? If there is something wrong please let me know before I save it.
 
@Gablux for the filter it was filter slot 0 but what is the number or the way to script the same menu for my envelope too? I tried a couple things but I don't get it only need the ""declare const $FILTER_SLOT := 0 { put the filter in the 0th index slot } "" line
 
Envelope is a bit different. The slot of the envelope is not between 0-7 since the envelope modulation is not inserted into one of these slots but added in different places like the group volume amp section, pitch section and into the FX parameters too.

The structure to address a value change in any envelope parameter (or any modulator parameter) is the same as control par or engine par:
<command to access the paramter> <constant addressing the parameter> < value > < group > < slot > <generic >
which in KSP is

set_engine_par( $ENGINE_PAR_ATTACK, a_value, group_number, *here we need something different, generic)

*the something different is:
up to Kontakt 6 or even 7.0 the way to obtain the slot address for modulations was find_mod()
in 7.1 we use get_mod_idx()

Usage is the same for both functions:
find_mod( group_number, "MOD_NAME")
"MOD_NAME" should be in quotes and is obtained when you go to edit view mode, have script editor open and right click on the background of the modulation you want to obtain the name for. You will see this:
1700432790930.png

The string value to be used between quotes would be ENV_AHDSR.

And finally the final command to change attack :

K < v7.1
set_engine_par($ENGINE_PAR_ATTACK, $slider_attack, 0, find_mod(0, "ENV_AHDSR"), -1)

K 7.1+
set_engine_par($ENGINE_PAR_ATTACK, $slider_attack, 0, get_mod_idx(0, "ENV_AHDSR"), -1)
 
Top Bottom