Link search Menu Expand Document

engine

Register a SuperCollider engine

control

Syntax Description
engine.name Using the format engine.name = <engine_name>, assigning this variable at the start of a script loads a SuperCollider engine as part of a script’s initialization
engine.COMMAND_NAME(args) After an engine is loaded, its SuperCollider commands are made executable to the Lua layer via engine.COMMAND_NAME(args) : function
engine.load(engine_name, callback) Manually load an engine (via string engine_name) and perform a callback function : function
Not necessary – just use engine.name!

query

Syntax Description
engine.list_commands() Print the commands added by the loaded engine  : function
tab.print(engine.names) Print the names of all the locally installed engines : function

description

The engine module manages the interactions between SuperCollider (generally speaking, the sound-making side of norns) and the Lua layer (where commands and performance interfaces are scripted).

The norns core software stack comes equipped with a few basic engines, which do not require any additional user management:

  • PolyPerc: pulse wave with percussive envelopes which are triggered on updates to the synth’s frequency (source code)

  • PolySub: a subtractive polysynth engine (source code)

  • SimplePassThru: an engine which passes incoming audio through, with control over amplitude (source code)

  • TestSine: a single, mono sinewave (source code)

  • None: a special-case engine which has no functions and is called when a script is cleared or a clean-slate is desired (source code)

For engine development overview and best practices, we encourage spending time with our engine-specific studies:

  • rude mechanicals // introduction to building norns engines with SuperCollider and Lua
  • skilled labor // extended study of norns engine development: polyphony and realtime parameter changes
  • transit authority // deep-dive into audio busses, FX, and polls (to communicate from SuperCollider to Lua)

Custom SuperCollider engine files live inside of a project’s lib folder, as either a single CroneEngine file or as CroneEngine / Class File pair. Engines can be distributed as part of a larger script or as a standalone project, but note that having multiple copies of the engine’s SuperCollider file will cause a DUPLICATE ENGINES error.

basic example

-- basic engine reference example

engine.name = 'PolyPerc' -- loads engine and executes script's init()

s = require 'sequins'

function init()
  print(" ")
  print("available engines:")
  tab.print(engine.names)
  print(" ")
  print("loaded engine:")
  print(engine.name)
  print(" ")
  print("commands for "..engine.name)
  engine.list_commands()

  pan_vals = s{-1,1,0.5,-0.5,0}
  pw_vals = s{0.25,0.9,0.1,0.75,0.3,0.5, 0.8}
  cutoff_vals = s{3000,600,1200,1530,6666}
  base_hz = 300
  hz_divs = s{1,1.5,0.5,1/3,2,0.25}

  clock.run(
    function()
      while true do
        clock.sync(1)
        engine.pan(pan_vals())
        engine.pw(pw_vals())
        engine.cutoff(cutoff_vals())
        engine.release(math.random(3,300)/100)
        engine.hz(base_hz * hz_divs())
      end
    end
  )
end

If one is feeling adventurous, you could embrace live-coding gestures by executing these commands through the maiden REPL:

>> load_callback = function() print("engine has been loaded!") end
>> engine.load("PolyPerc", load_callback)
>> engine.release(2)
>> engine.hz(300)
>> engine.pan(-1); engine.hz(400)
>> engine.cutoff(4500); engine.pan(0); engine.hz(150)
>> engine.load("None", function() print("clearing engine") end)