Norns/SuperCollider/Lua/Maiden

I found a small tutorial and followed all the steps from:

monome norns, supercollider and lua — part 1

  1. connected via ssh to norns
  2. used visual studio code editor
  3. created a folder and file
  4. copied the SC code
  5. compiled the code
  6. restarted norns
  7. Opened Maiden editor
  8. created folder + file
  9. copied Lua script into the file
  10. ran the script

I was able to hear now some ‘haunting noises’, but in norns it said “init error” and I couldn’t toggle from no play to play. And the script I heard in Maiden running was identical with what I heard in the SC IDE when I just pasted the code in there.

Any thoughts?

SC code for SC IDE:

// Copied from https://composerprogrammer.com/teaching/supercollider/sctutorial/1.1%20Getting%20Started.html
({
  var n = 11; 	//try changing me to 34, or 3, and then re-running... 

  Resonz.ar( 
    Mix.fill(n,{ 
      var freq=rrand(50,560.3); 
      var numcps= rrand(2,20); 
      Pan2.ar(Gendy1.ar(6.rand,6.rand,1.0.rand,1.0.rand,freq ,freq, 1.0.rand, 1.0.rand, numcps, SinOsc.kr(exprand(0.02,0.2), 0, numcps/2, numcps/2), 0.5/(n.sqrt)), 1.0.rand2) 
		}),
    MouseX.kr(100,2000), 
    MouseY.kr(0.01,1.0)
  ); 
}.play)

Code for Norns:

Engine_GendyTutorial : CroneEngine {
  var rez_x=100, rez_y=0.5, fill=50;
  var <synth;
	
  *new { arg context, doneCallback;
    ^super.new(context, doneCallback);
  }

  alloc {
    SynthDef(\GendyTutorial, {|inL, inR, out, rez_x=100, rez_y=0.5|
      var sound = {
        Resonz.ar( 
          Mix.fill(fill, { 
            var freq=rrand(50,560.3); 
            var numcps= rrand(2,20);
            Pan2.ar(Gendy1.ar(6.rand,6.rand,1.0.rand,1.0.rand,freq ,freq, 1.0.rand, 1.0.rand, numcps, SinOsc.kr(exprand(0.02,0.2), 0, numcps/2, numcps/2), 0.5/(fill.sqrt)), 1.0.rand2) 
          }),
          rez_x, 
          rez_y
        ); 
      };
      
      Out.ar(out, sound);
    }).add;

    context.server.sync;

    synth = Synth.new(\GendyTutorial, [
      \inL, context.in_b[0].index,			
      \inR, context.in_b[1].index,
      \out, context.out_b.index,
      \rez_x, 100,
      \rez_y, 0.5],
    context.xg);

    this.addCommand("x", "i", {|msg|
      synth.set(\rez_x, msg[1]);
    });
    
    this.addCommand("y", "f", {|msg|
      synth.set(\rez_y, msg[1]);
    }); 
  }

  free {
    synth.free;
  }
}

Lua code in Maiden editor:

engine.name = "GendyTutorial"

function init()
  -- map our supercollider controls to norns parameters
  params:add_control("x", controlspec.new(100,2000,"lin",0,0,""))
  params:set_action("x", function(x) engine.x(x) end)
  
  params:add_control("y", controlspec.new(0.01, 1.0,"lin",0,0,""))
  params:set_action("y", function(x) engine.y(x) end)
  
  -- set some initial values
  mix.output(0.5)
  engine.x(300)
  engine.y(0.5)
  engine.stopAll()
end

function enc(n,delta)
  -- map our encoder changes to parameters
  if n == 1 then
    mix:delta("output", delta)
  elseif n == 2 then
    params:delta("x", delta)
  elseif n == 3 then
    params:delta("y", delta)
  end
end

Maiden has a REPL where errors will show up.

If you have an init error, it should have some info for you in the REPL

1 Like

matron

sc

a CroneAudioContext

WARNING: SynthDef GendyTutorial too big for sending. Retrying via synthdef file

[ CroneEngine adding command, x, i, a Function ]

[ CroneEngine adding command, y, f, a Function ]


– crone: done loading engine, starting reports


engine: an Engine_GendyTutorial

command entry: [ 0, x, i ]

command entry: [ 1, y, f ]

cpu_peak

cpu_avg

amp_in_l

amp_in_r

amp_out_l

amp_out_r

pitch_in_l

pitch_in_r

norns.script.load(“deafsqrL/gendy-tutorial.lua”)

script load: /home/we/dust/deafsqrL/gendy-tutorial.lua

cleanup

script clear

pset >> write: /home/we/dust/data/system.pset

script run

loading engine: GendyTutorial

reading PMAP /home/we/dust/data/deafsqrL/gendy-tutorial/gendy-tutorial.pmap

m.read: /home/we/dust/data/deafsqrL/gendy-tutorial/gendy-tutorial.pmap not read.

Engine.register_commands; count: 2

___ engine commands ___

x i

y f

___ polls ___

amp_in_l

amp_in_r

amp_out_l

amp_out_r

cpu_avg

cpu_peak

pitch_in_l

pitch_in_r

script init

SCRIPT ERROR: init

/home/we/dust/deafsqrL/gendy-tutorial.lua:12: attempt to call a nil value (field ‘output’)

stack traceback:

/home/we/norns/lua/core/norns.lua:136: in field ‘output’

/home/we/dust/deafsqrL/gendy-tutorial.lua:12: in global ‘init’

/home/we/norns/lua/core/script.lua:105: in function ‘core/script.init’

[C]: in function ‘xpcall’

/home/we/norns/lua/core/norns.lua:137: in field ‘try’

/home/we/norns/lua/core/engine.lua:91: in function </home/we/norns/lua/core/engine.lua:89>

the error is in the lua script (and i guess in the tutorial - i don’t know who wrote this.)

(the on-screen message INIT ERROR indicates that lua encountered an error while running your script’s init function.)

the stack trace in the lua REPL makes this more explicit:

/home/we/dust/deafsqrL/gendy-tutorial.lua:12: attempt to call a nil value (field ‘output’)

you want mix:set("output", value) , not mix.output(value)

(mix is an instance of ParamSet)

(there could be other errors but that is the one that is halting the script right now.)

like that:

– set some initial values
mix:set(“output”, 0.5)
engine.x(300)
engine.y(0.5)
engine.stopAll()
end

stopAll does not seem to be a command registered by the engine class, so i’m guessing that will also throw an error. (not sure what the author’s intention was.)

other than that, seems plausible.

i recommend contacting the author of the tutorial and asking them to fix the code or help you fix it.

you might also want to look at the official studies published by monome, which are better maintained, and which are intended to progressively build an understanding of the critical APIs.

1 Like

Good idea!
Honestly, I just copied mechanically without even knowing what I am doing :slight_smile:

But it worked somehow. Will better go to the official tutorials for now. At least I had some success. LOL

I appreciate your help!

1 Like

yeah its definitely satisfying that you could paste some SC stuff and get new sounds!

I tried to research why norns is using Lua for scripting over SuperCollider when in fact it has anyway SC on it. Then I found that article and just tried the author’s code.

Norns’s Lua is primarily for all the non-sound aspects of the device: the screen, the knobs, the buttons, storing data, reading files, etc. SuperCollider does all the actual sound work.

(Of course, if you want the sound to change in a particular way due to a knob turn or other Lua-side event, then you need Lua to know how to talk to SC, so in that sense Lua does affect the sound. But thinking of the division this way is a good place to start)

1 Like

Ahh, that makes totally sense. Have not thought about that aspect at all.
Thank you!

1 Like