Skip to content

Commit

Permalink
update for public lib. NEEDS TESTING
Browse files Browse the repository at this point in the history
  • Loading branch information
= committed May 4, 2021
1 parent e251d4d commit 913828a
Show file tree
Hide file tree
Showing 18 changed files with 856 additions and 16 deletions.
42 changes: 42 additions & 0 deletions booleans.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--- boolean logic
-- output logic transfer functions are dynamically selected per channel
-- a state change on any input triggers update of all outputs

-- enumeration of the fnlist. least to most density of transfer
fenum = {'~|','>','<','&','~^','^','~&','<=','>=','|'}

public.add('f1','&',fenum)
public.add('f2','|',fenum)
public.add('f3','^',fenum)
public.add('f4','~^',fenum)

-- all the dynamic transfer fns between 2 inputs (ordering doesn't matter)
fnlist =
{ '~|' = function(a,b) return not (a or b) end
, '>' = function(a,b) return a>b end
, '<' = function(a,b) return a<b end
, '&' = function(a,b) return (a and b) end
, '~^' = function(a,b) return a==b end
, '^' = function(a,b) return a~=b end
, '~&' = function(a,b) return not (a and b) end
, '<=' = function(a,b) return a<=b end
, '>=' = function(a,b) return a>=b end
, '|' = function(a,b) return (a or b) end
}

function q(n) return input[n].volts > 1.0 end
function apply()
local a, b = q(1), q(2)
output[1].volts = fnlist[public.f1](a, b)
output[2].volts = fnlist[public.f2](a, b)
output[3].volts = fnlist[public.f3](a, b)
output[4].volts = fnlist[public.f4](a, b)
end

function init()
for n=1,2 do
input[n].mode('change')
input[n].change = apply -- update all outs on any state change
end
apply() -- initialize to current state
end
31 changes: 31 additions & 0 deletions clockdiv.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--- clock divider
-- in1: clock input
-- in2: division selector (see divs)
-- out1-4: divided outputs

function newdiv(tab)
for n=1,4 do
output[n].clock_div = tab[n]
end
end

-- choose your clock divisions
public.add('win1', {5,7,11,13}, newdiv)
public.add('win2', {3,5,7,11}, newdiv)
public.add('win3', {2,3,5,7}, newdiv)
public.add('win4', {2,4,8,16}, newdiv)
public.add('win5', {4,8,16,32}, newdiv)

WINDOWS = {public.win1, public.win2, public.win3, public.win4, public.win5}

function init()
input[1].mode('clock',1/4)
input[2].mode('window', {-3,-1,1,3})
for n=1,4 do
output[n]:clock(public.win3[n])
end
end

input[2].window = function(win, dir)
newdiv(WINDOWS[win])
end
36 changes: 20 additions & 16 deletions cvdelay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
-- output1-4: delay equaly spaced delay taps

LENGTH = 1000 -- max loop time. MUST BE CONSTANT

public.add('tap1', 250, {1,LENGTH,'slider'})
public.add('tap2', 500, {1,LENGTH,'slider'})
public.add('tap3', 750, {1,LENGTH,'slider'})
Expand All @@ -13,27 +14,30 @@ public.add('loop', 0.0, {0,1,'slider'})
bucket = {}
write = 1
cv_mode = 0

function init()
input[1].mode('stream', 0.001) -- 1kHz
for n=1,4 do output[n].slew = 0.002 end -- smoothing at nyquist
for n=1,LENGTH do bucket[n] = 0 end
for n=1,LENGTH do bucket[n] = 0 end -- clear the buffer
end

function peek(tap)
local ix = (math.floor(write - tap - 1) % LENGTH) + 1
return bucket[ix]
end

function poke(v, ix)
local c = (input[2].volts / 4.5) + public.loop
c = (c < 0) and 0 or c
c = (c > 1) and 1 or c
bucket[ix] = v + c*(bucket[ix] - v)
end

input[1].stream = function(v)
local function poke(v)
local c = (input[2].volts / 4.5) + public.loop
c = (c < 0) and 0 or c
c = (c > 1) and 1 or c
bucket[write] = v + c*(bucket[write] - v)
end
local function peek(ch, tap)
local ix = (math.floor(write - tap - 1) % LENGTH) + 1
output[ch].volts = bucket[ix]
end
peek(1, public.tap1)
peek(2, public.tap2)
peek(3, public.tap3)
peek(4, public.tap4)
poke(v)
output[1].volts = peek(public.tap1)
output[2].volts = peek(public.tap2)
output[3].volts = peek(public.tap3)
output[4].volts = peek(public.tap4)
poke(v, write)
write = (write % LENGTH) + 1
end
77 changes: 77 additions & 0 deletions euclidean.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
--- 4 euclidean rhythm generators
-- sam wolk 2019.10.21
-- in1: clock
-- in2: reset
-- outs: euclidean rhythms

-- ER parameters for each channel.
public.add('lengths', {16,16,16,16})
public.add('fills', {4,5,9,12})
public.add('offsets', {0,0,0,0})

-- private state
locations = {-1,-1,-1,-1}

-- ER function adapted from https://gist.github.com/vrld/b1e6f4cce7a8d15e00e4
function er(fill, length, ix)
local r = {}
-- place all filled slots at the start of the rhythm
for i=1,length do
r[i] = {i <= fill}
end
-- each element is now a table with either true or false

local function cat(t, dst, src)
-- copy all elements of t[src] to the end of t[dst] and remove t[src]
for _,v in ipairs(t[src]) do
table.insert(t[dst], v)
end
t[src] = nil
end

-- interleave the empty slots until they are spread out evenly
while #r > fill do
for i=1,math.min(fill, #r-fill) do
cat(r, i, #r)
end
end

-- fold all lists down to a single one
while #r > 1 do
cat(r, #r-1, #r)
end

-- return boolean (and discard table)
return r[1][ix]
end

-- Use a trigger to advance ER counters and activate ASLs on hits
input[1].change = function(state)
for i=1,4 do
--- increment counters
locations[i] = (locations[i] + 1) % lengths[i]

-- get current location
local index = (locations[i] + offsets[i]) % lengths[i]

-- create pulse if there is an event
if er(fills[i], lengths[i], index+1) then
output[i]()
end
end
end

input[2].change = function(state)
for i=1,4 do
locations[i] = -1 -- reset locations
end
end

function init()
input[1].mode('change',1,0.1,'rising')
input[2].mode('change',1,0.1,'rising')

for i=1,4 do
output[i].action = pulse(0.02,8)
end
end
36 changes: 36 additions & 0 deletions gingerbread.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--- gingerbread man chaotic attractor
-- input1: clock
-- input2: offset
-- output1: X1
-- output2: Y1
-- output3: X2
-- output4: Y2

-- TODO view in x-y mode
function init()
input[1]{ mode = 'change'
, direction = 'rising'
}
end

-- two instances
gs = { {x=0,y=0}
, {x=0,y=0}
}

function make_bread(g, xoff, yoff)
local x1 = g.x
g.x = 0.5 - g.y + math.abs(x1) + xoff
g.y = x1 + yoff
if g.x > 5 then g.x = 5.0 end
if g.y > 5 then g.y = 5.0 end
end

input[1].change = function()
make_bread(gs[1], input[2].volts, 0)
make_bread(gs[2], 0, input[2].volts)
for n=1,2 do
output[n*2-1].volts = gs[n].x
output[n*2].volts = gs[n].y
end
end
99 changes: 99 additions & 0 deletions legacy/boids.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
-- boids
-- t gill 190925
-- inspired by http://www.vergenet.net/~conrad/boids/pseudocode.html

-- params
follow = 0.75 -- input=1, free=0
pull = 0.5 -- to centre
avoid = 0.1 -- V threshold
sync = 1/20 -- dir attraction
limit = 0.05 -- max volts per timestep

timing = 0.02 -- calc speed

boids = {}
count = 4

-- artificially provide a 'centre-of-mass'
function centring(b,c)
return (c - b.p) * pull
end

function avoidance(bs,b)
v = 0
for n=1,count do
if bs[n] ~= b then -- ignore self
d = bs[n].p - b.p
if math.abs(d) < avoid then
v = v - d/2
end
end
end
return v
end

function syncing(bs,b)
v = 0
for n=1,count do
if bs[n] ~= b then -- ignore self
v = v + bs[n].v
end
end
v = v / (count-1)
return (v - b.v) * sync
end

function findcentre(bs,c)
m = 0
for n=1,count do
m = m + bs[n].p
end
m = m/count
return m + follow*(c-m)
end

function move( bs, n, c, v )
mass = findcentre(bs,c)
b = bs[n]
v1 = centring(b,mass)
v2 = avoidance(bs,b)
v3 = syncing(bs,b)
b.v = b.v + v1 + v2 + v3
if b.v > limit then b.v = limit
elseif b.v < -limit then b.v = -limit end
b.v = b.v * v
b.p = b.p + b.v
return b
end

function draw( b, n, v )
output[n].slew = v*1.1
output[n].volts = b.p
end

-- round-robin calculation
function step(c)
c = (c % count)+1
accel = input[2].volts
draw( boids[c], c, timing )
boids[c] = move( boids, c, input[1].volts, (accel+5.0)/5.0 )
end

function init_boids()
local bs = {}
for n=1,count do
bs[n] = { p = math.random()*3.0 - 1.0
, v = 0
}
end
return bs
end

function init()
boids = init_boids()
mover = metro.init{ event = step
, time = timing/count
, count = -1
}
mover:start()
end
31 changes: 31 additions & 0 deletions legacy/booleanlogic.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--- boolean logic
-- out1: 1 AND 2
-- out2: 1 OR 2
-- out3: 1 XOR 2
-- out4: true on 1rising, false on 2rising

g = {false, false} -- state of the input gates
flipflop = false -- state of the flipflop
function init()
for n=1,2 do
input[n].mode('change')
g[n] = input[n].volts > 1.0
end
end

function logic( chan, state )
g[chan] = state
if state then flipflop = (chan == 1) and true or false end

output[1].volts = (g[1] and g[2]) and 5 or 0
output[2].volts = (g[1] or g[2]) and 5 or 0
output[3].volts = (g[1] ~= g[2]) and 5 or 0 -- XOR is the same as not-equal
output[4].volts = flipflop and 5 or 0
end

input[1].change = function(s)
logic(1,s)
end
input[2].change = function(s)
logic(2,s)
end
Loading

0 comments on commit 913828a

Please sign in to comment.