diff --git a/src/fft.c b/src/fft.c index 9282aed..d69b263 100755 --- a/src/fft.c +++ b/src/fft.c @@ -1,4 +1,6 @@ #include "fft.h" +#include + /* if flag is EVEN (0), it takes only the even elements * otherwise if flag is ODD (1) it takes only the odd ones */ @@ -60,24 +62,26 @@ } unsigned int -amplitude(cplx c) +amplitude(cplx c, unsigned int n) { - double sq; - unsigned int res; + // compute a normalized amplitude (actually power spectrum, since it's not squared + // normalize on n (N_SAMPLES) + double sq = 0; + unsigned int res = 0; /*compute amplitude*/ - sq = sqrt(pow(creal(c), 2) + pow(cimag(c), 2)); + sq = sqrt(pow(creal(c)/n, 2) + pow(cimag(c)/n, 2)); res = round(20*log10(sq)); // dB scale + /*fprintf(stderr, "%f - %d\n", sq, res);*/ return res; } -unsigned int* -fast_fft(int inLen, uint16_t *sig) +void +fast_fft(int inLen, uint16_t *sig, unsigned int *fftSig) { int i; cplx *inputComponents; cplx *outputComponents; - unsigned int *fftSig; if(inLen % 2 != 0){ fprintf(stderr, "Note that the length of the array MUST be a power of 2."); @@ -89,26 +93,17 @@ inputComponents[i] = sig[i]; } - /*fprintf(stdout, "in:\n");*/ - /*print_components(inputComponents, inLen);*/ - outputComponents = _fast_ft(inputComponents, inLen); - fftSig = calloc(inLen, sizeof(unsigned int)); - /*fprintf(stdout, "out:\n");*/ - /*print_components(outputComponents, inLen);*/ for(i=0; i // exit #include // read #include // open +#include // timeout +#include #include // open #include // uint16_t #include // strcmp #include +#include +#include #include "fft.h" // fast fourier transform #include "utils_curses.h" @@ -14,104 +18,138 @@ #include "utils_mpd.h" #define MPD_FIFO "/tmp/mpd.fifo" -/*FREQ 44100*/ #define N_SAMPLES 1024 -/*FPS FREQ/N_SAMPLES*/ +#define MAXEVENTS 1 -static int maxR; -static int maxC; -static STATUS* status; +static _Atomic bool getstatus = true; +static int maxR = 0; +static int maxC = 0; void -get_mpd_status() +get_mpd_status(struct mpd_connection* session, STATUS* status) { - signal(SIGALRM, SIG_IGN); - if(status) { - free_status_st(status); + if(!session) { + session = open_connection(); } - - struct mpd_connection* session = open_connection(); - if(session) { - status = get_current_status(session); - close_connection(session); - } - signal(SIGALRM, get_mpd_status); - alarm(1); + status = get_current_status(session); } -void process_mpd (int fifo) { - uint16_t buf[N_SAMPLES]; - unsigned int *fftBuf, *fftAvg; - int correction; //curses - struct mpd_connection* session = open_connection(); - get_mpd_status(); +void +alarm_status() +{ + getstatus = true; +} + +void +process_fifo (uint16_t* buf, unsigned int* fftBuf, unsigned int* fftAvg) { + // performs a Fourier Transform of the buffer data + fast_fft(N_SAMPLES, (uint16_t*)buf, fftBuf); + + // computes an average of the signals in fftBuf + // based on the number of columns of the screen + average_signal(fftBuf, N_SAMPLES, maxC, fftAvg); +} + +void +print_visual(unsigned int* fftBuf, unsigned int* fftAvg) +{ + int correction = maxC/16; //center terminal + int i; + + // main loop to print column by column + for(i=correction; i maxR || fftAvg[i] < 0){ + fftAvg[i] = 1; + } + // print the column fftAvg[i] + print_col(i-correction, fftAvg[i], maxR, maxC); + } +} + +void +main_event() +{ + uint16_t buf[N_SAMPLES]; + int fifo; + struct mpd_connection *session; + bool over = false; + STATUS* status = NULL; + fd_set set; + int ret; + + // open mpd fifo + while((fifo = open(MPD_FIFO, O_RDONLY)) == -1); + // add it to select() set + FD_ZERO(&set); + FD_SET(fifo, &set); + + // allocate buffers used + unsigned int* fftBuf= (unsigned int*)malloc(N_SAMPLES*sizeof(unsigned int)); + unsigned int* fftAvg = (unsigned int*)malloc(N_SAMPLES*sizeof(unsigned int)); + /*// set the result buffer to 0s*/ + memset(fftBuf, 0, N_SAMPLES*sizeof(unsigned int)); + memset(fftAvg, 0, N_SAMPLES*sizeof(unsigned int)); + + // open connection to mpd and set alarm to refresh status + session = open_connection(); + + signal(SIGALRM, alarm_status); alarm(1); - while(read(fifo, (uint16_t*)buf, 2*N_SAMPLES) != 0){ - // close on keypress 'q' - if(wgetch(stdscr)=='q'){ - break; - } - - // performs a Fourier Transform of the buffer data - fftBuf = fast_fft(N_SAMPLES, (uint16_t*)buf); - - // computes an average of the signals in fftBuf - // based on the number of columns of the screen - fftAvg = average_signal(fftBuf, N_SAMPLES, maxC); - free(fftBuf); - - // clear the screen - erase(); - - // correction can be used to exclude certain frequencies - correction = maxC/16; - int i; - for(i=correction; i maxR || fftAvg[i] < 0){ - fftAvg[i] = 1; - } - // print the column fftAvg[i] - print_col(i-correction, fftAvg[i], maxR, maxC); + while(!over) { + if (wgetch(stdscr) == 'q') { + over = true; } - - // print current mpd status - // if unable, just print error - if(!(status)){ - mvprintw(0,0, "Unable to retrieve status from mpd."); - } else { - print_mpd_status(status,maxC,maxR/2+maxR/6); + // select on fifo socket + // if > 0 means data to be read + if ((ret = select(fifo+1, &set, NULL, NULL, NULL)) > 0) { + // read data when avaiable + read(fifo, (uint16_t*)buf, 2*N_SAMPLES); + // process read buffer + process_fifo(buf, fftBuf, fftAvg); } - - // refresh the screen, free the allocated buffer - refresh(); - free(fftAvg); - } + // refresh status at SIGALRM + if(getstatus) { + // get mpd status + free_status_st(status); + status = get_current_status(session); + getstatus = false; + // set alarm for status refresh + alarm(1); + } + if (ret > 0) { + // clear screen for printing (only if new data on fifo) + erase(); + print_visual(fftBuf, fftAvg); + // print mpd status (if not refreshed, print old one) + } + // print mpd status even if no new data is avaiable + print_mpd_status(status, maxC, maxR/2+maxR/6); + // refresh screen + refresh(); + } + free(fftAvg); + free(fftBuf); + free_status_st(status); + close(fifo); close_connection(session); } -void -process_alsa() {} int main(int argc, char *argv[]) { - int fifo; WINDOW *mainwin; + import_var_from_settings(); - while((fifo = open(MPD_FIFO, O_RDONLY)) == -1); - - if (argc > 2 || argc < 1){ - fprintf(stderr, "Usage: mvc [--alsa/--mpd]\nDefault is MPD."); - exit(EXIT_FAILURE); - } - if((mainwin = curses_init()) == NULL){ exit(EXIT_FAILURE); } + // get screen properties getmaxyx(stdscr, maxR, maxC); curs_set(0); @@ -119,14 +157,9 @@ nodelay(stdscr, TRUE); // call the fifo processor - if (strcmp (argv[2], "--alsa") == 0) { - process_alsa(fifo); - } else { - process_mpd(fifo); - } + main_event(); // free resources - close(fifo); endwin(); delwin(mainwin); diff --git a/src/utils_curses.c b/src/utils_curses.c index ba176d4..6cdfdbe 100755 --- a/src/utils_curses.c +++ b/src/utils_curses.c @@ -44,48 +44,28 @@ int row, changeCol; int color = 5; - for(row=maxR; row>=0; row--){ + /*for(row=maxR; row>=0; row--){*/ + for (row=0; row l && row < maxR-l/3)) { // center of the screen - color_set(changeCol, NULL); - mvaddch(row, col, SHARP); + mvaddch(row, col, FULL); } else { - color_set(changeCol, NULL); - mvaddch(row, col, HEAVY); + mvaddch(row, col, EMPTY); } } } } -void -print_row(int row, int l, const int maxR, const int maxC) -{ - int col, changeCol; - int color = 5; - - for(col=maxC; col>=0; col--){ - if (row < maxR) { - color++; - changeCol = color % 6; - if ((col > l && col < maxR-l/3)) { // center of the screen - color_set(changeCol, NULL); - mvaddch(row, col, SHARP); - } else { - color_set(changeCol, NULL); - mvaddch(col, col, HEAVY); - } - } - } -} /* prints a STATUS structure to stdout */ void print_mpd_status(STATUS* status, const int maxC, const int row) { SONG* song = NULL; - bool CRflag = false, nullFlag = false; + bool nullFlag = false; int i,j; if(status == NULL){ @@ -95,6 +75,9 @@ song = status->song; int maxlen; int center; + if (song == NULL) { + return; + } if (song->artist == NULL) { maxlen = strlen(song->uri) + 3; center = maxC/2 - maxlen/2; diff --git a/src/utils_curses.h b/src/utils_curses.h index 785e758..9248bbd 100755 --- a/src/utils_curses.h +++ b/src/utils_curses.h @@ -3,8 +3,8 @@ #include "utils_mpd.h" // used while printing -#define SHARP 'x' -#define HEAVY '.' +#define FULL 'X' +#define EMPTY '.' void init_color_pairs(); WINDOW* curses_init();