Browse Source

Added lua scripting capabilities

- basic configuration is now done via a lua script
- all the animation is generated by a lua script (see pulsetunnel.lua
  and vumeter.lua for examples)
- basic calculations (FFT, RMS) are done in C and accessible on demand
  from the lua scripts
lua
Thomas Kolb 7 years ago
parent
commit
d4a2e7ef4c
16 changed files with 481 additions and 120 deletions
  1. 7
    4
      Makefile
  2. 0
    7
      config.h
  3. 7
    0
      config.lua
  4. 73
    0
      lua_utils.c
  5. 20
    0
      lua_utils.h
  6. 73
    0
      lua_wrappers.c
  7. 21
    0
      lua_wrappers.h
  8. 118
    102
      main.c
  9. 70
    0
      pulsetunnel.lua
  10. 1
    1
      run_alsa.sh
  11. 1
    1
      run_mpd.sh
  12. 2
    2
      run_pa.sh
  13. 1
    1
      run_remote.sh
  14. 85
    0
      vumeter.lua
  15. 1
    1
      ws2801.c
  16. 1
    1
      ws2801.h

+ 7
- 4
Makefile View File

@@ -1,10 +1,13 @@
1
+LUA_CFLAGS=$(shell pkg-config --cflags lua)
2
+LUA_LIBS=$(shell pkg-config --libs lua)
3
+
1 4
 CC=gcc
2
-CFLAGS+=-O3 -Wall -march=native -pedantic -std=c99 -D_POSIX_C_SOURCE=20120607L -D_XOPEN_SOURCE
3
-LIBS=-lm -lpthread -lrt
5
+CFLAGS+=-O2 -Wall -march=native -pedantic -std=c99 -D_POSIX_C_SOURCE=20120607L -D_XOPEN_SOURCE $(LUA_CFLAGS)
6
+LIBS=-lm -lpthread -lrt $(LUA_LIBS)
4 7
 
5 8
 TARGET=musiclight2
6
-SOURCE=main.c fft.c utils.c ws2801.c
7
-DEPS=config.h fft.h utils.h ws2801.h
9
+SOURCE=main.c fft.c utils.c ws2801.c lua_utils.c lua_wrappers.c
10
+DEPS=config.h fft.h utils.h ws2801.h lua_utils.h lua_wrappers.h
8 11
 
9 12
 OBJ=$(patsubst %.c, %.o, $(SOURCE))
10 13
 

+ 0
- 7
config.h View File

@@ -30,9 +30,6 @@
30 30
 // update rate for the led strip (in seconds)
31 31
 #define LED_INTERVAL 0.03
32 32
 
33
-// number of modules in LED strip
34
-#define NUM_MODULES 20
35
-
36 33
 // frequency ranges for the base colors
37 34
 #define RED_MIN_FREQ 0
38 35
 #define RED_MAX_FREQ 400
@@ -43,10 +40,6 @@
43 40
 
44 41
 #define COLOR_MAX_REDUCTION_FACTOR 0.9998
45 42
 
46
-#define CENTER_MODULE 10
47
-
48
-#define GAMMA 2.0
49
-
50 43
 // sample data types
51 44
 typedef int16_t sample;
52 45
 typedef int64_t sample_sum;

+ 7
- 0
config.lua View File

@@ -0,0 +1,7 @@
1
+WS2801_HOST = "192.168.23.222"
2
+WS2801_PORT = 2703
3
+
4
+NUM_MODULES = 20
5
+CENTER_MODULE = 10
6
+
7
+GAMMA = 2.0

+ 73
- 0
lua_utils.c View File

@@ -0,0 +1,73 @@
1
+/*
2
+ * vim: sw=2 ts=2 expandtab
3
+ *
4
+ * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
5
+ * <cfr34k@tkolb.de> wrote this file. As long as you retain this notice you can
6
+ * do whatever you want with this stuff. If we meet some day, and you think
7
+ * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb
8
+ */
9
+
10
+#include <lua.h>
11
+#include <lualib.h>
12
+#include <lauxlib.h>
13
+
14
+#include "lua_utils.h"
15
+
16
+void lua_showerror(lua_State *L, const char *msg) {
17
+  fprintf(stderr, "\nLUA ERROR:\n  %s: %s\n\n",
18
+      msg, lua_tostring(L, -1));
19
+}
20
+
21
+void lua_pushdoublearray(lua_State *L, double *numbers, size_t len) {
22
+  size_t i;
23
+
24
+  // create an empty table
25
+  lua_createtable(L, len, 0);
26
+
27
+  for(i = 0; i < len; i++) {
28
+    // push key and value
29
+    lua_pushnumber(L, i+1); // lua arrays count from 1
30
+    lua_pushnumber(L, numbers[i]);
31
+
32
+    // store the values in the table
33
+    lua_settable(L, -3);
34
+  }
35
+}
36
+
37
+void lua_pushsamplearray(lua_State *L, sample *numbers, size_t len) {
38
+  size_t i;
39
+
40
+  // create an empty table
41
+  lua_createtable(L, len, 0);
42
+
43
+  for(i = 0; i < len; i++) {
44
+    // push key and value
45
+    lua_pushnumber(L, i+1); // lua arrays count from 1
46
+    lua_pushnumber(L, numbers[i]);
47
+
48
+    // store the values in the table
49
+    lua_settable(L, -3);
50
+  }
51
+}
52
+
53
+void lua_readdoublearray(lua_State *L, double *numbers, size_t len) {
54
+  size_t k;
55
+  double v;
56
+
57
+  // go to the top of the stack
58
+  lua_pushnil(L);
59
+
60
+  while(lua_next(L, -2)) {
61
+    v = lua_tonumber(L, -1);
62
+    lua_pop(L, 1);
63
+    k = lua_tointeger(L, -1);
64
+
65
+    if(k > len || k < 1) {
66
+      fprintf(stderr, "Warning: Lua index (%u) is out of C array range (%u)!\n", k, len);
67
+    } else {
68
+      numbers[k-1] = v;
69
+    }
70
+  }
71
+
72
+  lua_pop(L, 1);
73
+}

+ 20
- 0
lua_utils.h View File

@@ -0,0 +1,20 @@
1
+/*
2
+ * vim: sw=2 ts=2 expandtab
3
+ *
4
+ * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
5
+ * <cfr34k@tkolb.de> wrote this file. As long as you retain this notice you can
6
+ * do whatever you want with this stuff. If we meet some day, and you think
7
+ * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb
8
+ */
9
+
10
+#ifndef LUA_UTILS_H
11
+#define LUA_UTILS_H
12
+
13
+#include "config.h"
14
+
15
+void lua_showerror(lua_State *L, const char *msg);
16
+void lua_pushdoublearray(lua_State *L, double *numbers, size_t len);
17
+void lua_pushsamplearray(lua_State *L, sample *numbers, size_t len);
18
+void lua_readdoublearray(lua_State *L, double *numbers, size_t len);
19
+
20
+#endif // LUA_UTILS_H

+ 73
- 0
lua_wrappers.c View File

@@ -0,0 +1,73 @@
1
+/*
2
+ * vim: sw=2 ts=2 expandtab
3
+ *
4
+ * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
5
+ * <cfr34k@tkolb.de> wrote this file. As long as you retain this notice you can
6
+ * do whatever you want with this stuff. If we meet some day, and you think
7
+ * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb
8
+ */
9
+
10
+#include <semaphore.h>
11
+
12
+#include <lua.h>
13
+#include <lualib.h>
14
+#include <lauxlib.h>
15
+
16
+#include "fft.h"
17
+
18
+#include "config.h"
19
+
20
+#include "lua_utils.h"
21
+#include "lua_wrappers.h"
22
+
23
+extern sem_t  fftSemaphore;
24
+extern double fft[BLOCK_LEN];
25
+extern sample signal[BLOCK_LEN];
26
+extern double rms;
27
+
28
+static int l_get_energy_in_band(lua_State *L) {
29
+  int lowerFreq, higherFreq;
30
+
31
+  luaL_checktype(L, 1, LUA_TNUMBER);
32
+  lowerFreq = lua_tointeger(L, 1);
33
+
34
+  luaL_checktype(L, 2, LUA_TNUMBER);
35
+  higherFreq = lua_tointeger(L, 2);
36
+
37
+  sem_wait(&fftSemaphore);
38
+  lua_pushnumber(L, get_energy_in_band(fft, lowerFreq, higherFreq));
39
+  sem_post(&fftSemaphore);
40
+
41
+  return 1; // number of arguments
42
+}
43
+
44
+static int l_get_fft(lua_State *L) {
45
+  sem_wait(&fftSemaphore);
46
+  lua_pushdoublearray(L, fft, BLOCK_LEN);
47
+  sem_post(&fftSemaphore);
48
+
49
+  return 1; // number of return values
50
+}
51
+
52
+static int l_get_signal(lua_State *L) {
53
+  sem_wait(&fftSemaphore);
54
+  lua_pushsamplearray(L, signal, BLOCK_LEN);
55
+  sem_post(&fftSemaphore);
56
+
57
+  return 1; // number of return values
58
+}
59
+
60
+static int l_get_rms(lua_State *L) {
61
+  sem_wait(&fftSemaphore);
62
+  lua_pushnumber(L, rms);
63
+  sem_post(&fftSemaphore);
64
+
65
+  return 1; // number of return values
66
+}
67
+
68
+void lua_register_funcs(lua_State *L) {
69
+  lua_register(L, "get_energy_in_band", l_get_energy_in_band);
70
+  lua_register(L, "get_fft", l_get_fft);
71
+  lua_register(L, "get_signal", l_get_signal);
72
+  lua_register(L, "get_rms", l_get_rms);
73
+}

+ 21
- 0
lua_wrappers.h View File

@@ -0,0 +1,21 @@
1
+/*
2
+ * vim: sw=2 ts=2 expandtab
3
+ *
4
+ * THE PIZZA-WARE LICENSE" (derived from "THE BEER-WARE LICENCE"):
5
+ * <cfr34k@tkolb.de> wrote this file. As long as you retain this notice you can
6
+ * do whatever you want with this stuff. If we meet some day, and you think
7
+ * this stuff is worth it, you can buy me a pizza in return. - Thomas Kolb
8
+ */
9
+
10
+#ifndef LUA_WRAPPERS_H
11
+#define LUA_WRAPPERS_H
12
+
13
+void lua_register_funcs(lua_State *L);
14
+
15
+/*
16
+static int l_get_energy_in_band(lua_State *L);
17
+static int l_get_fft(lua_State *L);
18
+static int l_get_signal(lua_State *L);
19
+*/
20
+
21
+#endif // LUA_WRAPPERS_H

+ 118
- 102
main.c View File

@@ -14,6 +14,14 @@
14 14
 #include <math.h>
15 15
 #include <string.h>
16 16
 #include <stdint.h>
17
+#include <malloc.h>
18
+
19
+#include <lua.h>
20
+#include <lualib.h>
21
+#include <lauxlib.h>
22
+
23
+#include "lua_utils.h"
24
+#include "lua_wrappers.h"
17 25
 
18 26
 #include "fft.h"
19 27
 #include "utils.h"
@@ -27,12 +35,9 @@
27 35
 // Number of new samples put into the buffer each frame
28 36
 #define READ_SAMPLES (BLOCK_LEN / BUFFER_PARTS)
29 37
 
30
-#define COLORBUF_SIZE (2*(NUM_MODULES+1))
31
-#define CENTER_POS (2*CENTER_MODULE)
32
-
33 38
 double fft[BLOCK_LEN];
39
+sample signal[BLOCK_LEN];
34 40
 double rms;
35
-double redEnergy, greenEnergy, blueEnergy;
36 41
 double lastUpdateTime = 0;
37 42
 
38 43
 sem_t  fftSemaphore;
@@ -72,7 +77,7 @@ void* fft_thread(void *param) {
72 77
 
73 78
     tmpRMS = 0;
74 79
     for(i = 0; i < BLOCK_LEN; i++) {
75
-      tmpRMS += block[i]*block[i];
80
+      tmpRMS += buffer[i]*buffer[i];
76 81
     }
77 82
     tmpRMS = sqrt(tmpRMS/BLOCK_LEN);
78 83
 
@@ -80,10 +85,8 @@ void* fft_thread(void *param) {
80 85
     sem_wait(&fftSemaphore);
81 86
 
82 87
     memcpy(fft, tmpFFT, sizeof(fft));
88
+    memcpy(signal, buffer, sizeof(signal));
83 89
     rms = tmpRMS;
84
-    redEnergy = get_energy_in_band(fft, RED_MIN_FREQ, RED_MAX_FREQ);
85
-    greenEnergy = get_energy_in_band(fft, GREEN_MIN_FREQ, GREEN_MAX_FREQ);
86
-    blueEnergy = get_energy_in_band(fft, BLUE_MIN_FREQ, BLUE_MAX_FREQ);
87 90
 
88 91
 		curTime = get_hires_time();
89 92
     lastUpdateTime = curTime;
@@ -113,64 +116,97 @@ void* fft_thread(void *param) {
113 116
 	return NULL;
114 117
 }
115 118
 
116
-double gamma_correct(double d) {
117
-  return pow(d, GAMMA);
119
+double gamma_correct(double d, double gamma) {
120
+  return pow(d, gamma);
118 121
 }
119 122
 
120
-void text_bar(double fill) {
121
-  int fillCnt = 10 * fill;
122
-  int i;
123
+int main(int argc, char **argv) {
124
+  double nextFrame = get_hires_time() + LED_INTERVAL;
123 125
 
124
-  for(i = 0; i < fillCnt; i++) {
125
-    printf("|");
126
-  }
126
+	int i;
127
+	pthread_t fftThread;
128
+
129
+  int active = 1;
130
+
131
+  double *red;
132
+  double *green;
133
+  double *blue;
134
+
135
+  int useFading, fadeStep;
127 136
 
128
-  for(; i < 10; i++) {
129
-    printf("-");
137
+  if(argc < 2) {
138
+    fprintf(stderr, "LUA script file must be given as command line argument!\n");
139
+    return 1;
130 140
   }
131
-}
132 141
 
133
-double weighted_avg(uint8_t colorBuf[COLORBUF_SIZE][3], int channel, int centerPos) {
134
-  return 0.20 * colorBuf[centerPos - 1][channel] +
135
-         0.60 * colorBuf[centerPos][channel] +
136
-         0.20 * colorBuf[centerPos + 1][channel];
137
-}
142
+  // initialize lua
143
+  lua_State *L = lua_open();
138 144
 
139
-void show_status(double curRed, double maxRed, double curGreen, double maxGreen, double curBlue, double maxBlue) {
140
-  printf("\r");
145
+  // load the lua libraries
146
+  luaL_openlibs(L);
141 147
 
142
-  printf("[\033[31m");
143
-  text_bar(curRed / maxRed);
144
-  printf("\033[0m] ");
145
-  printf("\033[1;31m%7.2e\033[0m ", maxRed / (RED_MAX_FREQ - RED_MIN_FREQ));
148
+  // register local functions
149
+  lua_register_funcs(L);
146 150
 
147
-  printf("[\033[32m");
148
-  text_bar(curGreen / maxGreen);
149
-  printf("\033[0m] ");
150
-  printf("\033[1;32m%7.2e\033[0m ", maxGreen / (GREEN_MAX_FREQ - GREEN_MIN_FREQ));
151
+  // load the configuration from "config.lua"
152
+  if(luaL_dofile(L, "config.lua")) {
153
+    lua_showerror(L, "luaL_dofile(config.lua) failed.");
154
+    return 1;
155
+  }
151 156
 
152
-  printf("[\033[34m");
153
-  text_bar(curBlue / maxBlue);
154
-  printf("\033[0m] ");
155
-  printf("\033[1;34m%7.2e\033[0m ", maxBlue / (BLUE_MAX_FREQ - BLUE_MIN_FREQ));
157
+  lua_getglobal(L, "WS2801_HOST");
158
+  if(!lua_isstring(L, -1)) return 2;
159
+  const char *host = lua_tostring(L, -1);
156 160
 
157
-  fflush(stdout);
158
-}
161
+  lua_getglobal(L, "WS2801_PORT");
162
+  if(!lua_isnumber(L, -1)) return 2;
163
+  unsigned short port = lua_tointeger(L, -1);
159 164
 
160
-int main(int argc, char **argv) {
161
-  double nextFrame = get_hires_time() + LED_INTERVAL;
165
+  lua_getglobal(L, "GAMMA");
166
+  if(!lua_isnumber(L, -1)) return 2;
167
+  double gamma = lua_tonumber(L, -1);
162 168
 
163
-	int i, j;
164
-	pthread_t fftThread;
169
+  lua_getglobal(L, "NUM_MODULES");
170
+  if(!lua_isnumber(L, -1)) return 2;
171
+  int num_modules = lua_tointeger(L, -1);
165 172
 
166
-  int active = 1;
173
+  lua_getglobal(L, "CENTER_MODULE");
174
+  if(!lua_isnumber(L, -1)) return 2;
175
+  int center_module = lua_tointeger(L, -1);
176
+
177
+  // allocate arrays
178
+  red = malloc(num_modules * sizeof(double));
179
+  green = malloc(num_modules * sizeof(double));
180
+  blue = malloc(num_modules * sizeof(double));
167 181
 
168
-  uint8_t colorBuf[COLORBUF_SIZE][3];
182
+  // load and initialize the script
183
+  if(luaL_loadfile(L, argv[1])) {
184
+    lua_showerror(L, "luaL_loadfile(cmdline_argument) failed.");
185
+  }
169 186
 
170
-  double curRedEnergy, curGreenEnergy, curBlueEnergy;
171
-  double maxRedEnergy = 1, maxGreenEnergy = 1, maxBlueEnergy = 1;
187
+  // priming call: read the lua file to make functions known
188
+  if(lua_pcall(L, 0, 0, 0)) {
189
+    lua_showerror(L, "lua_pcall failed.");
190
+  }
172 191
 
173
-  memset(colorBuf, 0, sizeof(colorBuf));
192
+  // call the init function
193
+  lua_getglobal(L, "init");
194
+  lua_pushnumber(L, num_modules);
195
+  lua_pushnumber(L, center_module);
196
+  if(lua_pcall(L, 2, 1, 0)) {
197
+    lua_showerror(L, "lua_pcall(init) failed.");
198
+  }
199
+
200
+  fadeStep = lua_tointeger(L, -1);
201
+  useFading = fadeStep > 0;
202
+  if(useFading) {
203
+    ws2801_set_fadestep(fadeStep);
204
+    printf("Fading enabled with fadestep %i.\n", fadeStep);
205
+  }
206
+
207
+  // initialize the WS2801 library
208
+  printf("Connecting to %s:%i\n", host, port);
209
+  ws2801_init(host, port);
174 210
 
175 211
 	// create semaphores
176 212
 	sem_init(&fftSemaphore, 0, 1);
@@ -178,68 +214,41 @@ int main(int argc, char **argv) {
178 214
 	// run the fft thread
179 215
 	pthread_create(&fftThread, NULL, fft_thread, NULL);
180 216
 
181
-  ws2801_init(HOST, PORT);
182
-
183 217
 	while(running) {
184
-    for(i = COLORBUF_SIZE-1; i >= 0; i--) {
185
-      int pos = CENTER_POS + i;
186
-      if(pos < COLORBUF_SIZE-1) {
187
-        for(j = 0; j < 3; j++) {
188
-          colorBuf[pos][j] = colorBuf[pos - 1][j];
189
-        }
190
-      }
191
-
192
-      pos = CENTER_POS - i;
193
-      if(pos >= 0) {
194
-        for(j = 0; j < 3; j++) {
195
-          colorBuf[pos][j] = colorBuf[pos + 1][j];
196
-        }
197
-      }
198
-    }
199
-
200 218
     if(active) {
201
-      sem_wait(&fftSemaphore);
202
-      curRedEnergy = redEnergy;
203
-      curGreenEnergy = greenEnergy;
204
-      curBlueEnergy = blueEnergy;
205
-      sem_post(&fftSemaphore);
206
-
207
-      maxRedEnergy *= COLOR_MAX_REDUCTION_FACTOR;
208
-      if(curRedEnergy > maxRedEnergy) {
209
-        maxRedEnergy = curRedEnergy;
219
+      // call the periodic() function from LUA
220
+      lua_getglobal(L, "periodic");
221
+      if(lua_pcall(L, 0, 3, 0)) { // no arguments, 3 return values
222
+        lua_showerror(L, "lua_pcall(periodic) failed.");
210 223
       }
211 224
 
212
-      maxGreenEnergy *= COLOR_MAX_REDUCTION_FACTOR;
213
-      if(curGreenEnergy > maxGreenEnergy) {
214
-        maxGreenEnergy = curGreenEnergy;
215
-      }
216
-
217
-      maxBlueEnergy *= COLOR_MAX_REDUCTION_FACTOR;
218
-      if(curBlueEnergy > maxBlueEnergy) {
219
-        maxBlueEnergy = curBlueEnergy;
220
-      }
221
-
222
-      colorBuf[CENTER_POS][0] = 255 * gamma_correct(curRedEnergy / maxRedEnergy);
223
-      colorBuf[CENTER_POS][1] = 255 * gamma_correct(curGreenEnergy / maxGreenEnergy);
224
-      colorBuf[CENTER_POS][2] = 255 * gamma_correct(curBlueEnergy / maxBlueEnergy);
225
-
226
-      /*
227
-      show_status(curRedEnergy, maxRedEnergy, curGreenEnergy, maxGreenEnergy,
228
-          curBlueEnergy, maxBlueEnergy);
229
-      */
230
-
231
-      for(i = 0; i < NUM_MODULES; i++) {
232
-        ws2801_set_color(i,
233
-            weighted_avg(colorBuf, 0, 2 * i + 1),
234
-            weighted_avg(colorBuf, 1, 2 * i + 1),
235
-            weighted_avg(colorBuf, 2, 2 * i + 1));
225
+      // read the return values (reverse order, as lua uses a stack)
226
+      lua_readdoublearray(L, blue, num_modules);
227
+      lua_readdoublearray(L, green, num_modules);
228
+      lua_readdoublearray(L, red, num_modules);
229
+
230
+      if(useFading) {
231
+        for(i = 0; i < num_modules; i++) {
232
+          ws2801_fade_color(i,
233
+              255 * gamma_correct(red[i], gamma),
234
+              255 * gamma_correct(green[i], gamma),
235
+              255 * gamma_correct(blue[i], gamma));
236
+        }
237
+        ws2801_commit();
238
+      } else {
239
+        for(i = 0; i < num_modules; i++) {
240
+          ws2801_set_color(i,
241
+              255 * gamma_correct(red[i], gamma),
242
+              255 * gamma_correct(green[i], gamma),
243
+              255 * gamma_correct(blue[i], gamma));
244
+        }
245
+        ws2801_commit();
236 246
       }
237
-      ws2801_commit();
238 247
 
239 248
       if(lastUpdateTime < nextFrame - 1) {
240 249
         printf("Idle for 1 second -> stopping updates.\n");
241 250
 
242
-        for(i = 0; i < NUM_MODULES; i++) {
251
+        for(i = 0; i < num_modules; i++) {
243 252
           ws2801_fade_color(i, 20, 20, 20);
244 253
         }
245 254
         ws2801_commit();
@@ -257,7 +266,14 @@ int main(int argc, char **argv) {
257 266
 
258 267
   ws2801_shutdown();
259 268
 
269
+  // free arrays
270
+  free(red);
271
+  free(green);
272
+  free(blue);
273
+
260 274
 	pthread_join(fftThread, NULL);
261 275
 
276
+  lua_close(L);
277
+
262 278
 	return 0;
263 279
 }

+ 70
- 0
pulsetunnel.lua View File

@@ -0,0 +1,70 @@
1
+COOLDOWN_FACTOR = 0.9998
2
+
3
+num_modules = 20
4
+center_module = 10
5
+
6
+-- maximum energy values for each band
7
+maxRedEnergy = 1
8
+maxGreenEnergy = 1
9
+maxBlueEnergy = 1
10
+
11
+-- output color buffers
12
+red = {}
13
+green = {}
14
+blue = {}
15
+
16
+function periodic()
17
+  local redEnergy = get_energy_in_band(0, 400);
18
+  local greenEnergy = get_energy_in_band(400, 4000);
19
+  local blueEnergy = get_energy_in_band(4000, 22000);
20
+
21
+  maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
22
+  if redEnergy > maxRedEnergy then
23
+    maxRedEnergy = redEnergy
24
+  end
25
+
26
+  maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR
27
+  if greenEnergy > maxGreenEnergy then
28
+    maxGreenEnergy = greenEnergy
29
+  end
30
+
31
+  maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR
32
+  if blueEnergy > maxBlueEnergy then
33
+    maxBlueEnergy = blueEnergy
34
+  end
35
+
36
+  -- move the color buffers on by one in each direction
37
+  for i = 2,center_module,1 do
38
+    red[i-1]   = red[i]
39
+    green[i-1] = green[i]
40
+    blue[i-1]  = blue[i]
41
+  end
42
+
43
+  for i = num_modules-1,center_module,-1 do
44
+    red[i+1]   = red[i]
45
+    green[i+1] = green[i]
46
+    blue[i+1]  = blue[i]
47
+  end
48
+
49
+  -- set the new value for the center module
50
+  red[center_module] = redEnergy / maxRedEnergy
51
+  green[center_module] = greenEnergy / maxGreenEnergy
52
+  blue[center_module] = blueEnergy / maxBlueEnergy
53
+
54
+  -- return the 3 color arrays
55
+  return red, green, blue
56
+end
57
+
58
+function init(nmod, cmod)
59
+  num_modules = nmod
60
+  center_module = cmod
61
+
62
+  for i = 1,nmod do
63
+    red[i] = 0
64
+    green[i] = 0
65
+    blue[i] = 0
66
+  end
67
+
68
+  -- don't use fading
69
+  return 0
70
+end

+ 1
- 1
run_alsa.sh View File

@@ -1,3 +1,3 @@
1 1
 #!/bin/sh
2 2
 
3
-arecord -c 1 -f s16 -r 22050 | ./rtfft
3
+arecord -c 1 -f s16 -r 22050 | ./musiclight2 $*

+ 1
- 1
run_mpd.sh View File

@@ -1,4 +1,4 @@
1 1
 #!/bin/sh
2 2
 
3 3
 #dd if=/tmp/mpd.fifo bs=1024 | ./musiclight2
4
-./musiclight2 < /tmp/mpd.fifo
4
+./musiclight2 $* < /tmp/mpd.fifo

+ 2
- 2
run_pa.sh View File

@@ -5,12 +5,12 @@
5 5
 case $1 in
6 6
   mic)
7 7
     #mikro
8
-    parec -d "alsa_input.pci-0000_00_1b.0.analog-stereo" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2
8
+    parec -d "alsa_input.pci-0000_00_1b.0.analog-stereo" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $*
9 9
     ;;
10 10
 
11 11
   *)
12 12
     # soundkarte
13
-    parec -d "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2
13
+    parec -d "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" --raw --rate=44100 --channels=1 --format=s16 | ./musiclight2 $*
14 14
     ;;
15 15
 esac
16 16
 

+ 1
- 1
run_remote.sh View File

@@ -1,3 +1,3 @@
1 1
 #!/bin/sh
2 2
 
3
-nc -l -p 12345 | ./musiclight2
3
+nc -l -p 12345 | ./musiclight2 $*

+ 85
- 0
vumeter.lua View File

@@ -0,0 +1,85 @@
1
+COOLDOWN_FACTOR = 0.9998
2
+FACTOR = 0.2
3
+
4
+num_modules = 20
5
+center_module = 10
6
+
7
+-- maximum energy values for each band
8
+maxRedEnergy = 1
9
+maxGreenEnergy = 1
10
+maxBlueEnergy = 1
11
+maxRMS = 1
12
+
13
+-- output color buffers
14
+red = {}
15
+green = {}
16
+blue = {}
17
+
18
+function periodic()
19
+  local redEnergy = get_energy_in_band(0, 400);
20
+  local greenEnergy = get_energy_in_band(400, 4000);
21
+  local blueEnergy = get_energy_in_band(4000, 22000);
22
+  local rms = get_rms();
23
+
24
+  maxRedEnergy = maxRedEnergy * COOLDOWN_FACTOR
25
+  if redEnergy > maxRedEnergy then
26
+    maxRedEnergy = redEnergy
27
+  end
28
+
29
+  maxGreenEnergy = maxGreenEnergy * COOLDOWN_FACTOR
30
+  if greenEnergy > maxGreenEnergy then
31
+    maxGreenEnergy = greenEnergy
32
+  end
33
+
34
+  maxBlueEnergy = maxBlueEnergy * COOLDOWN_FACTOR
35
+  if blueEnergy > maxBlueEnergy then
36
+    maxBlueEnergy = blueEnergy
37
+  end
38
+
39
+  maxRMS = maxRMS * COOLDOWN_FACTOR
40
+  if rms > maxRMS then
41
+    maxRMS = rms
42
+  end
43
+
44
+  local brightness = rms / maxRMS
45
+
46
+  for i = 1,num_modules do
47
+    if i <= num_modules * redEnergy / maxRedEnergy then
48
+      redTarget = brightness
49
+    else
50
+      redTarget = 0
51
+    end
52
+    red[i] = (1 - FACTOR) * red[i] + FACTOR * redTarget;
53
+
54
+    if i <= num_modules * greenEnergy / maxGreenEnergy then
55
+      greenTarget = brightness
56
+    else
57
+      greenTarget = 0
58
+    end
59
+    green[i] = (1 - FACTOR) * green[i] + FACTOR * greenTarget;
60
+
61
+    if i <= num_modules * blueEnergy / maxBlueEnergy then
62
+      blueTarget = brightness
63
+    else
64
+      blueTarget = 0
65
+    end
66
+    blue[i] = (1 - FACTOR) * blue[i] + FACTOR * blueTarget;
67
+  end
68
+
69
+  -- return the 3 color arrays
70
+  return red, green, blue
71
+end
72
+
73
+function init(nmod, cmod)
74
+  num_modules = nmod
75
+  center_module = cmod
76
+
77
+  for i = 1,nmod do
78
+    red[i] = 0
79
+    green[i] = 0
80
+    blue[i] = 0
81
+  end
82
+
83
+  -- fadestep (0 = no fading)
84
+  return 0
85
+end

+ 1
- 1
ws2801.c View File

@@ -32,7 +32,7 @@ struct WS2801Packet packetQueue[50];
32 32
 int queueIndex = 0;
33 33
 
34 34
 // creates the socket needed for steering the LED strip
35
-int ws2801_init(char *host, unsigned short port) {
35
+int ws2801_init(const char *host, unsigned short port) {
36 36
   struct addrinfo  hints;
37 37
   struct addrinfo *result;
38 38
   char portstr[6];

+ 1
- 1
ws2801.h View File

@@ -10,7 +10,7 @@
10 10
 #ifndef WS2801_H
11 11
 #define WS2801_H
12 12
 
13
-int ws2801_init(char *host, unsigned short port);
13
+int ws2801_init(const char *host, unsigned short port);
14 14
 void ws2801_set_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);
15 15
 void ws2801_fade_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);
16 16
 void ws2801_add_color(uint8_t module, uint8_t r, uint8_t g, uint8_t b);

Loading…
Cancel
Save