yes. demo:

engine.name = 'TestSine'

local function draw_grid_connected()
   screen.clear()
   screen.move(10, 20)
   screen.text("grid connected")
   screen.update()
end

local function draw_grid_disconnected()
   screen.clear()
   screen.move(10, 20)
   screen.text("grid disconnected")
   screen.update()
end

function init()
   -- set our handler for grid add / remove
   grid.add = draw_grid_connected
   grid.remove = draw_grid_disconnected
end

function cleanup()
   -- it's nice to clean up
   grid.add = function() end
   grid.remove = function() end
end
3 Likes

dumb question of the day:

how would I go about making an LFO - or any number of LFOs? (to modulate various engine/synth params)

Would this need to be a feature already in an engine?

3 Likes

I have been thinking about this also. An idea I have is to assign various MIDI CCs to the parameters I want to modulate. Probably do this manually one time.

Then, in a script - using a system of column and/or row lengths and timings, similar to the way Meadowphysics, loom and others handle this – modulate the CC values.

I haven’t started on this script. Just an idea I had.

Not by a computer but surely using a metro to send a value = value +1 would work. You’d need to do an if value > n value = value -1 and
Vice Versa. The speed of the metro can be assigned to an encoder.

We should create a place for various little snippets of useful.

I have been thinking about this as well. R has some LFO modules, maybe you can just use one of those, with a metro to keep track of it’s value and update the param?

2 Likes

arbitrary control rate lfo should be pretty achievable using commands presented in the studies. metro and params. Google the lua math lib for sine shapes.

3 Likes

lfos controlled by Arc? :slight_smile:

1 Like

Ideally I’d want many different shapes :slight_smile:

(Dreaming of Batumi functionality)

Game on

7 Likes

Feeling rather stupid right now as this is so simple in other languages… is there a neat way in Lua to split a string into a table?

My specific issue right now is trying to split a string of numbers for example '123456' into a table of numbers like this: {1, 2, 3, 4, 5, 6}

function split_str(str)
   local tab = {}
   for i=1,string.len(str) do
      tab[i] = string.sub(str, i, i)
   end
   return tab
end

core libraries in lua are pretty minimal. but there is some string manipuation and fairly powerful pattern matching.

http://www.lua.org/manual/5.3/manual.html#6.4

i’d be interested in providing more string and collection utilities out of the box, whether by pulling in some stuff from luarocks or by collecting our own structured utility suite.

the problem with pulling in stuff (imho) is that there a number of ways to shoot yourself in the foot performance-wise by doing this. for example the nice list-comprehension lib in Penlight is unsuitable for soft-realtime use.

1 Like

thanks! i was being lazy thinking that there would be a function for it already!
My vote would be for utilities to be gathered on here - i haven’t hugely explored luarocks but having some recent frustrations with npm makes me err on the side of a more focused utility suite

Playing around right now and I notice Fugu gives me trouble at 19-20fps or faster. Look at the grid_redraw() function there (line 488), it seems to be calling grid:led() many many times.

Am I correct that calls to grid:led() take a roundtrip to libmonome and back?

(total shot in the dark guess) Maybe lots of grid:led() calls together are piling up in libmonome?

Curious if you notice issues at higher BPMs?

unless i’m misunderstanding, no - LED commands go one way, key events come the other way.

not literally. we don’t actually use individual led_set calls. all updates to led’s are with led_level_map. all changes to invididual leds are buffered, and only entire (dirty) quads are transmitted. (on grid:refresh()).

this is generally more efficient, but you can make a script that renders it totally inefficient; for example by doing grid:led() followed by grid:refresh() over and over, instead of using grid:refresh() sparingly once you are done building the LED state you want to see.

we could expose more of the libmonome API to lua if people want to use actual col and led commands. but then they have to know about the bandwidth tradeoffs inherent therein and choose the appropriate method.

(i’d like to move this conversation to GH or at least the scripting thread if we want to continue it.)

2 Likes

given matron (lua) is calling libmonome directly (so there is no OSC overhead) this seems pretty efficient as is. i think adding more libmonome API hooks to lua would be confusing and offer not much benefit.

2 Likes

I’ve been using this little script to give me a grid of program change triggers, which when working with other hardware gives me one-press change of programs/patterns across all the machines. It’s offensively under-utilizing Norns but it’s been surprisingly enjoyable to jam out with in the studio, or quickly get a fresh pattern on all the devices to work something out.

I feel a bit icky about how I’ve mapped 0-127 across the rows and columns of the grid and I feel like there is a more elegant way than how I’m doing it here:

--
-- launchctrl
--
-- provides grid launching
-- of midi program changes

local g = grid.connect();
g:all(0);
g:refresh();

local mo = midi.connect()
local program = 0
local program_change_channel = 7

-- Receive program change event and highlight related grid button
mo.event = function(data)
  d = midi.to_msg(data)
  if d.type == "program_change" then
    local row = math.floor(d.val/16)
    local column = (d.val - row*16)
    row = row + 1
    column = column + 1
    g:all(0)
    g:led(column, row, 8)
    g:refresh()
  end
end

-- Send program change event
g.key = function(x,y,z)
  if z == 0 then
    g:led(x, y, 3)
    local pattern = (y-1) * 16 + (x-1)
    mo:program_change(pattern, program_change_channel)
    g:refresh()
  end
end

any suggestions?

1 Like

You could use util.linlin() as a way of making the mapping between the 1-16 of the grid rows and columns and the 0-127 of midi look a little cleaner. The math that a remapping function is doing is basically the same but I definitely find it easier to read when I come back to it.

1 Like

@markeats had an amazing looking sample player in development (saw a demo on Instagram some time back). Any updates on this?

4 Likes

I put it on hold while the dust settled on norns 2.0 (…sorry)
Picked it up again recently and hope to put out a beta in the coming weeks.

14 Likes

This question might be very general, but is there a way to declare x.y boundaries on the grid for certain keypress events. Example: you can only do a certain commandon the top half of the grid, and a different command on the bottom half.