Skip to content

NSL - NGEN SCRIPTING LANGUAGE

The NSL Engine Generator is a powerful tool that lets you create your own custom algorithms using a simple scripting language.

At it's core, the NSL Engine features a 32-step sequence (with individual pitch, velocity, length (in beats) and density per step) and standard parameters such Shift, Length and Density to control playback.

Instead of using a pre-defined algorithm to fill the 32-step sequence, the NSL Engine lets you load a script to generate it using your own custom algorithm.

Each NSL script consists of a series of hex values that are parsed into commands and values. Hex values of 160 (0xA0) or higher trigger new commands and values below 160 are assigned as values / parameters for these commands. The engine also includes 32 registers (Memory Buffer) that can be used to store values and use them later in the script and 4 generic parameters (Param 1-4) with ranges from 0-100.

Warning

The NSL Engine is still in beta and it's not fully documented and implemented yet. This section of the manual will be updated as we continue to develop the NSL Engine. Scripts that run out of control are stopped by the engine's execution limits (see Execution Limits) instead of freezing the generator, but faulty scripts can still produce unexpected sequences.


ngen_nsl Rust Library

ngen_nsl is a custom Rust library available via cargo / crates.io that make it easier to create and parse NSL scripts for the NSL Engine.

To add it to your Rust project, run the command cargo add ngen_nsl in your project's directory.

Documentation for ngen_nsl is available at https://docs.rs/ngen_nsl.


NSL Programming Reference

Script File Format

NSL scripts are stored as binary files in the /NSL folder of your microSD card (see File Management). Each file starts with a 4 byte header followed by the program itself:

Position Content Description
0 - 2 NSL File identifier (0x4E 0x53 0x4C)
3 Version NSL script version marker
4 - end Program Series of commands and values

A program can be up to 65535 bytes long and the file name is limited to 15 characters. Files shorter than 4 bytes or files that don't start with the NSL identifier are rejected and the previously loaded script is kept.


Parameter Types

NSL commands require set of different parameters to execute correctly and each parameter's value is used according to the list below:

VALUE

The VALUE parameter type returns a constant values from 0x00 to 0x7F (0-127) and values stored in the NSL Engine's memory buffer from 0x80 to 0x9F (128-159).

DESTINATION / SOURCE

The DESTINATION / SOURCE parameters consists of 2 x VALUE parameters that are used in pair to retrieve values from different parts and features of the NSL Engine.

SOURCE parameters are used to retrieve data while DESTINATION parameters are used to set data.

The first VALUE in the pair (aka VALUE 1) is used to indicate the type / location of the value that follows it (VALUE 2) according to the table below:

PART / FEATURE VALUE 1 (Address) VALUE 2 (Value / Index) VALUE 2 RANGE SOURCE DESTINATION DESTINATION RANGE
Constant Value 0x00 Value 0-127 ✔︎ ✕ N/A
Random Value 0x01 Random Range 0-127 ✔︎ ✕ N/A
Step Pitch 0x02 Step Number (Zero-Indexed) 0-31 ✔︎ ✔︎ 0-127 (MIDI PITCH)
Step Velocity 0x03 Step Number (Zero-Indexed) 0-31 ✔︎ ✔︎ 0-127 (MIDI VELOCITY)
Step Length 0x04 Step Number (Zero-Indexed) 0-31 ✔︎ ✔︎ 0-7 (BEATS)
Step Density 0x05 Step Number (Zero-Indexed) 0-31 ✔︎ ✔︎ 0-49
Memory Buffer 0x06 Memory Index (Zero-Indexed) 0-31 ✔︎ ✔︎ 0-255
Params 1-4 0x07 Parameter Number (Zero-Indexed) 0-3 ✔︎ ✔︎ 0-99
Scale 0x08 Note position in scale 0-127 ✔︎ ✕ N/A
Scale (Quantized) 0x09 Note position in scale 0-127 ✔︎ ✕ N/A
Random Note 0x0A Probability (Root Note Chance) 0-100 ✔︎ ✕ N/A

Some features such as Constant and Random use the second VALUE in the pair (VALUE 2) as the actual value while the other types use it as an index to indicate the location of the value in the NSL Engine's memory.

Examples:

  • 0x00 0x05 : Returns a constant value (ORIGIN = 0x00) of 5 (VALUE = 0x05).
  • 0x02 0x10 : Returns the step pitch (ORIGIN = 0x02) at index 16 (VALUE = 0x10).
  • 0x01 0x20 : Returns a random value (ORIGIN = 0x01) between 0 and 31 (VALUE = 0x20). The upper limit is exclusive, so the range is always 0 to VALUE - 1.
  • 0x07 0x02 : Returns the value of Param 3 (ORIGIN = 0x07) at parameter index 2 (VALUE = 0x02).

INT16

The INT16 parameter type uses a pair (x and y) of 8-bit values (0-255) to create a 16-bit value (0-65535) by shifting the first value 8 bits to the left and adding the second value to it ((x << 8) + y).


Execution Limits

Every time you run Generate, the NSL Engine clears all step sequences and the memory buffer before running the program. Scripts always start from an empty state, so a script must build the whole sequence by itself.

To keep faulty scripts from locking up the generator, the engine stops the program when it reaches any of the limits below. The rest of the program is skipped and the sequence generated so far is kept.

Limit Value Behavior
Instructions per generation 20000 Program stops (watchdog)
Nested loops 4 Program stops
Nested conditions 4 Program stops
JUMP position Must be smaller than the program size Program stops

List of Commands

0xA1 SET

Description: Sets the value of a destination to the value of a source.

Parameters: DESTINATION SOURCE

Examples:

  • 0xA1 0x02 0x00 0x01 0x10 : Sets the pitch of step 1 to a random value between 0 and 15.

  • 0xA1 0x03 0x00 0x03 0x01 : Sets the velocity of step 1 (0x03 0x00) to the velocity of step 2 (0x03 0x01).

  • 0xA1 0x06 0x00 0x05 0x04 : Sets the value of the memory buffer at index 0 to the density of step 5.

0xA3 CLEAR TRACK

Description: Clears the pitch, velocity, length and density sequences (all 32 steps).

Parameters: None

Examples:

  • 0xA3 : Clears the sequence of the current track.

0xA4 CLEAR MEMORY

Description: Clears the memory buffer, setting all 32 registers to 0.

Parameters: None

Examples:

  • 0xA4 : Clears the memory buffer.

0xA5 CLEAR ALL

Description: Clears the track and the memory buffer, returning the sequence to the same empty state used at the start of a generation.

Parameters: None

Examples:

  • 0xA5 : Clears everything.

0xB0 ADD

Description: Adds the value of a source to a destionation.

Parameters: DESTINATION SOURCE

Examples:

  • 0xB0 0x02 0x00 0x00 0x02 : Add 2 (0x00 0x02) to the pitch of the first step (0x02 0x00).

0xB1 SUBTRACT

Description: Subtracts the value of a source from a destination.

Parameters: DESTINATION SOURCE

Examples:

  • 0xB1 0x02 0x00 0x01 0x10 : Subtract a random value between 0 - 15 (0x01 0x10) from the pitch of the first step (0x02 0x00).

0xB2 MULTIPLY

Description: Multiplies the value of a destination by the value of a source.

Parameters: DESTINATION SOURCE

Examples:

  • 0xB2 0x03 0x00 0x00 0x02 : Doubles the velocity of the first step (0x03 0x00).

0xB3 DIVIDE

Description: Divides the value of a destination by the value of a source. If the source value is 0, the command is ignored to avoid division by zero.

Parameters: DESTINATION SOURCE

Examples:

  • 0xB3 0x02 0x00 0x00 0x02 : Halves the pitch of the first step (0x02 0x00).

0xB4 PITCH QUANTIZE

Description: Quantizes the pitch of all 32 steps of the current track to the active scale.

Parameters: None

Examples:

  • 0xB4 : Snaps every pitch value of the current track to the nearest note of the active scale.

0xB5 GENERATE PROGRESSION

Description: Generates a chord progression and stores its 4 degrees in the memory buffer at index 0 to 3. These are the same progression degrees used by the Arpeggiator, POP and LUAR generators.

Each degree is a position in the active scale, so you read them back as a Scale source (0x08) combined with an indirect address from 0x80 to 0x83.

Parameters: None

Examples:

  • 0xB5 0xA1 0x02 0x00 0x08 0x80 : Generates a progression and sets the pitch of the first step to the note of the first degree.

0xB6 GENERATE EUCLID

Description: Builds a Euclidean rhythm over the 32 steps of the current track and writes it as the velocity sequence. Steps that receive a hit get a velocity of 127, all other steps are set to 0.

Parameters: SOURCE (Number of Pulses) SOURCE (Rotation Offset)

Examples:

  • 0xB6 0x00 0x05 0x00 0x00 : Distributes 5 pulses evenly over the 32 steps of the current track.

0xC0 LOOP SET

Description: Starts a loop and sets the loop count to the value of a source. The first pass counts as one run, so a loop count of 3 executes the commands between LOOP SET and LOOP END 3 times in total.

Parameters: SOURCE (Loop Count)

Examples:

  • 0xC0 0x00 0x03 : Repeats the commands until the next LOOP END 3 times.

Loops can be nested up to 4 levels deep. A LOOP END without a matching LOOP SET is ignored.

0xC1 LOOP END

Description: Ends the current loop and jumps back to the matching LOOP SET until the loop count is reached.

Parameters: None

0xC2 JUMP

Description: Jumps to a specific position in the program. The jump position must be smaller than the size of the program, otherwise the program stops.

Parameters: INT16 (Jump Position)

Examples:

  • 0xC2 0x02 0x24 : Jumps to position 548.

0xD0 EQUAL

Description: Starts a condition that only runs the commands that follow when both values are equal. Both values are read again before each command, so a condition can react to changes made by the script itself. Conditions stay active until END COND.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD0 0x06 0x00 0x00 0x01 0xA1 0x02 0x00 0x00 0x42 : Sets the pitch of the first step to 66 only while the memory buffer at index 0 is equal to 1.

0xD1 NOT EQUAL

Description: Starts a condition that only runs the commands that follow when both values are different.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD1 0x06 0x00 0x00 0x00 : Runs the following commands while the memory buffer at index 0 is not 0.

0xD2 GREATER THAN

Description: Starts a condition that only runs the commands that follow when the left value is greater than the right value.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD2 0x03 0x00 0x00 0x64 : Runs the following commands while the velocity of the first step is greater than 100.

0xD3 LESS THAN

Description: Starts a condition that only runs the commands that follow when the left value is smaller than the right value.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD3 0x03 0x00 0x00 0x64 : Runs the following commands while the velocity of the first step is smaller than 100.

0xD4 GREATER OR EQUAL

Description: Starts a condition that only runs the commands that follow when the left value is greater than or equal to the right value.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD4 0x07 0x00 0x00 0x32 : Runs the following commands while Param 1 is greater than or equal to 50.

0xD5 LESS OR EQUAL

Description: Starts a condition that only runs the commands that follow when the left value is smaller than or equal to the right value.

Parameters: SOURCE (Left Value) SOURCE (Right Value)

Examples:

  • 0xD5 0x07 0x00 0x00 0x32 : Runs the following commands while Param 1 is smaller than or equal to 50.

0xD6 END COND

Description: Ends the current condition. When conditions are nested, END COND closes the innermost one and returns to the condition that contains it. Conditions can be nested up to 4 levels deep.

Loop and condition commands always run, even when a condition is not met, so the structure of a script is never broken by a condition.

Parameters: None

Examples:

  • 0xD6 : Ends the active condition.

0xFF END

Description: Ends the program.

Parameters: None


Script Playback

A script only builds the sequence. The generator parameters decide how that sequence is played:

Parameter Effect during playback
Length Sets how many steps are played (1-32). Steps after the Length are never triggered.
Density Works as a threshold. A step only sounds when its own density value is smaller than the Density parameter, so higher values let more steps play.
Shift Transposes the pitch of every step by up to 12 semitones in each direction.
Quantize When enabled, every pitch is quantized to the active scale during playback.

A step is triggered when all of these are true:

  • Velocity is greater than 0.
  • Step length is greater than 0.
  • The density value of the step is smaller than the Density parameter.

The duration of each note is the step length multiplied by the note length of the track, reduced by 10% so that repeated notes are always separated.