Skip to content
Permalink
spring
Go to file
 
 
Cannot retrieve contributors at this time
88 lines (69 sloc) 3.12 KB
--- Springs
-- a spring physics based voltage follower
-- input 1+2: voltages that outs 1/2 and 2/4 will follow.
-- output 1/2 will follow input 1
-- output 3/4 will follow input 2 (the first pair is more volatile)
-- For best results don't attentuate the input but the outputs. Bigger or faster changes put more energy into the system and create more pronounced effects. Try using a quantizer to drive two related melodies.
-- settings
scale = false -- outputs are continous (not quantized). Try {0,2,3,5,7,9,10} instead.
rate = 0.05 -- sets the refresh rate for the springs' state calculation. This has a drastic effect and is callibrated to the default set of variables for the springs. Best leave and play with the spring values below instead.
function init()
-- initialize the 4 springs with dedicated settings for gravity, spring constant, mass, and dampening
springA = Spring:new(0,0.5,2,0.92)
springB = Spring:new(0,0.01,5,0.97)
springC = Spring:new(0,0.7,1,0.90)
springD = Spring:new(0,0.03,5,0.92)
-- configure the 4 outputs
for i = 1, 4 do
if scale then
-- if a scale is set up in settings it is used here
output[i].scale(scale)
else
-- otherwise the output is slewed to be continuous
output[i].slew = rate
end
end
-- kick of the spring update cycle at the given rate
metro[1].event = updateSprings
metro[1].time = rate
metro[1]:start()
end
function updateSprings()
-- update the spring pairs A/B and C/D based on input 1 and 2 using the built in method
-- Tip: try passing in one spring's endpoint (e.g. springA.ps) as another spring's target
springA:calculate(input[1].volts)
springB:calculate(input[1].volts)
springC:calculate(input[2].volts)
springD:calculate(input[2].volts)
-- update the outputs based on the updated springs' states. They all will evetually catch up with the input voltages.
-- Please note: If you set gravity to something other than 0 than springs will set in a "stretched" state which means the output will never quite reach the input voltage.
output[1].volts = springA.ps
output[2].volts = springB.ps
output[3].volts = springC.ps
output[4].volts = springD.ps
end
-- defining the spring object
Spring = {}
function Spring:new(g,K,M,D)
-- a = postion of anchor
-- f = force = f=-ky
-- g = gravity (if not 0 the output will be offset from the input and never catch up)
-- as = acceleration, f=ma == a=f/m
-- vs = velocity
-- ps = position of spring end
-- K = spring constant
-- M = Mass
-- D = Dampening
newObj = {a = 0, f = 0, g = g, as = 0, vs = 0, ps = 0, K = K, M = M, D = D }
setmetatable(newObj, self)
self.__index = self
return newObj
end
function Spring:calculate(target)
-- method to calculate the spring's state with physics!
self.a = target or input[1].volts
self.f = -self.K * ( self.ps - self.a ) -- f=-ky
self.as = self.f / self.M + self.M * self.g -- Set the acceleration based on force, f=ma == a=f/m
self.vs = self.D * (self.vs + self.as); -- Set the velocity
self.ps = self.ps + self.vs -- Updated endpoint
end