Norns: scripting

norns

#78

What’s the best way of sending midi note on and note off messages when using metro? I’m trying to adapt the 16sliders sequencer to send note on an note off messages but if I put both messages in the callback the sound is too short. Is there any way to specify functions which happen at the beginning of the metro callback and at the end? I’m probably missing something simple here.


#79

Is there a way to save the contents of a table (array) to a file to be recalled later? I know it’s implemented in the parameter section, but I have a sequence that I’d like to save for recall later. How can I write the contents to file?


#80

These?

  Log.post (txt)    post message to log, timestamped 
  Log.get (index)    get log message at index, with timestamp (seconds old)

Although it’s unclear if you can “get” an index


#81

@carltesta, Ive not looked at this explicitly , but just some thoughts

so you want to view the metro as something that gives you a ‘timeline’,of an interval you specified when you created it (e.g. 100ms , 1s , whatever) , so this gives you a ‘resolution’
so basically you should independently count(*) to decide when to send the note off
(for a simple case that might be as easy as 1, but for a complex sequencer you might track individual notes on/off)

(*) count in a sequencer = position in the sequence.

Im not sure if parameters are going to cover ‘complex types’ , like a table which is a set of values.
but no worries, Lua has complete file io that you can use see here
note: file io is not to be done in a high priority thread, but i guess for matron this is a non-issue since SC is doing all the DSP, but still be careful of writing large files.


#82

i’m going to cover file saving (for non-parameter, likely table types) in a later study. in the meantime check out any basic lua file io (as @TheTechnobear suggests)

in general googling anything related to lua will work on norns!


#83

Not sure if this is a bug (for the dev thread) or what.

From Maiden - I created a new script and forgot to add “.lua” at the end. From there I could not run script or do anything else - including rename the file

So i then needed to jump over to my FTP app (Transmit) and rename the file.


#84

I can’t seem to find a way to consistently create a spacing of a single pixel when editing the screen. I’m working on a base-4 number system along the lines of the image I’ve attached but something like this leads to an issue I’ve been trying to solve for hours:

for n=1,4 do
screen.line_rel(0,-1)
screen.move_rel(2,0)

This results in single pixels with a gap of two pixels, but changing screen.mov to (1,0) results in a solid line.

Any help would be appreciated!


#85

@tyler we’ve done a big set of fixes with screen drawing which will be included in this friday’s update. if you want to get a head start, connect to norns via screen/ssh and cd norns; git pull while connected to a network with internet.


#86

@tehn the git pull was successful, but I can’t seem to find a list of changes. Since I assume the changelog will be included in Friday’s update, can you share what changes were made with screen drawing?

(or point me the right direction if I’m missing a log in the git pull somewhere…)


#87


i think this is probably the issue you are seeing (now fixed)


#88

Is there a good way to remind scripters that using # or // for comments in a lua file will make things just not work? Seems like these comments crash something.

(for reference) lua comments start with --


#89

not sure what you’re thinking of (a warning in maiden?) but it’s the very first bit of instruction in the initial norns study. also, presumably if you are scripting you will want to be familiar with conventions… similar problems arise in most languages if the syntax is wrong.


#90

Looks the screen fixes did the trick! I’ve run into a problem with screen.pixel though.
in function mod() the first two if statements produce the result I want (1 pixel then 1 pixel of space x times), but the subsequent if statements produce a solid line despite the coding appearing to be identical.

-- base-4 numbering system
-- vertically compact (7x3)   
-- 
-- example below
--
-- ___   ___   ___   ___
-- 1      2     3      4 
-- ,__,__,__,__,__,__,__,
-- b  8  12 16 20 2b 28
-- ___   ___   ___   ___
-- 32    64    128    256

engine.name = "TestSine"

function init()
  engine.amp(0)
  b = 4                                         -- base. in this case, base-4
  val = 3                                       -- value to be interpretted
  x = 0                                         -- x for screen values
  y = 0                                         -- y for screen values
end

function redraw()
  screen.clear()
  screen.level(7)
  screen.aa(0)
  screen.move(64,32)
  screen.text_center(val)
  screen.move(0,0)
  mod()
  screen.stroke()
  screen.update()
end

function mod()
  if val / b <= 1 and val % b > 0 then        -- val = 1,2,3...(b-1)
    for n=0,(val % b-1) do                    -- row 1
      screen.pixel(x+n*2,y)
    end
  elseif val / b == 1 and val % b == 0 then   -- val = b
    for n=0,b-1 do                            -- row 1
      screen.pixel(x+n*2,y)
    end
  elseif val / b >= 1 and val % b > 0 then    -- val = more than b, but not a multiple of b
    for n=0,(val % b-1) do                    -- row 1
      screen.pixel(x+n*2,y)
      print("n:"..n*2+x)
    end
    screen.pixel(x,y+1)                       -- row 2
    screen.move(x,y+1)
    screen.line_rel(val/b-1,0)
  elseif val / b > 1 and val % b == 0 then    -- val = multiples of b
    for n=0,b-1 do
      screen.pixel(x+n*2,y)
      print("n:"..n*2+x)
    end
    screen.pixel(x,y+1)                       -- row 2
    screen.move(x,y+1)
    screen.line_rel(round(val/b-2,0),0)
  end
end

function round(num, numDecimalPlaces)
  local mult = 10^(numDecimalPlaces or 0)
  return math.floor(num * mult + 0.5) / mult
end

function enc(n,d)
  if n == 2 then
    val = val + d
    print("val:"..val)
  elseif n == 3 then
    y = y + d
    print("y:"..y)
  end
  redraw()
end

function key(n,z)
  if n == 3 and z == 1 then
    x = x + z
    print("x:"..x)
  elseif n == 2 and z == 1 then
    x = x + (z * -1)
  end
  redraw()
end

merging a separate comment

@okyeron: I think something could easily be added to the maiden editor, there’s already a red [ X ] the appears on lines with simple syntax errors that could work well as a reminder.


#92

screen.pixel() does indeed seem… quirky.
You can reliably use screen.rect(10, 10, 1, 1) followed by screen.fill()


#93

Perhaps a warning in maiden would be helpful. Or perhaps an error being thrown somewhere.

In my case I had edited one of the norns lua files (not dust scripts) and this apparently crashed everything (or rendered things unusable) without throwing any errors that I could find, so it took me awhile to figure out what was broken.

But yeah - totally a stupid mistake on my part.


#94

The lua code which is part matron that provides the menu system and device handling isn’t normally exposed in maiden - only content in dust. I’m guessing this on an rpi?


#95

Yes that is correct. (there’s a couple battery related lines in menu.lua that help to have commented out or deleted)

FWIW - I’ve also had this cause issues when adding # or // comments in maiden as well.


#96

The syntax hilighting / checking which happens in maiden is done directly in the editor, it does not have access to the full lua parser.

The # character is actually a unary operator in lua which returns the size/length of values like strings and tables. The // lexeme is a mathematical operator which provides floor division. Given that both are part of the language (and not comment characters) I’m not surprised that the basic syntax checking didn’t flag them.

In the off chance that folks with a norns are concerned about editing stuff in maiden might break something - don’t be. Nothing critical to the device can be modified via maiden under normal circumstances.


#98

I am actually creating short scripts in order to wrap my head about basic LUA coding in Maiden (SC will comes later) and I would need a bit of help. Though I don’t know if this thread is the right place for noobish questions (if not such a place would be really useful, maybe somewhere in Github?).

I am trying to make a basic sequencer, the 8 steps are represented by “grey” circles, actual position is indicated by a counter and a “white” circle. My problem is that the last circle is white from the start and never turn grey.

    function init()
      Nsteps = 8
      position = 1
      counter = metro.alloc(count, 0.5, -1)
      counter:start()
    end

    function count()
      position = (position % Nsteps) +1 
      redraw()
    end
      
    function redraw()
      screen.clear()
      screen.aa(0)
      screen.level(15)
      screen.move(0,10)
      screen.text(position)
      for i=1, Nsteps do
          screen.stroke()
          screen.level(1)
        if i == position then
          screen.level(15)
        end
        screen.circle(14 *i, 30, 2)
      end
      screen.update()
    end

By the way, why does syntax hilighting not displayed in my post?


#99

use ``` to block code instead of four spaces and you’ll get bit of highlighting