diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2012-06-17 09:28:18 +0000 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2012-06-17 09:28:18 +0000 |
commit | 96d4d223a6e2790e6269cd3b19b4944d99d61eb3 (patch) | |
tree | c62d0a1e02e7e9fe4a4415a6eeafb8ea35d10bf4 | |
parent | 797149c5a9ee0c7c70947f72cbaece5efd3dd687 (diff) | |
download | 2012-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/Makefile | 5 | ||||
-rw-r--r-- | src/capture.c | 2 | ||||
-rw-r--r-- | src/compute.c | 15 | ||||
-rw-r--r-- | src/illuminate.c | 164 | ||||
-rw-r--r-- | src/illuminate.h | 8 | ||||
-rw-r--r-- | src/music2light.c | 7 | ||||
-rw-r--r-- | src/win_main.c | 12 |
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}}; |