musiclight2/flame.lua

217 lines
4.9 KiB
Lua
Raw Permalink Normal View History

COOLDOWN_FACTOR = 0.9998
OVERDRIVE = 1.70
EXPONENT = 1.5
W_EXPONENT = 2.2
2019-12-17 22:09:53 +01:00
M = 10.0 -- mass
D = 1 -- spring strength
DAMPING = {} -- filled in init()
2019-12-17 22:09:53 +01:00
num_modules = 16
center_module = 16
num_masses = math.floor(num_modules/2)
excitement_pos = 1
-- maximum energy values for each band
maxRedEnergy = 1
maxGreenEnergy = 1
maxBlueEnergy = 1
maxWhiteEnergy = 1
-- spring-mass-grid values
pos_r = {}
pos_g = {}
pos_b = {}
pos_w = {}
vel_r = {}
vel_g = {}
vel_b = {}
vel_w = {}
acc_r = {}
acc_g = {}
acc_b = {}
acc_w = {}
-- output color buffers
red = {}
green = {}
blue = {}
white = {}
r_tmp = {}
g_tmp = {}
b_tmp = {}
w_tmp = {}
function limit(val)
if val > 1 then
return 1
elseif val < 0 then
return 0
else
return val
end
end
function periodic()
local redEnergy = get_energy_in_band(0, 400);
local greenEnergy = get_energy_in_band(400, 4000);
local blueEnergy = get_energy_in_band(4000, 12000);
local whiteEnergy = get_energy_in_band(12000, 22000);
local centerIndex = 2 * center_module + 1;
2018-08-14 21:52:33 +02:00
--print(maxRedEnergy .. "\t" .. maxGreenEnergy .. "\t" .. maxBlueEnergy .. "\t" .. maxWhiteEnergy)
maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
if redEnergy > maxRedEnergy then
maxRedEnergy = redEnergy
end
maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR
if greenEnergy > maxGreenEnergy then
maxGreenEnergy = greenEnergy
end
maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR
if blueEnergy > maxBlueEnergy then
maxBlueEnergy = blueEnergy
end
maxWhiteEnergy = maxWhiteEnergy * COOLDOWN_FACTOR
if whiteEnergy > maxWhiteEnergy then
maxWhiteEnergy = whiteEnergy
end
-- update the spring-mass string
-- the outside masses are special, as they are auto-returned to 0 position
-- { spring-mass pendulum } { friction }
--acc_r[1] = (-pos_r[1] + (pos_r[2] - pos_r[1])) * D / M
--acc_g[1] = (-pos_g[1] + (pos_g[2] - pos_g[1])) * D / M
--acc_b[1] = (-pos_b[1] + (pos_b[2] - pos_b[1])) * D / M
--acc_w[1] = (-pos_w[1] + (pos_w[2] - pos_w[1])) * D / M
acc_r[num_masses] = (-pos_r[num_masses] + (pos_r[num_masses-1] - pos_r[num_masses])) * D / M
acc_g[num_masses] = (-pos_g[num_masses] + (pos_g[num_masses-1] - pos_g[num_masses])) * D / M
acc_b[num_masses] = (-pos_b[num_masses] + (pos_b[num_masses-1] - pos_b[num_masses])) * D / M
acc_w[num_masses] = (-pos_w[num_masses] + (pos_w[num_masses-1] - pos_w[num_masses])) * D / M
-- inside masses are only influenced by their neighbors
for i = 2,num_masses-1 do
acc_r[i] = (pos_r[i-1] + pos_r[i+1] - 2 * pos_r[i]) * D / M
acc_g[i] = (pos_g[i-1] + pos_g[i+1] - 2 * pos_g[i]) * D / M
acc_b[i] = (pos_b[i-1] + pos_b[i+1] - 2 * pos_b[i]) * D / M
acc_w[i] = (pos_w[i-1] + pos_w[i+1] - 2 * pos_w[i]) * D / M
end
-- update velocity and position
for i = 1,num_masses do
vel_r[i] = DAMPING[i] * (vel_r[i] + acc_r[i])
vel_g[i] = DAMPING[i] * (vel_g[i] + acc_g[i])
vel_b[i] = DAMPING[i] * (vel_b[i] + acc_b[i])
vel_w[i] = DAMPING[i] * (vel_w[i] + acc_w[i])
pos_r[i] = pos_r[i] + vel_r[i]
pos_g[i] = pos_g[i] + vel_g[i]
pos_b[i] = pos_b[i] + vel_b[i]
pos_w[i] = pos_w[i] + vel_w[i]
end
-- set the new position for the center module
newRed = redEnergy / maxRedEnergy
pos_r[excitement_pos] = newRed
vel_r[excitement_pos] = 0
acc_r[excitement_pos] = 0
newGreen = greenEnergy / maxGreenEnergy
pos_g[excitement_pos] = newGreen
vel_g[excitement_pos] = 0
acc_g[excitement_pos] = 0
newBlue = blueEnergy / maxBlueEnergy
pos_b[excitement_pos] = newBlue
vel_b[excitement_pos] = 0
acc_b[excitement_pos] = 0
newWhite = whiteEnergy / maxWhiteEnergy
pos_w[excitement_pos] = newWhite
vel_w[excitement_pos] = 0
acc_w[excitement_pos] = 0
-- map to LED modules
for i = 1,num_masses do
r_tmp[i] = pos_r[i]
g_tmp[i] = pos_g[i]
b_tmp[i] = pos_b[i]
w_tmp[i] = pos_w[i]
2018-06-30 01:42:34 +02:00
--r_tmp[num_modules-i+1] = pos_r[i]
--g_tmp[num_modules-i+1] = pos_g[i]
--b_tmp[num_modules-i+1] = pos_b[i]
--w_tmp[num_modules-i+1] = pos_w[i]
--print(i, pos_r[i])
end
-- make colors more exciting + remove the first (flickering) mass
for m = 1,num_modules do
rval = limit(OVERDRIVE * r_tmp[m+1]^EXPONENT)
gval = limit(OVERDRIVE * g_tmp[m+1]^EXPONENT)
bval = limit(OVERDRIVE * b_tmp[m+1]^EXPONENT)
wval = limit(OVERDRIVE * w_tmp[m+1]^W_EXPONENT)
for s = 1,num_strip do
i = idx(s, m)
red[i] = rval
green[i] = gval
blue[i] = bval
white[i] = wval
end
end
2019-12-17 22:09:53 +01:00
-- return the 4 color arrays
return red, green, blue, white
end
function init(nstrip, nmod, cmod)
num_strip = nstrip
num_modules = nmod
2018-08-14 21:52:33 +02:00
center_module = nmod --cmod
num_masses = nmod+1 --math.floor(nmod/2)
excitement_pos = 1
for i = 1,(nmod*nstrip) do
red[i] = 0
green[i] = 0
blue[i] = 0
white[i] = 0
end
for i = 1,num_masses do
pos_r[i] = 0
pos_g[i] = 0
pos_b[i] = 0
pos_w[i] = 0
vel_r[i] = 0
vel_g[i] = 0
vel_b[i] = 0
vel_w[i] = 0
acc_r[i] = 0
acc_g[i] = 0
acc_b[i] = 0
acc_w[i] = 0
2019-12-17 22:09:53 +01:00
DAMPING[i] = 1 - 0.15 * math.abs((i - excitement_pos) / num_masses)^2
end
-- don't use fading
return 0
end