Skip | Home | Site Map | Terms and Conditions | Feedback Form | Keys

Noatikl User Guide


Scripting: Overview

Noatikl contains a powerful scripting engine, which while entirely optional to use, offers tremendous power.

Introduction to Noatikl Scripting

Noatikl contains several very powerful scripting features, which can be used in two separate contexts.

The most common way to use scripting in Noatikl, it to embed small Trigger Scripts, which are small bits of code in the widely used Lua language, attached to the Piece or to Voice objects. These scripts are triggered when various events happen when Noatikl is playing. Using trigger scripts allows you to tell Noatikl to behave in very powerful ways while it is playing.

The other way to use scripting in Noatikl, is to use the Noatikl Script Window to create and run scripts written in the Lua language, to manipulate Noatikl editor windows. This is done through the Noatikl Script Window. This allows you to, for example, dynamically create random Noatikl compositions.

Noatikl scripts are written using the widely used Lua scripting langauge. Lua is very powerful, fast and easy to learn. Lua is a very popular embedded scripting langage, and is widely used in the gaming and multimedia worlds. Noatikl adds various noatikl-specific functions to the Lua language. These extensions are outlined later in this document. We give you lots of examples to get you started. If you ever get stuck, or if you want to share your cunning scripts with fellow Noatikl users, then please make use of the Noatikl forums!

Note that Noatikl supports the table, string and math standard Lua libraries. It does not support the io or os libraries.

Why would you want to use Noatikl Scripting?

With careful use of trigger scripts, you can use Noatikl to build a custom hyperinstrument!

You can, if you wish, create trigger scripts to run at the following times:

  • start of playback
  • every bar
  • when a note is composed by noatikl
  • end of playback
  • in response to MIDI CC via e.g. keyboard controller
  • in response to MIDI Note on/off via e.g. keyboard controller

Every script can do pretty much anything to the Noatikl engine in real-time, such as manipulating music rules, playing with mutation, and what have you.

We also have a new hyperinstrument mode, and allow the Note on/off commands to control parameters and/or trigger "listening" voices within Noatikl, that can in turn trigger off other musical events such as auto-chording events or following voices.

The scripts are in the very widely used Lua scripting language.

A note on print

Note that the standard Lua function print may be used to display text in the Noatikl console window (if you happen to have that displayed; this is very useful for debugging your scripts!

A note on Comments in Lua script

Single-line comments in Lua script start with the two minus characters:

  -- This is a comment

To comment-out a block of text in Lua, enclose the text in --[[ and ]] as in this example

  print ("Hello")
  --[[
  This is a big block
  of text that I want to comment out!
  ]]
  print ("World")

Trigger Scripts ("Triggers")

Noatikl Triggers can be assigned to most Noatikl objects, including the Piece and Voice objects.

Not all Noatikl script functions are available to you within Noatikl trigger scripts; specifically, the functions that open and manipulate windows are not available from Triggers (these are reserved for use from the Noatikl Script Window). You can enter these scripts using the following Noatikl views:

There are a variety of Trigger Scripts types that you may invoke.

Start

The Start Trigger Script is called once at the start of the Piece, when the piece starts playing.

function nt_trigger_start()
  print ("Piece start!")
end
  

Bar

The Bar Trigger Script is called at the start of every bar while the piece is playing.

function nt_trigger_bar(bar)
  print ("Bar number", bar)
end
  

Composed

The Composed Script is called when Noatikl composes a note. Only available to voice objects! Use this to emit MIDI CC events and what have you!

Advanced users might also be interested in reading about using this script with embedded calls to noatikl_Trigger_EmitListeningNote, to help build hyperinstruments.

function nt_trigger_composed(noteon, channel, pitch, velocity)
  print ("Composed", noteon, channel, pitch, velocity)
end
  

MIDI In CC

The MIDI In CC Trigger Script is called whenever a MIDI CC event is received by the MIDI Input device.

function nt_trigger_midiin_cc(channel, cc, value)
  if (cc == 1)
  then
    print ("MIDI In CC", channel, cc, value)
  end
end
  

NOTE on Omni: Noatikl delivers all MIDI CC events to this trigger from all MIDI channels, even if this trigger is a voice trigger script with a voice targeting a different MIDI channel. This is known as Omni behaviour. If you want your voice trigger to respond only if the supplied MIDI CC is from the same channel as your voice, use script like this:

function nt_trigger_midiin_cc(channel, cc, value)
  if (channel == noatikl_Trigger_GetMidiChannel())
  then
    -- Matches our voice channel!
    print ("MIDI In CC", channel, cc, value)

    if (cc == 1)
    then
      noatikl_Trigger_Parameter_Set("Patch", value)
    end
  end
end
  

MIDI In Note

The MIDI In Note Trigger Script is called whenever a MIDI Note On or Off event is received by the MIDI Input device. See the Noatikl hyperinstrument guide for a detailed discussion.

function nt_trigger_midiin_note(noteon, channel, pitch, velocity)
  print ("note ", noteon, channel, pitch, velocity)
end
  

NOTE on Omni: Noatikl delivers all MIDI Note events to this trigger from all MIDI channels, even if this trigger is a voice trigger script with a voice targeting a different MIDI channel. This is known as Omni behaviour. If you want your voice trigger to respond only if the supplied MIDI Note is from the same channel as your voice, use script like this:

function nt_trigger_midiin_note(noteon, channel, pitch, velocity)
 if (channel == noatikl_Trigger_GetChannel())
  then
    print ("note ", noteon, channel, pitch, velocity)
  end
end
  

Stop

The Stop Trigger Script is called once at the end of the Piece, just as the Piece stops playing.

  function nt_trigger_stop()
    print ("Piece stop!")
  end
  

Tbe Script Editor Window

When you decide to edit a Trigger Script property, you are presented with a Script Editor window.

The text panels support the usual context-sensitive text editor menus and keyboard accelerators (allowing for fast copy and paste operations).

The Script Editor window allows you to edit trigger scripts associated with your object.

Script Editor Window

Test

Pressing this button will compile any Lua script that you type in the large text area at the top of the window, and display any results in the bottom panel. Use the Test to quickly check your script for obvious syntax errors!

Help

Pressing the Help button displays help on the Noatikl Scripting system!

Clear

Pressing the Clear button quickly erases the text in the top panel.

Default

Pressing the Default button will replace any text in the top panel, with a new, empty default trigger script appropriate to the Noatikl script property you are currently viewing.

OK

Pressing the OK button will save your changes. These are used by Noatikl it next starts playing.

Cancel

Pressing the Cancel button will discard your changes.

Test Results

Any test results are displayed in the Test Results area at the bottom.

Clear

Pressing the Clear button in the bottom area, quickly erases the text in the bottom panel.


Scripting Reference

To find out about all the available objects, parameters, and functions, you should refer to the complete Noatikl scripting reference.


Trigger Script Cookbook

A great way to start thinking about Noatikl trigger scripts, is to look at various real examples of how to do various interesting things with Noatikl trigger scripts!

Example: Change the scale to use depending on time of day

This is a script that you could use as a piece-level Bar trigger script.

  function nt_trigger_start()
    -- Noatikl script to get hour of day as 24-hour clock value
    -- ... and select scale accordingly!
    local lTime = tonumber(noatikl_GetDate("%H"))
    if ((lTime > 20) or (lTime <8))
    then
      noatikl_Trigger_Parameter_Set("Scale Rules", "early morning scale")
    else
      noatikl_Trigger_Parameter_Set("Scale Rules", "middle of day scale")
    end
  end
  

Example: randomly select a pattern to use for a voice

This is a voice-level Bar trigger script.

function nt_trigger_start()
  -- Get a random integer between 1 and 3 inclusive.
  local lValue = noatikl_GetRandomFromTo (1, 3)

  print ("lValue", lValue)

  local lPattern = ""
  if (lValue == 1)
  then
    lPattern = "<100 B 240 1>"
  elseif (lValue == 2)
  then
    lPattern = "<100 B 120 1 120 2>"
  else
    lPattern = "<100 B 60 1 60 2 60 3 60 4>"
  end

  noatikl_Trigger_Parameter_Set("Patterns", lPattern)
end

Example: script trigger that allows Noatikl trigger scripts to emit MIDI CC events, with an optional delay

This is a script that you could use as a piece-level Bar trigger script.

  function nt_trigger_bar(bar)

    -- Voice trigger...
    -- Apply a pan sweep through the bar from left to right,
    -- to show-off the use of noatikl_Trigger_EmitMidiCC.

    local lDuration = noatikl_Trigger_GetBarDuration()

    local lMidiChannel = noatikl_Trigger_GetChannel()
    local lDelay = 0
    local lCC = 10 -- Pan controller!
    local lValue = 0
    while lDelay <= lDuration do
      local lValue = (127 * lDelay) / lDuration
      -- Note that the "lDelay" is optional; we're using the in this specific
      -- demo, to get a sweep effect from start to end of the bar.
      noatikl_Trigger_EmitMidiCC(lMidiChannel, lCC, lValue, lDelay)
      lDelay = lDelay + 20
    end
  end

Example: piece bar trigger, that automatically adjusts the piece root every 10 bars

function nt_trigger_bar (bar)

  if ((bar % 10) == 0)
  then
    -- Every 10 bars, change the root at random,
    -- from all those available!
    local lRoots = {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"}
    local lIndex = noatikl_GetRandomFromTo(1,12)
    local lRoot = lRoots[lIndex]
    print ("Root", lRoot)
    noatikl_Trigger_Parameter_Set("Piece Roots", lRoot) 

    -- Un-comment the following line to set tempo at random, too,
    -- to a value related to the selected root!
    -- noatikl_Trigger_Parameter_Set("Tempo", 100 + lIndex * 5) 
  end
end

Example: piece start trigger, that automatically adjusts the tempo to suit the time of day

function nt_trigger_start()
  print("Piece!")

  -- Noatikl script to get hour of day as 24-hour clock value
  -- ... and adjust tempo accordingly!
  local lTime = tonumber(noatikl_GetDate("%H"))
  if ((lTime > 20) or (lTime <8))
  then
    print ("late night / early morning!")
    local lRandom = noatikl_GetRandomFromTo(0,50)
    noatikl_Trigger_Parameter_Set("Tempo", 50 + lRandom)
  else
    print ("middle of day!")
    local lRandom = noatikl_GetRandomFromTo(0,50)
    noatikl_Trigger_Parameter_Set("Tempo", 100 + lRandom)
  end
end

Example: voice start trigger, that automatically cycles the patch every time it starts playback

function nt_trigger_start()
  print("Voice!")

  local lPatch = noatikl_Trigger_Parameter_Get_AsNumber("Patch")
  lPatch = lPatch + 1
  if (lPatch > 100)
  then
    lPatch = 0
  end
  noatikl_Trigger_Parameter_Set("Patch", lPatch)
end

Example: voice trigger, that automatically changes patch every bar

function nt_trigger_bar(bar)
  print("Voice1 ", bar)
  local lPatch = noatikl_Trigger_Parameter_Get_AsNumber("Patch")
  lPatch = lPatch + 1
  if (lPatch > 100)
  then
    lPatch = 0
  end
  noatikl_Trigger_Parameter_Set("Patch", lPatch)
end

Example: bringing voices into the mix

In this example, imagine that you have a mutating drum Voice that you want to have muted at the start of the piece and come in with a bang at the start of bar 20. And you don't want the mutations to start until bar 21...

How would that work in the world of script?

Here is the Voice Start trigger:

function nt_trigger_start()
  -- When we start, disable mutation for this voice!
  -- And set mute, too!
  noatikl_Trigger_Parameter_Set("Mute", "Yes")
  noatikl_Trigger_Parameter_Set("Mutation Factor", 0)
end

Here is the Voice Bar trigger:

function nt_trigger_bar(bar)
  if (bar == 20)
  then
    -- At bar 20, unmute the voice!
    noatikl_Trigger_Parameter_Set("Mute", "No")
  end

  if (bar == 21)
  then
    -- At bar 21, adjust the mutation factor!
    noatikl_Trigger_Parameter_Set("Mutation Factor", 20)
  end
end 

The power of using scripts like this, is that:

  • The drums alway start on the bar specified.
  • They don't morph until they are audible.
  • The drum elements can now make staggered entry despite all bing on the same midi channel.

Example: Emit MIDI CC in response to composed note events

function nt_trigger_composed(noteon, channel, pitch, velocity)
  -- Keep track of last composed note using the global (for this voice)
  -- called GLastNote ...
  -- Note that the "pitch" parameter should be ignored when noteon is false.

  lMidiChannel = noatikl_Trigger_GetChannel()

  if (noteon)
  then
    if (GLastNote ~= nil)
    then
      noatikl_Trigger_EmitMidiCC(lMidiChannel, 11, GLastNote, 10)
    end

    GLastNote=pitch
    noatikl_Trigger_EmitMidiCC(lMidiChannel, 11, pitch, 0)
  else
    if (GLastNote ~= nil)
    then
      noatikl_Trigger_EmitMidiCC(lMidiChannel, 11, GLastNote, 10)
      GLastNote = nil
    end
  end
end

Noatikl Script Window (the Noatikl Script Console)

The Noatikl Script Window is used to create and run scripts to manipulate Noatikl editor windows; for example, to dynamically create random Noatikl compositions.

It is also used for displaying messages from print calls within your trigger scripts!

The text panels support the usual context-sensitive text editor menus and keyboard accelerators (allowing for fast copy and paste operations).

Script Console Window

Run Command!

Pressing this button will run any Lua script that you type in the large text area at the top of the window, and display any results in the bottom panel

An example you might like to try would be this:

print ("Hello world!")

History and Results

Any results are displayed in the History and Results area at the bottom.

This is where the output from any print statements in your scripts are displayed (including those within trigger scripts).

Help

Pressing the Help button displays help on the Noatikl Scripting system!

Clear

Pressing the Clear button quickly erases the bottom panel.

Console Script Cookbook

A great way to start thinking about Noatikl console scripting, is to look at various real examples of how to do various interesting things with Noatikl console scripting!

Example: the simplest possible start

print ("Hello world")

Example: open all Noatikl files in a sub-folder with a .txt extension, adjust some properties and re-save with .Noatikl file extension.

local lFileList = noatikl_FindFilePaths("myfolder1", "myfolder2")

local index = 0
while true do

  index = index + 1
  local lFilePath = lFileList[index];
  if (lFilePath == nil)
  then
    break
  end

  if (string.find(lFilePath, '.txt'))
  then
    local lWindow = noatikl_Window_OpenPath(lFilePath)

    -- Change some file properties
    noatikl_Window_Object_Parameter_Set(lWindow, "File", 1, "Author", "my company")
    noatikl_Window_Object_Parameter_Set(lWindow, "File", 1, "Midi Output Device", "?")
    noatikl_Window_Object_Parameter_Set(lWindow, "File", 1, "Midi Input Device", "?")
    noatikl_Window_Object_Parameter_Set(lWindow, "File", 1, "Midi Sync?", "No")

    -- Change some properties for every voice in the file...    
    local lCount = noatikl_Window_Object_GetCount(lWindow, 'Voice')
    
    local lIndex = 1
    while lIndex <= lCount do
    
      noatikl_Window_Object_Parameter_Set(lWindow, "Voice", lIndex, "Copyright", "Copyright my company")
    
      lIndex = lIndex + 1
    end

    local lSaveToPath = string.gsub(lFilePath, '.txt', '.noatikl')

    noatikl_Window_SaveToPath(lWindow, lSaveToPath)

    print ("Saved", lFilePath)

    noatikl_Window_Close(lWindow)
  end
end

print ('Done!')

See Also

© 2010 Intermorphic Ltd. All rights reserved.