Skip to content

How to Set Up a Keymap

Configure a multi-zone keyboard layout with play zones, keyswitch zones, and inactive zones so that Kontakt's key display reflects your product's note routing.

Prerequisites

  • A working IVLS product with at least two flows (for example, a play flow and a keyswitch flow)
  • Ivls.Keymaps included via the IVLS core (it is part of the base system)
  • Familiarity with flows and keymap concepts

Steps

1. Create a keymap node with cb Keymaps

The cb Keymaps callback runs during keymap initialization. Inside it, you register a keymap category and assign each key to a flow with a color and type.

node MyProduct.Keymap:
    cb Keymaps:
        { Register a category name for our keymap requests }
        define KEYMAPS += my_keys

        declare i

        for i := 0 to 127
            if in_range(i, 36, 96)
                { Play zone: C2 to C7 }
                keymap.request(my_keys, 0, i, ...
                    my.play_flow, ...
                    NI_KEY_TYPE_DEFAULT, KEY_COLOR_BLUE, "")
            else if in_range(i, 24, 35)
                { Keyswitch zone: C1 to B1 }
                keymap.request(my_keys, 0, i, ...
                    my.keyswitch_flow, ...
                    NI_KEY_TYPE_CONTROL, KEY_COLOR_RED, "")
            else
                { Inactive keys: everything else }
                keymap.request(my_keys, 0, i, ...
                    my.no_play_flow, ...
                    NI_KEY_TYPE_NONE, KEY_COLOR_INACTIVE, "")
            end if
        end for
end node

2. Register the category

The define KEYMAPS += my_keys line inside cb Keymaps registers a category name. Categories prevent two systems from claiming the same key on the same map -- if another node tries to keymap.request a key that my_keys already owns, IVLS logs an error.

3. Understand the keymap.request parameters

keymap.request takes seven arguments:

Parameter Purpose
#category# Category name token (declared via define KEYMAPS +=)
#map_i# Map index (0 for the default map; up to keymap.MAX_MAPS - 1)
#key_i# MIDI key number (0--127)
#flow# Flow to route this key's notes through
#type# Kontakt key type: NI_KEY_TYPE_DEFAULT (playable), NI_KEY_TYPE_CONTROL (keyswitch), or NI_KEY_TYPE_NONE (inactive)
#color# Kontakt key color constant (e.g. KEY_COLOR_BLUE, KEY_COLOR_RED, KEY_COLOR_INACTIVE)
#name# Display name string shown on hover (use "" for no name)

4. Set up the three-zone pattern

A typical orchestral or multi-articulation product uses three zones:

node MyProduct.Keymap:
    cb Keymaps:
        define KEYMAPS += my_keys

        declare i

        { Zone 1: Keyswitches (C0 to B0) }
        for i := 12 to 23
            keymap.request(my_keys, 0, i, ...
                my.keyswitch_flow, ...
                NI_KEY_TYPE_CONTROL, KEY_COLOR_RED, my.artic_names[i - 12])
        end for

        { Zone 2: Play range (C1 to C6) }
        for i := 24 to 96
            keymap.request(my_keys, 0, i, ...
                my.play_flow, ...
                NI_KEY_TYPE_DEFAULT, KEY_COLOR_BLUE, "")
        end for

        { Zone 3: Inactive (everything else) }
        for i := 0 to 127
            if i < 12 or i > 96
                keymap.request(my_keys, 0, i, ...
                    my.no_play_flow, ...
                    NI_KEY_TYPE_NONE, KEY_COLOR_INACTIVE, "")
            end if
        end for
end node

5. Add the keymap node to IVLS_NODES

define IVLS_NODES := ..., MyProduct.Keymap, ...

For inactive keys, create a flow that silently consumes voices without triggering any events:

node MyProduct.NoPlay:
    cb NotePass:
        { Swallow the voice -- do nothing }
end node

Register it in your flows:

cb Flows:
    define FLOWS += my.no_play_flow
    ivls.register_node(my.no_play_flow, MyProduct.NoPlay)

Updating keys at runtime

To change key properties after initial setup (for example, highlighting the active keyswitch), use the update macros:

{ Change a key's color }
keymap.update_key_color(my_keys, 0, active_ks_key, KEY_COLOR_GREEN)

{ Change a key's type }
keymap.update_key_type(my_keys, 0, key_i, NI_KEY_TYPE_CONTROL)

{ Change a key's display name }
keymap.update_key_name(my_keys, 0, key_i, "Sustain")

All update macros require the owning category name -- you cannot update a key owned by a different category.

Multiple maps

For products that switch between different keyboard layouts (for example, an instrument with separate ensemble and solo modes), use different map indices:

{ Map 0: Ensemble layout }
keymap.request(my_keys, 0, i, my.ensemble_flow, ...)

{ Map 1: Solo layout }
keymap.request(my_keys, 1, i, my.solo_flow, ...)

{ Switch to map 1 at runtime }
keymap.select_map(1)

Verify

  1. Load the product -- Kontakt's keyboard display should show colored zones matching your configuration
  2. Play notes in the play zone -- they should trigger your play flow
  3. Press keys in the keyswitch zone -- they should trigger your keyswitch flow (verify via message() or UI indicator)
  4. Press keys in the inactive zone -- no sound should play
  5. If using key names, hover over keyswitch keys -- the name should appear in Kontakt's status bar

Further reading

  • Guide: Keymap System for the full architecture and multi-map details
  • Guide: Flows for understanding how keys route to flows