A basic cv-controlled clock with swing and clock multiplier for crow
| -- a basic cv-controlled clock with swing and clock division | |
| -- input 1: 0 - 5v cv to control tempo | |
| -- input 2: -5 - 5v cv to control swing on even notes | |
| -- 0v is no swing, -5v is 25% swing and 5v is 75% swing | |
| -- output 1: clock without swing | |
| -- output 2: clock with swing and clock division | |
| -- output 3: half-tempo clock with odd beats and clock division | |
| -- output 4: half-tempo swinged clock with even beats and clock division | |
| -- clock divider factor. 1 is no division, probably better to use even numbers | |
| swingclockdivider = 2 | |
| -- initial values and constants | |
| pulsetime = 0.0025 | |
| pulselevel = 5 | |
| pulsepolarity = 1 | |
| bpmmin = 50 | |
| bpmmax = 200 | |
| swingmin = 25 | |
| swingmax = 75 | |
| bpm = 120 | |
| click = 60 / bpm | |
| swing = 50 | |
| -- a few functions that help later | |
| function trunc_float(n) | |
| trunc = string.format("%.4f", n) | |
| return trunc | |
| end | |
| function map_range(a1, a2, b1, b2, s) | |
| return b1 + (s-a1)*(b2-b1)/(a2-a1) | |
| end | |
| function volt2clock(v) | |
| bpm = map_range(0, 5, bpmmin, bpmmax, v) | |
| bpm = math.floor(bpm) | |
| click = 60/bpm | |
| click = trunc_float(click) * 2 -- need to multiply clock to make it slower | |
| return click | |
| end | |
| function swing_delay(t, s) | |
| swingdel = t * s / 50 | |
| swingdel = trunc_float(swingdel) | |
| return swingdel | |
| end | |
| function volt2swing(v) | |
| swing = map_range(-5 , 5, swingmin, swingmax, v) | |
| swing = math.floor(swing) | |
| return swing | |
| end | |
| -- main clock function | |
| function clock() | |
| newclick = volt2clock(input[1].volts) | |
| clock_metro.time = newclick | |
| newswing = volt2swing(input[2].volts) | |
| swingdel = swing_delay(newclick, newswing) / 2 | |
| div = swingdel / swingclockdivider | |
| -- print(bpm, newclick, newswing, swingdel, div, swingdel / swingclockdivider) | |
| -- To get clock at normal speed on output 1 I am using delay to get clock divisions | |
| -- because of the clock multiply in volt2clock | |
| output[1]() | |
| delay(function() output[1]() end, newclick / 2, 0) | |
| if swingclockdivider == 1 then | |
| output[2]() | |
| output[3]() | |
| delay(function() output[2]() output[4]() end, swingdel, 0) | |
| elseif swingclockdivider >= 2 then | |
| delay(function() output[2]() output[3]() end, newclick / swingclockdivider, swingclockdivider - 1) | |
| delay(function() | |
| delay(function() | |
| output[2]() output[4]() | |
| end | |
| , newclick / swingclockdivider | |
| , swingclockdivider - 1) | |
| end | |
| , div | |
| , 0) | |
| end | |
| end | |
| -- report function to print swing and bpm to druid | |
| function report() | |
| print(newswing, bpm) | |
| end | |
| -- initialization function | |
| function init() | |
| for n = 1,4 do | |
| output[n].action = pulse( pulsetime, pulselevel, pulsepolarity ) | |
| end | |
| clock_metro = metro.init{ event = clock | |
| , time = click | |
| , count = -1 | |
| } | |
| clock_metro:start() | |
| reporter = metro.init{ event = report | |
| , time = 0.25 | |
| , count = -1 | |
| } | |
| -- reporter:start() | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment