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,
ckspallows 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. -
Type-Neutral Initialization
Variables are always initialized with their type's neutral value if no initial value is provided.
Default values:0for integers,0.0for reals,""for strings. This is also true for local variables. -
Local Scope
Variables can be declared independently of callbacks in any scope and are only valid within the scope in which they are declared.
-
Constants
Variables are mutable by default but can be declared
constto make them immutable after initialization. -
Thread Safety
Local variables are thread-safe and isolated to their scope.
Global variables can cause race conditions in asynchronous callbacks.
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.
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:
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. -
Bulk Initialization
Arrays support operations across all elements, such as initialization with the same value or assignment from lists.
-
Zero-Based Indexing
All arrays in
ckspare zero-based.
The first element has index0, the last has indexnum_elements(<array>)-1. -
Copy Semantics
Assignments between arrays copy all elements.
Arrays are not reference types; each assignment creates an independent copy.
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.
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:
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.
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. -
Internal Flattening
Internally, NDArrays are lowered into one-dimensional KSP arrays.
ckspautomatically calculates indices, soa[i,j]maps to the correct flat position. -
Wildcard Notation
Wildcards (
*) allow fast access to entire dimensions and are compatible with built-in functions likesearchandsort. -
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.
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.
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:
Wildcard Notation
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)
Here, the type of this multidimensional array temporarily becomes a one-dimensional array (
int[]).This notation is identical to
my_ndarraywithout 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.
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
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.
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].