norns

norns is many sound instruments.

View the Project on GitHub monome/norns

lua programming

see norns/doc for API reference.

a menu system manages the execution of a single user script, which is selected through the menu interface. on startup the last-selected user script will be run, and the interface will be in “script” mode (as opposed to menu mode). see Addendum 1 for the details of script startup.

audio

audio processing is performed by audio engines. only one engine is loaded at a time. each engine presents an arbitrary collection of ‘commands’. each command consists of a name and zero or more arguments. each argument can be one of three types: int, float, or string. thus, engine commands map directly to a subset of OSC messages.

engine control functions:

additionally, specific engine command functions are created dynamically on reception of a command list from the audio server, and placed in the table norns.engine. so for example, the TestSine engine reports just two commands, each of which takes a single float argument:

1: hz (f)
2: amp (f)

on receiving this report, norns creates two functions whose definitions would look like this:

norns.engine.hz = function(arg1) 
  send_command(1, arg1)
end
norns.engine.amp = function(arg1) 
  send_command(2, arg1)
end

a shortcut is set on startup: e = norns.engine; so the user then can then simply use e.hz(440) and e.amp(0.5) in this example.

engine callbacks:

note that commands are reported automatically on engine load. so for the time being, the report.commands callback is the easiest method for delaying lua code execution until an engine is finished loading.

high level management

user scripts specify an engine to load with a single line, ie:

engine = TestSine

the menu system manages the loading of the engine, and runs the user function init once the engine loads.

Polls

polls provide a way for matron to query crone. for example, getting audio input and output levels for VU display.

TODO

I/O devices

monome

grid devices can be hotplugged. connected devices are available as tables in norns.grid.devices and norns.arc.devices. each table includes information about the device as well as methods to control its output.

for device hotplug and gesture input, the following callbacks can be defined:

the menu system manages grid functions to simplify user scripts: gridkey() is the function which can be redefined in a user script for managing grid input. gridredraw() is the grid drawing function.connect/disconnect awareness can likewise be redefined by the user script.

HID

HID input devices work similarly to monome devices. however, the event structure is necessarily more complex.

callbacks:

TODO?: HID output

MIDI

TODO

timers

matron maintains a fixed number of high-resolution timers that can be used from lua:

graphics

user script screen drawing is managed in the user function redraw(). this function is called when the menu enters script mode, and can also be called arbitrarily within the user script (for example, after a key press which changes state somehow).

there are numerous high-level drawing functions, which are a subset of the underlying cairo library (see https://www.cairographics.org). for example:

s.clear()
s.move(0,20)
s.text("hello!")
s.update()

this clears the screen, moves the current position to (0,20) and then prints “hello!”. the final command s.update() flips the buffer to the screen, making the prior commands visible.

full drawing reference in the API.

Addendum 1: Startup Process

a quick outline describing how matron starts

  1. after some initialization matron will wait for a ready OSC message from crone (the dsp, ie supercollider), pinging crone with o_ready()
  2. once received, w_init() (weaver.c) first executes config.lua to get paths set up
  3. then norns.lua is loaded via a require
  4. norns.lua sets up a bunch of definitions that will be redefined later
  5. matron resumes initializing and then runs w_startup() which calls the startup function defined earlier in norns.lua– which runs startup.lua
  6. startup.lua loads all of the other modules, some shortcuts, and then calls norns.state.resume() which loads the last running script (which is stored in state.lua)