summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2012-06-17 09:28:18 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2012-06-17 09:28:18 +0000
commit96d4d223a6e2790e6269cd3b19b4944d99d61eb3 (patch)
treec62d0a1e02e7e9fe4a4415a6eeafb8ea35d10bf4
parent797149c5a9ee0c7c70947f72cbaece5efd3dd687 (diff)
download2012-violon-leds-96d4d223a6e2790e6269cd3b19b4944d99d61eb3.tar.gz
2012-violon-leds-96d4d223a6e2790e6269cd3b19b4944d99d61eb3.tar.bz2
2012-violon-leds-96d4d223a6e2790e6269cd3b19b4944d99d61eb3.zip
Premiere integraation de la partie DMX. Parfois le programme rate l'initialisation ou semble freezé !!
Mais l'iilumination fonctionne. La réactivité est géniale, il y a du boulot pour filtrer le plancher bruit et il y a encore un "flicker" pas sympa, je pense que ça a encore à voir avec la taille des buffers passés à la FFT... C'est très con ce pb... Les tests de cette version ont été faits avec le Netbook MSI (Ludo). git-svn-id: file:///var/svn/2012-violon-leds/trunk@21 6be1fa4d-33ac-4c33-becc-79fcb3794bb6
-rw-r--r--src/Makefile5
-rw-r--r--src/capture.c2
-rw-r--r--src/compute.c15
-rw-r--r--src/illuminate.c164
-rw-r--r--src/illuminate.h8
-rw-r--r--src/music2light.c7
-rw-r--r--src/win_main.c12
7 files changed, 198 insertions, 15 deletions
diff --git a/src/Makefile b/src/Makefile
index 67d7035..6b93d4c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,7 +4,10 @@ LDFLAGS=-Werror -g
EXEC=music2light
CFLAGS+=$(shell pkg-config --cflags gtk+-2.0 gthread-2.0 libpulse)
-LDFLAGS+=-lm $(shell pkg-config --libs gtk+-2.0 gthread-2.0 libpulse)
+# Maths for FFT related code, libftdi is the driver for USB2DMX module, rt is for ftdi
+LDFLAGS+=-lm -lftdi
+# -lrt
+LDFLAGS+=$(shell pkg-config --libs gtk+-2.0 gthread-2.0 libpulse)
SRC= $(wildcard *.c)
OBJ= $(SRC:.c=.o)
diff --git a/src/capture.c b/src/capture.c
index e8ca2fd..14e7abf 100644
--- a/src/capture.c
+++ b/src/capture.c
@@ -124,7 +124,7 @@ pa_stream *create_stream(pa_context *c, const pa_source_info *si) {
.tlength=1024,
.prebuf=-1,
.minreq=-1,
- // .minreq=256, //For FFT calculus
+ //.minreq=256, //For FFT calculus
.fragsize=512
};
diff --git a/src/compute.c b/src/compute.c
index 272d6f8..54d6929 100644
--- a/src/compute.c
+++ b/src/compute.c
@@ -26,7 +26,9 @@ float compute_level(const float *data, size_t nsamples, int rate) {
}
if (nsamples < MIN_SAMPLES) {
printf("WARN : nsamples < MIN_SAMPLES : %i >= %i\n", nsamples, MIN_SAMPLES);
- // Replicate with symmetry the sound to obtain an input buffer of the minimal len
+ return -120.f;
+ }
+ /* Replicate with symmetry the sound to obtain an input buffer of the minimal len
for (i=0;i<MIN_SAMPLES;i++) {
if ( (i/nsamples)%2==1 )
input[i]=data[i]; // First channel only
@@ -34,11 +36,11 @@ float compute_level(const float *data, size_t nsamples, int rate) {
input[i]=data[nsamples-i-1];
}
nsamples=MIN_SAMPLES;
- } else {
+ } else {*/
for (i=0;i<nsamples;i++) {
input[i]=data[i]; // First channel only
}
- }
+ //}
compute_spectrum(input, nsamples, pwrspec);
@@ -99,14 +101,15 @@ void compute_spectrum(float *data, int width, float output[PSHalf]) {
void audio2hsv_1(float audio_level, float *light_h, float *light_s, float *light_v) {
static float hue=0;
- float level_norm=(50.f+audio_level)/30.f;
+ float level_norm=(38.f+audio_level)/30.f;
- if (level_norm<0.f) level_norm=0.f;
+ if (level_norm<0.0f) level_norm=0.f;
+ //if (level_norm<0.1f) level_norm=0.f; //FIXME : ici cache misere pour le tremblement sur plancher bruit
if (level_norm>1.f) level_norm=1.f;
hue=(hue+0.0002f);
if (hue>1.f) hue-=1.f;
- printf("%+3.1f %+1.3f\n", audio_level, level_norm);
+// printf("%+3.1f %+1.3f\n", audio_level, level_norm);
// Dummy code
*light_h=hue;
diff --git a/src/illuminate.c b/src/illuminate.c
new file mode 100644
index 0000000..a0f146d
--- /dev/null
+++ b/src/illuminate.c
@@ -0,0 +1,164 @@
+#include <ftdi.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "illuminate.h"
+
+// FTDI Vendor ID
+#define VID 0x0403
+// FTDI Product ID
+#define PID 0x6001
+
+#define DMX_CHANNELS 6
+//#define DMX_CHANNELS 512
+//#define DMX_FRAMETIME 24000000
+#define DMX_FRAMETIME 0
+#define DMX_BREAK 110000
+#define DMX_MAB 16000
+
+#define MAX_STR 64
+
+/*
+struct ftdi_device_list
+{
+ // pointer to next entry
+ struct ftdi_device_list *next;
+ // pointer to libusb's usb_device
+ struct usb_device *dev;
+}
+*/
+
+inline void ts_diffadd(struct timespec *res, struct timespec *a, struct timespec *b, struct timespec *c);
+void e(int res, const char *funcname, struct ftdi_context *ftdi, int exit_val);
+int dmx_universe_write(struct ftdi_context *ftdi, unsigned char *universe, int uni_len);
+
+struct ftdi_context ftdi;
+struct ftdi_device_list *devlist=NULL;
+char *manufacturer, *description, *serial;
+unsigned char universe[DMX_CHANNELS+1];
+
+int dmx_init() {
+
+ struct usb_device *dev=NULL;
+
+ struct timespec ts_to_sleep;
+
+ (void) memset(universe, 0, sizeof(universe));
+ (void) memset(&ftdi, 0, sizeof(ftdi));
+
+ manufacturer=malloc(MAX_STR);
+ description=malloc(MAX_STR);
+ serial=malloc(MAX_STR);
+
+ e(ftdi_init(&ftdi),"ftdi_init",&ftdi,10);
+ e(ftdi_usb_find_all(&ftdi, &devlist, VID, PID),"ftdi_usb_find_all",&ftdi,11);
+
+ //Always take the first device
+ if (devlist==NULL || devlist->dev==NULL) {
+ fprintf(stderr, "No usb device detected (looking for USB ID 0x%04X:0x%04X)\n", VID, PID);
+ return(2);
+ }
+ dev=devlist->dev;
+
+// fprintf(stderr, "DEBUG : next==%p\n", devlist->next);
+
+ e(ftdi_usb_get_strings(&ftdi, dev, manufacturer, MAX_STR, description, MAX_STR, serial, MAX_STR),"ftdi_usb_get_strings",&ftdi,12);
+ fprintf(stderr, "Connecting to USB device ('%s','%s','%s')\n", manufacturer, description, serial);
+ e(ftdi_usb_open_dev(&ftdi,dev),"ftdi_usb_open_dev",&ftdi,13);
+ fprintf(stderr, "Connected\n");
+
+ //Init the device
+ e(ftdi_usb_reset(&ftdi),"ftdi_usb_reset",&ftdi,15);
+ e(ftdi_set_baudrate(&ftdi, 250000),"ftdi_set_baudrate",&ftdi,16);
+ e(ftdi_set_line_property(&ftdi, BITS_8, STOP_BIT_2, NONE),"ftdi_set_line_property",&ftdi,17);
+ e(ftdi_setflowctrl(&ftdi, SIO_DISABLE_FLOW_CTRL),"ftdi_setflowctrl",&ftdi,18);
+ e(ftdi_usb_purge_buffers(&ftdi),"ftdi_usb_purge_buffers",&ftdi,19);
+ e(ftdi_setrts(&ftdi, 0),"ftdi_setrts",&ftdi,20);
+
+ // 1ms pause for initialization completion
+ ts_to_sleep.tv_sec=0;
+ ts_to_sleep.tv_nsec=1000000;
+ nanosleep(&ts_to_sleep,NULL);
+
+ return 0;
+}
+
+int dmx_write_rgb(int r, int g, int b) {
+ if (! ftdi.usb_dev ) return -1;
+
+ universe[2]=r;
+ universe[3]=g;
+ universe[4]=b;
+
+ return dmx_universe_write(&ftdi, universe, DMX_CHANNELS);
+}
+
+void dmx_deinit() {
+ e(ftdi_usb_close(&ftdi),"ftdi_usb_close",&ftdi,50);
+ ftdi_list_free(&devlist);
+ ftdi_deinit(&ftdi);
+
+ free(manufacturer);
+ free(description);
+ free(serial);
+}
+
+int dmx_universe_write(struct ftdi_context *ftdi, unsigned char *universe, int uni_len) {
+ //static struct timespec ts_frame_time={0,DMX_FRAMETIME};
+ static struct timespec ts_dmx_break={0,DMX_BREAK};
+ static struct timespec ts_dmx_mab={0,DMX_MAB};
+ //static struct timespec ts_trame_begin={0,0};
+ //struct timespec ts_to_sleep, ts_now;
+
+ // http://www.opendmx.net/index.php/DMX512-A#Timings
+ // http://www.erwinrol.com/?s=dmx
+ // symbo_perdiod is 4us (250kHz)
+ // Full packet minimal timing : DMX_BREAK+DMX_MAB+(1+8+2)*513*symbol_period=22698us
+
+ ftdi_async_complete(ftdi,0);
+ // Wait the end of the previous timeslot
+/*
+ clock_gettime(CLOCK_MONOTONIC, &ts_now);
+ ts_diffadd(&ts_to_sleep,&ts_frame_time,&ts_now,&ts_trame_begin);
+
+ //fprintf(stderr, "DEBUG : ts_to_sleep==%li.%09li\n", ts_to_sleep.tv_sec, ts_to_sleep.tv_nsec);
+// ts_to_sleep.tv_sec=0;
+// ts_to_sleep.tv_nsec=23000000;
+ nanosleep(&ts_to_sleep,NULL);
+
+ clock_gettime(CLOCK_MONOTONIC, &ts_trame_begin);
+*/
+ e(ftdi_set_line_property2(ftdi, BITS_8, STOP_BIT_2, NONE, BREAK_ON),"ftdi_set_line_property2",ftdi,30);
+ nanosleep(&ts_dmx_break,NULL);
+ e(ftdi_set_line_property2(ftdi, BITS_8, STOP_BIT_2, NONE, BREAK_OFF),"ftdi_set_line_property2",ftdi,31);
+ nanosleep(&ts_dmx_mab,NULL);
+
+
+ //return ftdi_write_data(ftdi, universe, uni_len);
+ return ftdi_write_data_async(ftdi, universe, uni_len);
+}
+
+inline void ts_diffadd(struct timespec *res, struct timespec *a, struct timespec *b, struct timespec *c) {
+ time_t rem;
+
+ res->tv_nsec=a->tv_nsec-b->tv_nsec+c->tv_nsec;
+ rem=res->tv_nsec/1000000000;
+ res->tv_nsec=res->tv_nsec%1000000000;
+ res->tv_sec=a->tv_sec-b->tv_sec+c->tv_sec+rem;
+
+ if (res->tv_nsec<0 && res->tv_sec>0) { res->tv_sec--; res->tv_nsec+=1000000000; }
+ if (res->tv_nsec>0 && res->tv_sec<0) { res->tv_nsec-=1000000000; res->tv_sec++; }
+}
+
+void e(int res, const char *funcname, struct ftdi_context *ftdi, int exit_val) {
+ char *reason;
+
+ if ( res < 0 ) {
+ reason=ftdi_get_error_string(ftdi);
+ fprintf(stderr, "Error in %s : %s\n", funcname, reason);
+ exit(exit_val);
+ }
+
+}
+
diff --git a/src/illuminate.h b/src/illuminate.h
new file mode 100644
index 0000000..1854a85
--- /dev/null
+++ b/src/illuminate.h
@@ -0,0 +1,8 @@
+#ifndef ILLUMINATE_H
+#define ILLUMINATE_H
+
+int dmx_init();
+int dmx_write_rgb(int r, int g, int b);
+void dmx_deinit();
+
+#endif /*ILLUMINATE_H*/
diff --git a/src/music2light.c b/src/music2light.c
index fd58d03..18e6713 100644
--- a/src/music2light.c
+++ b/src/music2light.c
@@ -6,6 +6,7 @@
#include "compute.h"
#include "capture.h"
#include "hsv2rgb.h"
+#include "illuminate.h"
gint *audio_vumeter_val, *light_h, *light_s, *light_v, *light_r, *light_g, *light_b;
void my_process(float *data, size_t nsamples, size_t nchan);
@@ -37,8 +38,12 @@ int main (int argc, char **argv) {
pthread_create (&audio_analyzer, (void *)NULL, (void *)audio_thread, (void *)my_process);
g_timeout_add (25, win_main_update_vumeters, (gpointer)vals_for_vumeters);
+ dmx_init();
+
gtk_main ();
+
gdk_threads_leave();
+ dmx_deinit();
return 0;
}
@@ -75,6 +80,6 @@ void my_process(float *data, size_t nsamples, size_t nchan) {
*light_b=rgb.b*255;
// Send to DMX
- //TODO
+ dmx_write_rgb(*light_r, *light_g, *light_b);
}
diff --git a/src/win_main.c b/src/win_main.c
index daa0a34..08e6b4a 100644
--- a/src/win_main.c
+++ b/src/win_main.c
@@ -6,12 +6,12 @@ GtkWidget *vumeter_sound, *vumeter_r, *vumeter_g, *vumeter_b, *vumeter_h, *vumet
GtkWidget *win_main_build() {
GtkWidget *win, *hbox1;
- GdkColor f_gradient_red[2] = {{0,65535,0,0},{0,0,0,0}};
- GdkColor b_gradient_red[2] = {{0,49151,0,0},{0,0,0,0}};
- GdkColor f_gradient_green[2] = {{0,0,65535,0},{0,0,0,0}};
- GdkColor b_gradient_green[2] = {{0,0,49151,0},{0,0,0,0}};
- GdkColor f_gradient_blue[2] = {{0,0,0,65535},{0,0,0,0}};
- GdkColor b_gradient_blue[2] = {{0,0,0,49151},{0,0,0,0}};
+ GdkColor f_gradient_red[2] = {{0,65535,0,0},{0,32767,0,0}};
+ GdkColor b_gradient_red[2] = {{0,49151,0,0},{0,24575,0,0}};
+ GdkColor f_gradient_green[2] = {{0,0,65535,0},{0,0,32767,0}};
+ GdkColor b_gradient_green[2] = {{0,0,49151,0},{0,0,24575,0}};
+ GdkColor f_gradient_blue[2] = {{0,0,0,65535},{0,0,0,32767}};
+ GdkColor b_gradient_blue[2] = {{0,0,0,49151},{0,0,0,24575}};
GdkColor f_gradient_hue[7] = {{0,65535,0,0},{0,65535,0,65535},{0,0,0,65535},{0,0,65535,65535},{0,0,65535,0},{0,65535,65535,0},{0,65535,0,0}};
GdkColor b_gradient_hue[7] = {{0,49151,0,0},{0,49151,0,49151},{0,0,0,49151},{0,0,49151,49151},{0,0,49151,0},{0,49151,49151,0},{0,49151,0,0}};