norns SequencerClock test
| -- SeqClock | |
| -- multi-track sequencer test | |
| -- enc1: select track | |
| -- enc2: curr. track step rate | |
| -- enc3: curr. track steps count | |
| -- key2: randomize steps | |
| -- key3: toggle play | |
| engine.name = "PolyPerc" | |
| local playing = 0 | |
| local track = 1 --active track | |
| local tracksN = 4 --available tracks | |
| local trackClock = {} | |
| local steps = {} | |
| local pos = {} | |
| local trackParams = {} | |
| local stepLengthVals = { 4, 3, 2, 1, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/16, 1/24, 1/32 } | |
| for t=1,tracksN do | |
| pos[t] = 0 --set all voices position to 1 | |
| trackParams[t] = { | |
| steps = 16, | |
| stepLength = 5, | |
| transpose = 0, | |
| octave = 0 | |
| } | |
| end | |
| function togglePlay() | |
| playing = (playing+1)%2 -- toggle play | |
| print("playing",playing) | |
| if playing == 1 then | |
| for t=1,tracksN do | |
| trackClock[t] = clock.run(step,t) | |
| end | |
| print(trackClock) | |
| else | |
| for t=1,tracksN do | |
| clock.cancel(trackClock[t]) | |
| pos[t] = 0 --set all tracks position to 1 | |
| end | |
| --clock.cancel(masterClock) | |
| end | |
| end | |
| function n2f(note) | |
| return (440 / 32) * math.pow(2, ((note - 9) / 12)) | |
| end | |
| function note_on(track,note_num,vel) | |
| local transp = trackParams[track].transpose | |
| local oct = trackParams[track].octave | |
| --print("note_on:",note_num) | |
| local freq = n2f(note_num + transp + 12*oct) | |
| --print("freq:",freq) | |
| engine.hz(freq) | |
| clock.sync( stepLengthVals[trackParams[track].stepLength]) | |
| --note_off( track, note_num, vel) | |
| end | |
| function note_off(track,note_num) | |
| local transp = trackParams[track].transpose | |
| local oct = trackParams[track].octave | |
| engine.noteOff(track, note_num + transp + 12*oct ) | |
| end | |
| function key(n,z) | |
| if n == 2 then | |
| if z == 1 then | |
| randomizeSteps(track) | |
| end | |
| elseif n==3 then | |
| if z == 1 then | |
| togglePlay() | |
| elseif z == 0 then | |
| end | |
| end | |
| redraw() | |
| end | |
| function enc(n,d) | |
| if n == 1 then | |
| track = util.round(util.clamp(track + d, 1, tracksN), 1) | |
| elseif n == 2 then | |
| trackParams[track].stepLength = util.round(util.clamp(trackParams[track].stepLength + d, 1, #stepLengthVals), 1) | |
| elseif n == 3 then | |
| trackParams[track].steps = util.round(util.clamp(trackParams[track].steps + d, 1, 16), 1) | |
| end | |
| redraw() | |
| end | |
| local maj = {36,38,40,41,43,45,47,48,50,52,53,55,57,59,60,62} | |
| function step(trk) | |
| while true do | |
| local rate = stepLengthVals[trackParams[trk].stepLength] | |
| clock.sync(rate) | |
| pos[trk] = ( pos[trk] % trackParams[trk].steps ) + 1 | |
| local note = maj[ steps[trk][ pos[trk] ] ] | |
| --print("step:",pos[trk],"note num.",steps[trk][ pos[trk] ], "note:",note) | |
| if (note == nil) then | |
| clock.sync( rate ) | |
| else | |
| note_on( trk, note, 100) | |
| end | |
| --clock.sync(rate) | |
| end | |
| end | |
| function redraw() | |
| screen.clear() | |
| screen.level(15) | |
| screen.move(0, 8) | |
| screen.text("SeqClock") | |
| screen.move(60, 8) | |
| screen.text("track: "..track) | |
| screen.move(125, 8) | |
| if playing == 1 then screen.text("►") end | |
| screen.move(0,50) | |
| screen.text("step length: "..util.trim_string_to_width(""..stepLengthVals[trackParams[track].stepLength].."",40)) | |
| screen.move(0,60) | |
| screen.text("steps: "..trackParams[track].steps) | |
| screen.update() | |
| end | |
| function randomizeSteps(track) | |
| steps[track] = {} | |
| print("randomizeSteps") | |
| for i=1,trackParams[track].steps do | |
| table.insert(steps[track],math.random(16)) | |
| end | |
| print("track steps:",trackParams[track].steps) | |
| local showStepsVal = "" | |
| for i=1,trackParams[track].steps do | |
| showStepsVal = showStepsVal..steps[track][i].." " | |
| end | |
| print(showStepsVal) | |
| end | |
| function init() | |
| -- init steps | |
| for t=1,tracksN do | |
| steps[t] = {} | |
| for i=1,16 do | |
| table.insert(steps[t],0) | |
| --table.insert(steps[v],math.random(2,8)) | |
| end | |
| end | |
| counter = metro.init(grid_redraw,0.0016,-1) | |
| counter:start() | |
| redraw() | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment