Norns: studies

norns

#104

You’re welcome! Let me know if anything isn’t clear.


#105

https://monome.org/docs/norns/study-5/

polls. OSC. files.

vid: metallophone to mic, mic to inputs. pitch detect on inputs with key press, add oscillator with detected pitch. add up to 16 pitches, reset with other key. touchOSC running on phone, controlling filter and noise in x-y configuration.


#106

this is stunning. wow. norns is growing.


#107

Thanks much for the file operations, this is what I have been waiting for! One question regarding this example:

function print_file(filepath)
  local f=io.open(filepath,"r")
  if f==nil then
    print("file not found: "..filepath)
  else
    f:close()
    for line in io.lines(filepath) do
      -- this is where you would do something useful!
      -- but for now we'll just print each line
      print(line)
    end
  end
end

It is confusing to me why f:close() is called before the for…in…do operation using io.lines(filepath). I would have expected that the file must be open in order to execute the for…in…do operation using io.lines(filepath), and that f:close() is called after that.

Please, can you help me understand? Still a Lua (and programming) novice…thanks much in advance!


#108

@wolfgangschaltung

I believe io.lines only checks the amount of lines in a file, regardless of whether or not it is open. If this is the case, it wouldn’t matter if f:close() came before or after, but it’s good practice to close files as early as possible.


#109

It seems strange that a file handle doesn’t need to be open to count the lines in a file. But yeah, it seems like the io class has some methods that don’t require a file handle, only a path to a file.


#111

Thanks, but this is even more confusing to me, as the for…in…do does not count the lines, but prints each line.

Why does the file need to be opened in the first place if its content can be printed even after it is closed?


#112

Looking to the docs for io.lines, it seems like the iterator that is returned manages the file handle internally, closing it once the iteration has ended. I believe the print_file function is calling io.open just to verify if the file exists beforehand, as lines will throw an error if the file doesn’t exist. Checking for f==nil seems a bit easier than handling the error (I’m new to Lua but from what I can tell error handling looks pretty weird, correct me if I’m wrong).


#113

I have the same issue; external midi sync doesnt seem to work (tried Arturia Keystep and Squarp Pyramid)


#114

using the mallet to stop the feedback bloom was unexpectedly (and inordinately) amusing

excellent performance @tehn !


#116

Fun hack. I found a Kindle Fire (gen 5) tablet that I forgot about. It’s some weird fake Android without Google Play app store but…TouchOSC is in the Amazon App Store (is that even the same thing?).

The tablet cost $40 new. Kinda rad as a wireless general purpose controller.


#117

Have you checked if it works? If it does it would be AWESOME.


#118

try it, you’ll like it


#119

Update for future readers: I didn’t note it below, but I was on the 181002 firmware. The relevant syntax was changed with that firmware. @tehn explains in detail here: https://llllllll.co/t/norns-update-181002/16662/2

———

@tehn,

Looks like there’s a code example typo in study part 3, in the parameters section:

Current:

params:add_number(“tempo”,20,240,88)

Should be?

params:add_number(“tempo”,”tempo”,20,240,88)


#120

thanks for the mention. i’m mostly done updating the study… will get it posted in a bit!


#121

So I finally updated to update 181002 to learn the new way to access grid keys, and stumbled over this:

According to study 4 “physical” this is how to make use of grid key presses:
g.event = function(x,y,z)

But according to the new version of “awake” in update 181002, this is how to make use of grid key presses:
function g.event(x, y, z)

Both seem to work. Is there any difference between the 2, or can both be used interchangably? From my real bloody novice user experience, this format
function g.event(x, y, z)
blends in better with how functions have been introduced & used in previous studies.

On a slightly related note, there seems to be a bug in study 4 “physical” in the code for the “complete step sequencer”. When I enter the code as described…

engine.name = 'PolyPerc'
steps = {}
position = 1
counter = metro.alloc() 
counter.time = 0.1 
counter.count = -1
counter.callback = count

function init()
  for i=1,16 do 
    table.insert(steps,1)
  end
  grid_redraw()
  counter:start()
end

g = grid.connect()

g.event = function(x,y,z)
  if z == 1 then
    steps[x] = y
    grid_redraw()
  end 
end

function grid_redraw() 
  g.all(0)
  for i=1,16 do
    g.led(i,steps[i],i==position and 15 or 4)
  end
  g.refresh()
end

function count()
  position = (position % 16) + 1 
  engine.hz(steps[position]*100) 
  grid_redraw()
end

…nothing happens, i.e. the sequencer does not run.

After experimenting I found that
counter.callback = count
needs to be inside
function init()
in order to make the sequencer run.

Is there a way to explain to a novice user why only this counter.callback needs to be in the function init(), but not the other counter.xxx expressions?

Thanks much in advance!


#122

these statements mean the same thing in lua. (lua functions are first order objects, but the second form is provided as syntactic sugar - it looks more natural if you’re coming from c-like languages.)

just a guess, but i think the problem is simply that you say counter.callback = count before you define count. so you are really saying counter.callback = nil.

whereas init() is executed later by a callback (when engine is done loading), so the count function has already been defined there.

my guess is it would also work if you define count and then assign it to counter.callback, even without doing the assignment in init.


#123

i’ll fix the study, thanks for the heads up


#124

Strange error with renaming @tehn s awake script in 181002

STEPS

In maiden…

  • open tehn > awake and copy the lua script to clipboard
  • create a new empty script ("untitled.lua" is created)
  • paste clipboard content in “untitled.lua
  • press play (awake runs flawlessly)
  • rename “untitled.lua” to “new.lua
  • press play

RESULT

  • awake plays
  • REPL shows this error message over and over:

stack traceback:
/home/we/dust/scripts/jhh/untitled.lua:123: in field 'on_step'
/home/we/dust/lib/lua/beatclock.lua:66: in function 'beatclock.advance_step'
/home/we/dust/lib/lua/beatclock.lua:72: in function 'beatclock.tick'
/home/we/dust/lib/lua/beatclock.lua:22: in field 'callback'
/home/we/norns/lua/metro.lua:155: in function </home/we/norns/lua/metro.lua:152>
lua:
/home/we/dust/scripts/jhh/untitled.lua:123: attempt to call a nil value (global 'gridredraw')

Moving function step() after function gridredraw() doesn’t help. And the odd thing is, this behavior only occurs after renaming.

FURTHER RESULTS

  • although the file “new.lua” is shown in maiden’s script list, Cyberduck (after a refresh) still shows “untitled.lua”, and after a refresh in maiden, maiden also shows “untitled.lua” (and “new.lua” is gone)

NOTES

  • The new awake script still uses g:refresh() instead of g.refresh(), but the behavior mentioned above can also occur with g.refresh()

Is this a bug or am I missing something? Thanks in advance!


#125

g:refresh() is incorrect. it should be g.refresh(). i’ll fix this in the repo.

the renaming issue sounds like a maiden bug. i’ll try to reproduce it.

the repeated error is confusing, however. try to load a different script, then come back to your work in progress.