Skip to content

Variables and Arrays

Variables

Variables are placeholders for data values of a specific type. They allow you to store, access, and manipulate data throughout your script. Variables can hold values of five basic types: integers (int), real numbers (real), strings (string), booleans (bool), and objects (more on this here). Their types influence the operations and functions they can interact with.

Variables can contain both alphabetic (a-z, A-Z) and numeric (0-9) characters, as well as underscores (_) and dots (.). Additionally, they are case-sensitive, meaning var1 and Var1 are two different variables. This differs from sKSP and vanilla KSP, where variable names are case-insensitive. The following features also apply, with slight modifications, to arrays and multidimensional arrays.

  • Dynamic Type Inference


    While variables can have explicit type annotations, cksp allows the type to be inferred by the compiler.
    Type annotations can only be used in declarations and function parameters, not in assignments or function calls.

    Declarations and Variables

  • Type-Neutral Initialization


    Variables are always initialized with their type's neutral value if no initial value is provided.
    Default values: 0 for integers, 0.0 for reals, "" for strings. This is also true for local variables.

    Type-Neutral Declarations

  • Local Scope


    Variables can be declared independently of callbacks in any scope and are only valid within the scope in which they are declared.

    Scoped Variables

  • Constants


    Variables are mutable by default but can be declared const to make them immutable after initialization.

    Constant Variables

  • Thread Safety


    Local variables are thread-safe and isolated to their scope.
    Global variables can cause race conditions in asynchronous callbacks.

    Lexical Scope

Naming Conventions

Since the compiler internally works with certain internal variables and, for example, converts multidimensional arrays into raw arrays, variable names should generally not begin with an underscore. Variables like those listed below are therefore not recommended.

1
2
3
4
my_variable: int
var_1: real
my_string: string
my_truth: bool
1
2
3
4
_my_variable: int // Underscore at the beginning
_var_1: real
_my_string: string
_my_truth: bool

Dots in Variable Names

Since CKSP also supports the definition of custom data structures and access to their members via dot notation, it is recommended to avoid using dots in variable names for better code readability whenever possible.

Reserved Prefixes

Additionally, there are some reserved prefixes used internally by Kontakt for internal variables. These are:

$NI_
$CONTROL_PAR_
$EVENT_PAR_
$ENGINE_PAR_
$ZONE_PAR_
$LOOP_PAR_


Arrays

Arrays are data structures that group multiple elements of the same type into a single entity. This allows for efficient storage and manipulation of sequences of data, such as lists of numbers or strings. Therefore, arrays must always have a fixed size, which is specified at the time of declaration. This size can be defined either by an integer literal or a constant and is indicated in square brackets following the array name during declaration.

  • Fixed Size


    The size of an array is determined at declaration and cannot be changed later.
    Maximum size: 1,000,000 elements.

    Array Declarations

  • Bulk Initialization


    Arrays support operations across all elements, such as initialization with the same value or assignment from lists.

    Array Assignments

  • Zero-Based Indexing


    All arrays in cksp are zero-based.
    The first element has index 0, the last has index num_elements(<array>)-1.

    Referencing Array Elements

  • Copy Semantics


    Assignments between arrays copy all elements.
    Arrays are not reference types; each assignment creates an independent copy.

    Array Assignments

Naming and Types

The naming rules for arrays are the same as those for variables.

Arrays can be declared for any of the aforementioned three basic types. All elements of an array must be of the same type. The type annotations for arrays differ from those for variables in that arrays are composite types. This is indicated by appending [] to the base type.

1
2
3
4
my_array[10]: int[]
arr_1[11]: real[]
myarray[34]: string[]
my_truths[3]: bool[]

Maximum Array Size

The maximum array size is limited by KSP and, as of Kontakt 7.10.0, is 1000000 elements.

Referencing Array Elements

To access individual indices, use the array name followed by square brackets containing the index. The index starts at 0 and ends at the size of the array minus 1. For example, to access the third element of the previously declared array my_array with a size of 10, use the following code:

my_array[2]  // Accesses the third element of the array

Getting the Size of an Array

To determine the size of an array at runtime, you can use the num_elements() function. This function returns the number of elements in the array. The array is passed as a reference without square brackets.

num_elements(my_array)  // Outputs the size of the array

Multidimensional Arrays

Multidimensional arrays (NDArrays) extend the concept of arrays to two or more dimensions, allowing for the representation of matrices, grids, or higher-dimensional data structures. These arrays are especially useful for organizing complex datasets.

  • Multiple Dimensions


    NDArray declarations allow arbitrary dimensions. Each dimension is specified explicitly, and indexing starts at 0.

    Multidimensional Array Declarations

  • Internal Flattening


    Internally, NDArrays are lowered into one-dimensional KSP arrays. cksp automatically calculates indices, so a[i,j] maps to the correct flat position.

  • Wildcard Notation


    Wildcards (*) allow fast access to entire dimensions and are compatible with built-in functions like search and sort.

    Wildcard Notation

  • Dimension-Aware Size Retrieval


    The num_elements() function returns either the full flattened size or the size of a specific dimension.
    Wildcards can also be used for size queries.

    Getting the Size of a Specific Dimension

The size of each dimension is specified by comma-separated constants or integer literals within the brackets during the declaration. In the optional type annotation, the number of opening and closing brackets represents the number of dimensions. As with one-dimensional arrays, multidimensional arrays can be declared for any of the basic types.

1
2
3
4
my_ndarray[10, 20]: int[][]
ndarr_1[11, 12, 13]: real[][][]
myndarray[34, 42, 56]: string[][][]
my_many_truths[3, 4, 5, 6]: bool[][][][]

Maximum Size of Multidimensional Arrays

Due to the limitation of KSP regarding the maximum array size and the internal representation of multidimensional arrays in CKSP as Vanilla KSP Arrays, the previously explained size restriction also applies to multidimensional arrays. The multiplication of the sizes of the individual dimensions must not exceed 1000000 elements.

Referencing NDArray Elements

Referencing elements in multidimensional arrays is done by specifying the indices in square brackets, with the indices separated by commas. The index for each dimension starts at 0 and ends at the size of the dimension minus 1. For example, to access the element in the third row and the fourth column of the previously declared NDArray my_ndarray, use the following code:

my_ndarray[2, 3]  // Accesses the element in the third row and fourth column

Wildcard Notation

0.0.7

In the context of arrays, CKSP introduces a wildcard notation that allows you to access elements of specific dimensions quickly. Instead of an index, a * is used to access all elements of that dimension.

my_ndarray[2, *]  // Accesses all elements in the third row (1) 
my_ndarray[*, *]  // Accesses all elements in the entire array (2)
  1. 🙋‍♂️ Here, the type of this multidimensional array temporarily becomes a one-dimensional array (int[]).
  2. 🙋‍♂️ This notation is identical to my_ndarray without brackets.

The wildcard notation can be used in various contexts, including copying individual dimensions from another array (Array Declarations), searching within a specific dimension, or sorting certain parts of a multidimensional array (Searching and Sorting).

Getting the Size of a Specific Dimension

To determine the size of a specific dimension or the total number of elements of an NDArray at runtime, you can also use the num_elements() function. The function can take two arguments in the case of multidimensional arrays: the array itself and the number of the dimension for which the size is to be determined. If no integer or 0 is specified, the total number of elements of the internal one-dimensional KSP array is returned.

Another notation option to determine the size of individual dimensions is the wildcard notation, where the desired dimension is replaced by a *. Both variants are shown below.

1
2
3
num_elements(my_ndarray, 1)  // Outputs the number of rows (10)
num_elements(my_ndarray, 2)  // Outputs the number of columns (20)
num_elements(my_ndarray)     // Outputs total number of elements (10*20 in this case)
1
2
3
num_elements(my_ndarray[*, 2])  // Outputs the number of rows (10)
num_elements(my_ndarray[1, *])  // Outputs the number of columns (20)
num_elements(my_ndarray[*, *])  // Outputs total number of elements (10*20 in this case)

Dimension Parameter out of bounds

If the specified parameter for the dimension is greater than the number of dimensions of the multidimensional array, the size of the last dimension is returned without an error being issued. This behavior can occur, for example, when using variables as the second parameter.

Searching and Sorting Multidimensional Arrays

0.0.7 7.3

For the array-specific functions search and sort, CKSP offers a specialized syntax using wildcard notation to apply these functions to multidimensional arrays. The wildcards * indicate that the function should be applied to all elements of the corresponding dimension.

  search(my_ndarray[2, *], 5)  // Searches for the value 5 in the third row
  search(ndarr_1[4, *, *], 1)  // Searches the second and third dimension for the value 1
  sort(my_ndarray[3, *], 0)    // Sorts the fourth row in ascending order

Limitations of Wildcard Notation in Built-in Functions

Wildcards are only allowed in certain indices and specific order. Wildcards must always be at the end of the index list and cannot be in the middle or at the beginning. Once multiple wildcards are used, they must be directly next to each other and cannot have a number or other character in between. For example, my_ndarray[*, 2] is not allowed, as well as ndarr_1[*, 2, *] or my_ndarray[*, 2, 3].