Update Lua API to support 2D LED arrays
It’s a whole new dimension!
This commit is contained in:
parent
54609eae89
commit
4041923cc7
4
config.h
4
config.h
|
@ -16,13 +16,13 @@
|
||||||
// configuration variables for musiclight2
|
// configuration variables for musiclight2
|
||||||
|
|
||||||
// networking
|
// networking
|
||||||
#define HOST "musiclight0.wiese.icmp.camp"
|
#define HOST "192.168.42.1"
|
||||||
#define PORT 2703
|
#define PORT 2703
|
||||||
|
|
||||||
// FFT transformation parameters
|
// FFT transformation parameters
|
||||||
#define FFT_EXPONENT 8 // ATTENTION: when you change this, run gen_lut.py with this value as argument
|
#define FFT_EXPONENT 8 // ATTENTION: when you change this, run gen_lut.py with this value as argument
|
||||||
#define BLOCK_LEN (1 << FFT_EXPONENT) // 2^FFT_EXPONENT
|
#define BLOCK_LEN (1 << FFT_EXPONENT) // 2^FFT_EXPONENT
|
||||||
#define SAMPLE_RATE 48000
|
#define SAMPLE_RATE 44100
|
||||||
#define DATALEN (BLOCK_LEN / 2)
|
#define DATALEN (BLOCK_LEN / 2)
|
||||||
|
|
||||||
// Number of parts in the sample buffer
|
// Number of parts in the sample buffer
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
WS2801_HOST = "10.42.6.183"
|
WS2801_HOST = "192.168.42.1"
|
||||||
WS2801_PORT = 2703
|
WS2801_PORT = 2703
|
||||||
|
|
||||||
NUM_MODULES = 16
|
NUM_MODULES = 16
|
||||||
|
NUM_STRIPS = 8
|
||||||
CENTER_MODULE = 8
|
CENTER_MODULE = 8
|
||||||
|
|
||||||
GAMMA = 2.0
|
GAMMA = 2.0
|
||||||
|
|
24
flame.lua
24
flame.lua
|
@ -157,25 +157,35 @@ function periodic()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- make colors more exciting + remove the first (flickering) mass
|
-- make colors more exciting + remove the first (flickering) mass
|
||||||
for i = 1,num_modules do
|
for m = 1,num_modules do
|
||||||
red[i] = limit(OVERDRIVE * r_tmp[i+1]^EXPONENT)
|
rval = limit(OVERDRIVE * r_tmp[m+1]^EXPONENT)
|
||||||
green[i] = limit(OVERDRIVE * g_tmp[i+1]^EXPONENT)
|
gval = limit(OVERDRIVE * g_tmp[m+1]^EXPONENT)
|
||||||
blue[i] = limit(OVERDRIVE * b_tmp[i+1]^EXPONENT)
|
bval = limit(OVERDRIVE * b_tmp[m+1]^EXPONENT)
|
||||||
white[i] = limit(OVERDRIVE * w_tmp[i+1]^W_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
|
end
|
||||||
|
|
||||||
-- return the 4 color arrays
|
-- return the 4 color arrays
|
||||||
return red, green, blue, white
|
return red, green, blue, white
|
||||||
end
|
end
|
||||||
|
|
||||||
function init(nmod, cmod)
|
function init(nstrip, nmod, cmod)
|
||||||
|
num_strip = nstrip
|
||||||
num_modules = nmod
|
num_modules = nmod
|
||||||
center_module = nmod --cmod
|
center_module = nmod --cmod
|
||||||
|
|
||||||
num_masses = nmod+1 --math.floor(nmod/2)
|
num_masses = nmod+1 --math.floor(nmod/2)
|
||||||
excitement_pos = 1
|
excitement_pos = 1
|
||||||
|
|
||||||
for i = 1,nmod do
|
for i = 1,(nmod*nstrip) do
|
||||||
red[i] = 0
|
red[i] = 0
|
||||||
green[i] = 0
|
green[i] = 0
|
||||||
blue[i] = 0
|
blue[i] = 0
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <lua5.3/lauxlib.h>
|
#include <lua5.3/lauxlib.h>
|
||||||
|
|
||||||
#include "fft.h"
|
#include "fft.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -66,9 +67,24 @@ static int l_get_rms(lua_State *L) {
|
||||||
return 1; // number of return values
|
return 1; // number of return values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculate the position in the output arrays from strip and module index
|
||||||
|
static int l_idx(lua_State *L) {
|
||||||
|
luaL_checktype(L, 1, LUA_TNUMBER);
|
||||||
|
int strip = lua_tointeger(L, 1) - 1; // -1 because Lua counts from 1
|
||||||
|
|
||||||
|
luaL_checktype(L, 2, LUA_TNUMBER);
|
||||||
|
int module = lua_tointeger(L, 2) - 1; // -1 because Lua counts from 1
|
||||||
|
|
||||||
|
lua_pushnumber(L, idx(strip, module) + 1); // +1 because Lua counts from 1
|
||||||
|
|
||||||
|
return 1; // number of return values
|
||||||
|
}
|
||||||
|
|
||||||
void lua_register_funcs(lua_State *L) {
|
void lua_register_funcs(lua_State *L) {
|
||||||
lua_register(L, "get_energy_in_band", l_get_energy_in_band);
|
lua_register(L, "get_energy_in_band", l_get_energy_in_band);
|
||||||
lua_register(L, "get_fft", l_get_fft);
|
lua_register(L, "get_fft", l_get_fft);
|
||||||
lua_register(L, "get_signal", l_get_signal);
|
lua_register(L, "get_signal", l_get_signal);
|
||||||
lua_register(L, "get_rms", l_get_rms);
|
lua_register(L, "get_rms", l_get_rms);
|
||||||
|
|
||||||
|
lua_register(L, "idx", l_idx);
|
||||||
}
|
}
|
||||||
|
|
143
main.c
143
main.c
|
@ -36,11 +36,8 @@
|
||||||
// Number of new samples put into the buffer each frame
|
// Number of new samples put into the buffer each frame
|
||||||
#define READ_SAMPLES (BLOCK_LEN / BUFFER_PARTS)
|
#define READ_SAMPLES (BLOCK_LEN / BUFFER_PARTS)
|
||||||
|
|
||||||
#define NUM_SK6812 8
|
|
||||||
|
|
||||||
value_type fft[BLOCK_LEN];
|
value_type fft[BLOCK_LEN];
|
||||||
value_type rms;
|
value_type rms;
|
||||||
value_type redEnergy, greenEnergy, blueEnergy;
|
|
||||||
value_type lastUpdateTime = 0;
|
value_type lastUpdateTime = 0;
|
||||||
|
|
||||||
sample signal[BLOCK_LEN];
|
sample signal[BLOCK_LEN];
|
||||||
|
@ -49,6 +46,9 @@ sem_t fftSemaphore;
|
||||||
|
|
||||||
struct sk6812_ctx sk6812;
|
struct sk6812_ctx sk6812;
|
||||||
|
|
||||||
|
int num_modules;
|
||||||
|
int num_strips;
|
||||||
|
|
||||||
int running = 1;
|
int running = 1;
|
||||||
|
|
||||||
void* fft_thread(void *param) {
|
void* fft_thread(void *param) {
|
||||||
|
@ -61,22 +61,22 @@ void* fft_thread(void *param) {
|
||||||
double nextFrame = get_hires_time() + 0.05;
|
double nextFrame = get_hires_time() + 0.05;
|
||||||
double curTime;
|
double curTime;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
init_fft();
|
init_fft();
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
// shift the buffer left
|
// shift the buffer left
|
||||||
memmove(buffer, buffer + READ_SAMPLES,
|
memmove(buffer, buffer + READ_SAMPLES,
|
||||||
(BLOCK_LEN - READ_SAMPLES) * sizeof(sample));
|
(BLOCK_LEN - READ_SAMPLES) * sizeof(sample));
|
||||||
|
|
||||||
size_t ret = fread(buffer + (BLOCK_LEN - READ_SAMPLES),
|
size_t ret = fread(buffer + (BLOCK_LEN - READ_SAMPLES),
|
||||||
sizeof(sample), READ_SAMPLES, stdin);
|
sizeof(sample), READ_SAMPLES, stdin);
|
||||||
if(ret != READ_SAMPLES) {
|
if(ret != READ_SAMPLES) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(block, buffer, BLOCK_LEN * sizeof(sample));
|
memcpy(block, buffer, BLOCK_LEN * sizeof(sample));
|
||||||
|
|
||||||
tmpRMS = 0;
|
tmpRMS = 0;
|
||||||
for(i = 0; i < BLOCK_LEN; i++) {
|
for(i = 0; i < BLOCK_LEN; i++) {
|
||||||
|
@ -88,9 +88,9 @@ void* fft_thread(void *param) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_hanning(block);
|
apply_hanning(block);
|
||||||
fft_transform(block, fftOutReal, fftOutImag);
|
fft_transform(block, fftOutReal, fftOutImag);
|
||||||
complex_to_absolute(fftOutReal, fftOutImag, tmpFFT);
|
complex_to_absolute(fftOutReal, fftOutImag, tmpFFT);
|
||||||
|
|
||||||
// --- SAFE SECTION ---
|
// --- SAFE SECTION ---
|
||||||
sem_wait(&fftSemaphore);
|
sem_wait(&fftSemaphore);
|
||||||
|
@ -99,32 +99,32 @@ void* fft_thread(void *param) {
|
||||||
memcpy(signal, buffer, sizeof(signal));
|
memcpy(signal, buffer, sizeof(signal));
|
||||||
rms = tmpRMS;
|
rms = tmpRMS;
|
||||||
|
|
||||||
curTime = get_hires_time();
|
curTime = get_hires_time();
|
||||||
lastUpdateTime = curTime;
|
lastUpdateTime = curTime;
|
||||||
|
|
||||||
sem_post(&fftSemaphore);
|
sem_post(&fftSemaphore);
|
||||||
// --- END SAFE SECTION ---
|
// --- END SAFE SECTION ---
|
||||||
|
|
||||||
if(curTime > nextFrame + 0.05) {
|
if(curTime > nextFrame + 0.05) {
|
||||||
printf("Frame too late! Skipping.\n");
|
printf("Frame too late! Skipping.\n");
|
||||||
nextFrame = -1;
|
nextFrame = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(curTime < nextFrame - 0.05) {
|
if(curTime < nextFrame - 0.05) {
|
||||||
printf("Frame too early.\n");
|
printf("Frame too early.\n");
|
||||||
nextFrame = -1;
|
nextFrame = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextFrame < 0) {
|
if(nextFrame < 0) {
|
||||||
printf("Frame time reset.\n");
|
printf("Frame time reset.\n");
|
||||||
nextFrame = curTime;
|
nextFrame = curTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextFrame += 1.000/FPS;
|
nextFrame += 1.000/FPS;
|
||||||
//sleep_until(nextFrame);
|
//sleep_until(nextFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type gamma_correct(value_type d, value_type gamma) {
|
value_type gamma_correct(value_type d, value_type gamma) {
|
||||||
|
@ -134,8 +134,8 @@ value_type gamma_correct(value_type d, value_type gamma) {
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
double nextFrame = get_hires_time() + LED_INTERVAL;
|
double nextFrame = get_hires_time() + LED_INTERVAL;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
pthread_t fftThread;
|
pthread_t fftThread;
|
||||||
|
|
||||||
int active = 1;
|
int active = 1;
|
||||||
//int frame = 0;
|
//int frame = 0;
|
||||||
|
@ -181,7 +181,11 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
lua_getglobal(L, "NUM_MODULES");
|
lua_getglobal(L, "NUM_MODULES");
|
||||||
if(!lua_isnumber(L, -1)) return 2;
|
if(!lua_isnumber(L, -1)) return 2;
|
||||||
int num_modules = lua_tointeger(L, -1);
|
num_modules = lua_tointeger(L, -1);
|
||||||
|
|
||||||
|
lua_getglobal(L, "NUM_STRIPS");
|
||||||
|
if(!lua_isnumber(L, -1)) return 2;
|
||||||
|
num_strips = lua_tointeger(L, -1);
|
||||||
|
|
||||||
lua_getglobal(L, "CENTER_MODULE");
|
lua_getglobal(L, "CENTER_MODULE");
|
||||||
if(!lua_isnumber(L, -1)) return 2;
|
if(!lua_isnumber(L, -1)) return 2;
|
||||||
|
@ -198,10 +202,10 @@ int main(int argc, char **argv) {
|
||||||
lua_setglobal(L, "DATALEN");
|
lua_setglobal(L, "DATALEN");
|
||||||
|
|
||||||
// allocate arrays
|
// allocate arrays
|
||||||
red = malloc(num_modules * sizeof(double));
|
red = malloc(num_strips * num_modules * sizeof(double));
|
||||||
green = malloc(num_modules * sizeof(double));
|
green = malloc(num_strips * num_modules * sizeof(double));
|
||||||
blue = malloc(num_modules * sizeof(double));
|
blue = malloc(num_strips * num_modules * sizeof(double));
|
||||||
white = malloc(num_modules * sizeof(double));
|
white = malloc(num_strips * num_modules * sizeof(double));
|
||||||
|
|
||||||
// load and initialize the script
|
// load and initialize the script
|
||||||
if(luaL_loadfile(L, argv[1])) {
|
if(luaL_loadfile(L, argv[1])) {
|
||||||
|
@ -215,9 +219,10 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// call the init function
|
// call the init function
|
||||||
lua_getglobal(L, "init");
|
lua_getglobal(L, "init");
|
||||||
|
lua_pushnumber(L, num_strips);
|
||||||
lua_pushnumber(L, num_modules);
|
lua_pushnumber(L, num_modules);
|
||||||
lua_pushnumber(L, center_module);
|
lua_pushnumber(L, center_module);
|
||||||
if(lua_pcall(L, 2, 1, 0)) {
|
if(lua_pcall(L, 3, 1, 0)) {
|
||||||
lua_showerror(L, "lua_pcall(init) failed.");
|
lua_showerror(L, "lua_pcall(init) failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,13 +237,13 @@ int main(int argc, char **argv) {
|
||||||
printf("Connecting to %s:%i\n", host, port);
|
printf("Connecting to %s:%i\n", host, port);
|
||||||
sk6812_init(&sk6812, host, port);
|
sk6812_init(&sk6812, host, port);
|
||||||
|
|
||||||
// create semaphores
|
// create semaphores
|
||||||
sem_init(&fftSemaphore, 0, 1);
|
sem_init(&fftSemaphore, 0, 1);
|
||||||
|
|
||||||
// run the fft thread
|
// run the fft thread
|
||||||
pthread_create(&fftThread, NULL, fft_thread, NULL);
|
pthread_create(&fftThread, NULL, fft_thread, NULL);
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
if(active) {
|
if(active) {
|
||||||
// call the periodic() function from LUA
|
// call the periodic() function from LUA
|
||||||
lua_getglobal(L, "periodic");
|
lua_getglobal(L, "periodic");
|
||||||
|
@ -247,27 +252,29 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the return values (reverse order, as lua uses a stack)
|
// read the return values (reverse order, as lua uses a stack)
|
||||||
lua_readdoublearray(L, white, num_modules);
|
lua_readdoublearray(L, white, num_strips*num_modules);
|
||||||
lua_readdoublearray(L, blue, num_modules);
|
lua_readdoublearray(L, blue, num_strips*num_modules);
|
||||||
lua_readdoublearray(L, green, num_modules);
|
lua_readdoublearray(L, green, num_strips*num_modules);
|
||||||
lua_readdoublearray(L, red, num_modules);
|
lua_readdoublearray(L, red, num_strips*num_modules);
|
||||||
|
|
||||||
for(int s = 0; s < NUM_SK6812; s++) {
|
for(int s = 0; s < num_strips; s++) {
|
||||||
if(useFading) {
|
if(useFading) {
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
|
int lidx = idx(s, i);
|
||||||
sk6812_fade_color(&sk6812, s, i,
|
sk6812_fade_color(&sk6812, s, i,
|
||||||
255 * gamma_correct(red[i], gamma),
|
255 * gamma_correct(red[lidx], gamma),
|
||||||
255 * gamma_correct(green[i], gamma),
|
255 * gamma_correct(green[lidx], gamma),
|
||||||
255 * gamma_correct(blue[i], gamma),
|
255 * gamma_correct(blue[lidx], gamma),
|
||||||
255 * gamma_correct(white[i], gamma));
|
255 * gamma_correct(white[lidx], gamma));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
|
int lidx = idx(s, i);
|
||||||
sk6812_set_color(&sk6812, s, i,
|
sk6812_set_color(&sk6812, s, i,
|
||||||
255 * gamma_correct(red[i], gamma),
|
255 * gamma_correct(red[lidx], gamma),
|
||||||
255 * gamma_correct(green[i], gamma),
|
255 * gamma_correct(green[lidx], gamma),
|
||||||
255 * gamma_correct(blue[i], gamma),
|
255 * gamma_correct(blue[lidx], gamma),
|
||||||
255 * gamma_correct(white[i], gamma));
|
255 * gamma_correct(white[lidx], gamma));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,7 +285,7 @@ int main(int argc, char **argv) {
|
||||||
printf("Idle for 1 second -> stopping updates.\n");
|
printf("Idle for 1 second -> stopping updates.\n");
|
||||||
|
|
||||||
for(i = 0; i < num_modules; i++) {
|
for(i = 0; i < num_modules; i++) {
|
||||||
for(int s = 0; s < NUM_SK6812; s++) {
|
for(int s = 0; s < num_strips; s++) {
|
||||||
sk6812_fade_color(&sk6812, s, i, 0, 0, 0, 20);
|
sk6812_fade_color(&sk6812, s, i, 0, 0, 0, 20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,21 +301,19 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
nextFrame += LED_INTERVAL;
|
nextFrame += LED_INTERVAL;
|
||||||
sleep_until(nextFrame);
|
sleep_until(nextFrame);
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < NUM_SK6812; i++) {
|
|
||||||
sk6812_shutdown(&sk6812);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sk6812_shutdown(&sk6812);
|
||||||
|
|
||||||
// free arrays
|
// free arrays
|
||||||
free(red);
|
free(red);
|
||||||
free(green);
|
free(green);
|
||||||
free(blue);
|
free(blue);
|
||||||
free(white);
|
free(white);
|
||||||
|
|
||||||
pthread_join(fftThread, NULL);
|
pthread_join(fftThread, NULL);
|
||||||
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
2
old_scripts/README.txt
Normal file
2
old_scripts/README.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
The scripts in this directory are no longer compatible with the current API and
|
||||||
|
are preserved just for their algorithms.
|
206
old_scripts/flame.lua
Normal file
206
old_scripts/flame.lua
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
COOLDOWN_FACTOR = 0.9998
|
||||||
|
OVERDRIVE = 1.70
|
||||||
|
EXPONENT = 1.5
|
||||||
|
W_EXPONENT = 2.2
|
||||||
|
|
||||||
|
M = 10.0 -- mass
|
||||||
|
D = 1 -- spring strength
|
||||||
|
DAMPING = {} -- filled in init()
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
--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]
|
||||||
|
|
||||||
|
--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 i = 1,num_modules do
|
||||||
|
red[i] = limit(OVERDRIVE * r_tmp[i+1]^EXPONENT)
|
||||||
|
green[i] = limit(OVERDRIVE * g_tmp[i+1]^EXPONENT)
|
||||||
|
blue[i] = limit(OVERDRIVE * b_tmp[i+1]^EXPONENT)
|
||||||
|
white[i] = limit(OVERDRIVE * w_tmp[i+1]^W_EXPONENT)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- return the 4 color arrays
|
||||||
|
return red, green, blue, white
|
||||||
|
end
|
||||||
|
|
||||||
|
function init(nmod, cmod)
|
||||||
|
num_modules = nmod
|
||||||
|
center_module = nmod --cmod
|
||||||
|
|
||||||
|
num_masses = nmod+1 --math.floor(nmod/2)
|
||||||
|
excitement_pos = 1
|
||||||
|
|
||||||
|
for i = 1,nmod 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
|
||||||
|
|
||||||
|
DAMPING[i] = 1 - 0.15 * math.abs((i - excitement_pos) / num_masses)^2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- don't use fading
|
||||||
|
return 0
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#dd if=/tmp/mpd.fifo bs=1024 | ./musiclight2
|
#dd if=/tmp/mpd.fifo bs=1024 | ./musiclight2
|
||||||
./musiclight2 $* < /tmp/mpd.fifo
|
./musiclight2 $* < /tmp/musiclight.fifo
|
||||||
|
|
6
utils.c
6
utils.c
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
extern int num_modules;
|
||||||
|
|
||||||
double get_hires_time(void) {
|
double get_hires_time(void) {
|
||||||
struct timespec clk;
|
struct timespec clk;
|
||||||
clock_gettime(CLOCK_REALTIME, &clk);
|
clock_gettime(CLOCK_REALTIME, &clk);
|
||||||
|
@ -41,3 +43,7 @@ void sleep_until(double hires_time) {
|
||||||
} while(ret == EINTR);
|
} while(ret == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int idx(int strip, int module)
|
||||||
|
{
|
||||||
|
return strip * num_modules + module;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue