Norns: scripting

norns

#37

This sounds like an easy problem to solve, but I am having a bit of trouble.

Is there an easy way to make an int wrap around a range in lua? For instance, I want enc1 to increment/decrement a value, wrapping at its upper and lower bounds.
i.e. in a range of 1 - 8, 8 + 1 would be 1.


#38

modulo (%) is your friend.

for example: 9 % 8 = 1


#39

thanks! I realized now that this was mentioned in the first study!! :drooling_face:

edit: @ppqq, using my previous example of a range of 1-8. modulo seems to work perfectly for counting up, but when I count down I get some strangeness. crossing 0 seems to jump to 3 instead of the expected 8.


#40

Mod of negative is confusing, search it if you like confusion.

Id just use a while loop

Thumbtyping …

while x > 8 do x = x - 8 end
while x < 1 do x = x + 8 end

#41

bless this perfectly valid use of a norns.


#42

just add the range when you’re counting down before you apply modulo. also you have to add a -1 correction and then add 1 after to shift it to 1…8 range instead of 0…7 (lua being 1-based is really… inconvenient):

increment: x = (x + 1 - 1) % 8 + 1
decrement: x = (x + 8 - 1 - 1) % 8 + 1

i’m showing full calculation to make it clear what’s happening but you can of course collapse it to:

x = x % 8 + 1
x = (x + 6) % 8 + 1


#43

That worked like a charm! Thanks everyone!


#44

Not really understanding some nut-and-bolts stuff… not sure if it’s lua or just the way the scripting engine works here.

FWIW (as background) - I can muddle my way thru scripting with PHP, python, etc and coding basic stuff with Arduino

Where do functions like key(n,z) or enc(n,d) or something like gridkey(x,y,s) get executed or called? There’s not like a main loop here like with arduino, is there?


#45

I’m trying to wrap my head around the metro class. Any examples of executing a function using metro?emphasized text


#46

matron does indeed have a main loop which is consuming events that come in via timers and other low level glue for monome devices, midi, hid devices, etc. The C level event handlers in turn execute callbacks defined in Lua.

Main loop:

…and an example of one of the many functions which handles a C-level event by calling a function in Lua:


#47

As far as I understand, the script itself is the main loop. I think that function init() can start a loop if need be.

The encoder and key functions are always running as far as I know. I think osc.event functions can be placed anywhere. Or maybe within the init() function.


#48

soon after I posted above - I found the “norns” section in the docs - which is where those globals where hiding.

I’ve got osc events coming in ok - I just need to figure out how to make those be interpreted in the same way that grid events are (to emulate grid from TouchOSC).


#49

to close the loop here (into the lua domain)

the above calls the lua function

norns.monome.add

which usually is found in the ‘appropriate’ lua class e.g. grid.lua
(its also seems to be in norns.lua, but im not sure why)


#50

Anyone have any examples of using a poll to get info from a SuperCollider engine into a LUA script?


#51

i would love to see this one too. I think doing a random jukebox is a great way to understand tables, strings etc…
share possibly?

thank you


#52

Trying to send some midi back out (echo) when a note is received.

local midi_data = {144, note, velocity}
Midi:send(midi_data)

Error: lua: /home/we/dust/scripts/okyeron/hello_gong_osc.lua:107: attempt to index a nil value (global ‘Midi’)

I don’t understand where a nil value is happening. Any pointers?

EDIT: I’m apparently doing something stupid, but haven’t figure out what just yet :stuck_out_tongue:


#53

Yes, would be happy to! I had big plans to add extra bells and whistles, but I think I need more time to absorb all the info from the 2nd study. I’ll share what I have later tonight or tomorrow.


#54

OK - I got myself working with midi.send(dev,data) I had to define a variable for the device in midi.add(dev) and include that in my midi.send (the nil value was because I wasn’t picking up a value for dev)

Question: Where do these “status” codes for midi events come from?

norns.midi.event = function(id, data)
  status = data[1]
  data1 = data[2]
  data2 = data[3]
  if status == 144 then
    note_on(data1, data2)
  elseif status == 128 then
    note_off(data1)
  end

The earthsea script (snippet above) has a note-off code of 128, but my midi controller sends note-off as 144 with velocity 0 (same code as note-on)


#55

The numbers are from MIDI standard itself! A note_on with velocity = zero is often used as a note-off (I guess the code is easier?). Thus: note_on(pitch, 0) is the same as note_off(pitch).

You could change the line note_on(data1, data2) to:

if data2 == 0 then note_off(data1)
else note_on(data1, data2) end

Which should cover the case you mention


#56

Just a quick word of warning. If anyone comes across scripts in dust which assign values to anything in the norns module (like this snippet does) please flag it - as it is most likely the wrong way to do something. The norns module contains the low level glue where C-level hardware drivers are exposed to lua - changing things in the norns module will likely cause other scripts to break.

In the case of midi the proper way to define event handlers is shown in earthsea, specifically:

…looking at the dust repo I see that the hello_gong script is still using the (now internal) midi api (which we need to fix).