Skip to content

Instantly share code, notes, and snippets.

@jmsole
Last active May 31, 2020 16:22
Show Gist options
  • Save jmsole/6572916b58f79bb75392cd589b5e25da to your computer and use it in GitHub Desktop.
Save jmsole/6572916b58f79bb75392cd589b5e25da to your computer and use it in GitHub Desktop.
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