Norns: scripting

norns

#100

OK - this seems to work:

Changes - set position to 0 on init, so it counts to 1 on the first round.

Added screen.stroke() before the for loop and moved it’s position inside the for loop.

function init()
  Nsteps = 8
  position = 0
  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(1)
  screen.move(0,10)
  screen.text(position)
  screen.stroke()
  for i=1, Nsteps do
    if i == position then
      screen.level(15)
    else 
      screen.level(1)
    end    
    screen.circle(14 *i, 30, 2)
    screen.stroke()
  end
  screen.update()
end

#101

Thank you very much, i was hitting a wall.
So now i see that i was mixing up my screen.stroke().


#102

Loving all the new scripts/engines in this update! put a nice karplus sequence (@burn) into the quick granulator (@trickyflemming) and it’s an instant soundtrack for baby sleep time.

Haven’t had much time to write my own scripts lately, hoping to soon tho.

Anyway, this community rules… now back to norns


#103

Is there an easy way to randomly mix up a table’s data?

example = {1,2,3,4}
to
example = {2,4,3,1}

i tried that:

example = {1,2,3,4}
mixedup = {}
for i=1, 4 do
table.insert(mixedup, math.random(1,4), example[i])
end 

but it doesn’t seem to work: "bad argument #2 to ‘insert’ (position out of bounds)"


#104

Here’s a possible solution:


#105

Kinda stumped - i think there’s some syntax I don’t understand yet.

The new version of playfair is using this new Beatclock library. This works great as is for MIDI out, but I can’t figure out how to access the MIDI IN data - since that’s being handled in the beatclock library (instead of my script)

The basic aspects are pasted below (as copied from playfair). What am I missing to get the incoming midi data?

local BeatClock = require 'beatclock'
local clk = BeatClock.new()

midi.add = function(dev)
  dev.event = clk.process_midi
  print("midi device added", dev.id, dev.name)
end

please see lib/beatclock.lua for more on what it’s doing

EDIT: Is this what I’m missing? If so - why do I need to copy this into my script from what already exists in the beatclock lib?

clk.process_midi = function (data)
 -- do stuff
end

#106

I just finished a minimal MPE example. I was surprised how easy it was to get working and how well it works (tried it with my Linnstrument without any issues). It’s not really in a state where I’d want to push it to dust (a more interesting synth engine would be in order), but I’m going to be on the road for two weeks and I’m not sure when I’m going to do more work on it, so I thought I’d already share it here in case anyone is interested: https://gist.github.com/x2mirko/8e35b6825d04e3d925817f288aab16c4


#107

i’m sorry to say this but i’d suggest holding off until i finish the MIDI study. there’s a bunch to explain.

@x2mirko fantastic!!


#108

Understood. Thanks.

Another aspect that had me confused was calculating incoming clock beats per minute (bpm) - which I couldn’t figure out at all.


#109

@okyeron
midi is fairly straightforward…

midi.add = function (dev) … blah
is defining a function you wish to be called when a midi devices is added (or reconnected to a script)

in this particular case, all that is happening is its setting the ‘event callback function’ on the midi device (dev.event = )

so dev.event is a function that is called for each midi event.

(if you look in norns/lua/midi , you can see this happening)

so in playfair what is happening is…

when we get a new midi device (added/reconnected) it is telling it to call used beatclocks.process_midi as the event callback , which in turn will process the midi (which might be a midi clock tick)

i read this as , how do you get your script to be able to process midi

simple… define your own event callback handler

so to give you the idea you want (untested/compiled :wink: ) its something like


my_midi_hander = function(data)
 -- do your midi handling here

 -- then call the beat clock to update the beat clock 
  clk.process_midi(data)
end

midi.add = function(dev)
  dev.event = my_midi_hander
end

so what this does it… you define midi.add, so you can add your own handler
then in your handler you then call the process_miidi of clk as well

again, this is a bit like the last study, it comes down to being able to define function pointers/callbacks. (sorry dont know what lua calls them :slight_smile: )

Ive not had a close look, but given tick() is being called by both the midi handler and the internal metro,
Id assume the internal metro is being set at 24ppqn (just like [midi clock]) (https://en.wikipedia.org/wiki/MIDI_beat_clock) , so this is why the ‘ticks per steps’ is defaulted to 6, (6*4 = 24)

anyway, hopefully this will give you a few pointers till is all explained better :slight_smile:

(fwiw , I suspect many are going to struggle with extensive use of callback functions… they are not the easiest of things to trace through if your not familiar with them)


#110

main reason i suggested holding off is that we’re refining the technique for interacting with midi. so heads up that things will change a bit (for the better)


Norns: code review
#111

That makes me very happy :slight_smile: looking forward to the study!


#112

Gonna start working on a vocoder, but haven’t had a chance to look deeply into many of the engines. Are there any engines that would work well to base a vocoder off of, or should I start with the project in super collider?


#113

I would like to use my MIDI Fighter Twister as a controller for norns. After the readings from norns repo from GitHub MIDI management #454 and feature request: midi CC for toplevel system audio #465, knowing that the MIDI implementation is working in progress. I wanna experiment it a bit on this weekends, maybe try to make Awake script able to receive CC messages.

Where to start? Any reference and documentation (Lua) I should read before? Or I better keep away until the next official update? Thanks and please share your thoughts.


#114

the last release add CC mapping - no?


#115

Oh thanks @TheTechnobear! :sweat_smile:


#116

When you get working (not if) please share a video! The MIDI Fighter Twister is a compelling little bit of kit that I’m dying to see well-integrated with Norns in performance settings. Thanks!


#117

If the MIDI fighter twister is class compliant, it should just work. I just got a faderfox pc4 a couple days ago and found the cc mapping/ setup to be super easy.


#118

It is class compliant :slight_smile: The default settings (and the multiple pages) should work out of the box.


#119

Is there a doc or github issue somewhere that explains everything that goes into a well-behaving engine. I’m familiar enough with supercollider, but am I have trouble getting my scripts to cooperate with norns. An example of something I’m working on: The engine runs, but the commands are unresponsive, do lua engine commands only work if on arg and not var?

// CroneEngine_Klank
// Stolen from example 1.18 in The SuperCollider Book
Engine_Klank : CroneEngine {
	var <synth;

	*new { arg context, doneCallback;
		^super.new(context, doneCallback);
	}

	alloc {
		synth = {
			var scale, specs, freqs, amps, rings,
			    numRes = 5, bells = 4, pan, dur = 1/6;
				scale = [57, 60, 62, 64, 67, 69].midicps;
				Mix.fill(bells, {
					freqs = Array.fill(numRes, {rrand(1, 15)*(scale.choose)});
					amps = Array.fill(numRes, {rrand(0.3, 0.9)});
					rings = Array.fill(numRes, {rrand(1.0, 4.0)});
					specs = [freqs, amps, rings].round(0.01);
						//specs.postln;
					pan = (LFNoise1.kr(rrand(3,6))*2).softclip;
					Pan2.ar(Klank.ar(`specs,
						Dust.ar(dur, 0.03)), // creates impulse 0-(+1) act as trigger
						pan)
				})
}.play;

		this.addCommand("numRes", "r", { arg msg;
			synth.set(\numRes, msg[1]);
		});

		this.addCommand("bells", "b", { arg msg;
			synth.set(\bells, msg[1]);
		});

		this.addCommand("density", "d", { arg msg;
			synth.set(\dur, msg[1]);
		});
	}

	free {
		synth.free;
	}
}