diff --git a/alsa_fifo.c b/alsa_fifo.c deleted file mode 100644 index 3ef04d0..0000000 --- a/alsa_fifo.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include - -void -read_alsa_fifo (char* pcm_name) -{ - int i; - int err; - short buf[128]; - snd_pcm_t *capture_handle; - snd_pcm_hw_params_t *hw_params; - - if ((err = snd_pcm_open (&capture_handle, pcm_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { - fprintf (stderr, "cannot open audio device %s (%s)\n", - argv[1], - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { - fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) { - fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { - fprintf (stderr, "cannot set access type (%s)\n", - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { - fprintf (stderr, "cannot set sample format (%s)\n", - snd_strerror (err)); - exit (1); - } - unsigned int *rate = malloc(sizeof(unsigned int));; - int *dir = malloc (sizeof (int)); - *rate = 44100; - if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, rate, dir)) < 0) { - fprintf (stderr, "cannot set sample rate (%s)\n", - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { - fprintf (stderr, "cannot set channel count (%s)\n", - snd_strerror (err)); - exit (1); - } - - if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { - fprintf (stderr, "cannot set parameters (%s)\n", - snd_strerror (err)); - exit (1); - } - - snd_pcm_hw_params_free (hw_params); - - if ((err = snd_pcm_prepare (capture_handle)) < 0) { - fprintf (stderr, "cannot prepare audio interface for use (%s)\n", - snd_strerror (err)); - exit (1); - } - - while (1) { - if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) { - fprintf (stderr, "read from audio interface failed (%s)\n", - snd_strerror (err)); - exit (1); - } - fprintf (stdout, "%s\n", buf); - } - - snd_pcm_close (capture_handle); - free (rate); - free (dir); - exit (0); -} diff --git a/fft.c b/fft.c deleted file mode 100755 index fa7a866..0000000 --- a/fft.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "fft.h" -/* if flag is EVEN (0), it takes only the even elements - * otherwise if flag is ODD (1) it takes only the odd ones - */ -cplx *split_array(cplx *a, int len, int flag) -{ - int i, cnt = 0; - cplx *ret = malloc((len/2)*sizeof(cplx)); - - for(i=0+flag; i -#include // malloc -#include -#include -#include // uint16_t - -#define PI acos(-1.0) // even if it is defined as M_PI in math.h, this is more precise computationally -#define EVEN 0 -#define ODD 1 - -typedef double complex cplx; - -cplx *split_array(cplx *a, int len, int flag); -cplx *_fast_ft(cplx *compArray, int len); -void print_components(cplx *a, int len); -unsigned int amplitude(cplx c); -unsigned int* fast_fft(int inLen, uint16_t *sig); -unsigned int* average_signal(unsigned int *fftBuf, int inLen, int maxC); diff --git a/makefile b/makefile index df521e1..08f5ee1 100644 --- a/makefile +++ b/makefile @@ -1,8 +1,9 @@ -ALL = fft.c utils_curses.c music_visualizer.c +SRC = src/fft.c src/utils_curses.c src/music_visualizer.c src/alsa_fifo.c +ALL = $(SRC) LOCPATH = ./bin INSTALLPATH = /usr/local -LFLAGS = -lm -lcurses -ldl -ltinfo -DEBFLAGS = -g -Wall +LFLAGS = -lm -lcurses -ldl -ltinfo -lasound +DEBFLAGS = -g -Wall NAME = mvc all: @@ -22,7 +23,3 @@ cp $(LOCPATH)/$(NAME) $(INSTALLPATH)/bin/$(NAME) uninstall: rm $(INSTALLPATH)/bin/$(NAME) - - - - diff --git a/music_visualizer.c b/music_visualizer.c deleted file mode 100755 index eed3478..0000000 --- a/music_visualizer.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include // exit -#include // read -#include // open -#include // open -#include // uint16_t -#include "fft.h" // fast fourier transform -#include "utils_curses.h" -#include "time.h" - -#define MPD_FIFO "/tmp/mpd.fifo" -/*FREQ 44100*/ -#define N_SAMPLES 1024 -/*FPS FREQ/N_SAMPLES*/ - -void process_mpd (int fifo) { - uint16_t buf[N_SAMPLES]; - unsigned int *fftBuf, *fftAvg; - int maxR, maxC, correction; //curses - - - getmaxyx(stdscr, maxR, maxC); - - while(read(fifo, (uint16_t*)buf, 2*N_SAMPLES) != 0){ - /*usleep(45000);*/ - if(wgetch(stdscr)=='q'){ - break; - } - - fftBuf = fast_fft(N_SAMPLES, (uint16_t*)buf); - fftAvg = average_signal(fftBuf, N_SAMPLES, maxC); - free(fftBuf); - - erase(); - correction = 0; - for(i=correction; i maxR || fftAvg[i] < 0){ - fftAvg[i] = 1; - } - print_col(i-correction, fftAvg[i], maxR, atoi(argv[1])); - /*print_col(i-correction+1, fftAvg[i], maxR);*/ - } - refresh(); - free(fftAvg); - } -} - -int -main(int argc, char *argv[]) -{ - int fifo, i, j; - WINDOW *mainwin; - - if (strcmp (argv[2], "--alsa") == 0) { - - } - while((fifo = open(MPD_FIFO, O_RDONLY)) == -1); - - if (argc != 2){ - fprintf(stderr, "Usage: mvc [color number]\n"); - exit(EXIT_FAILURE); - } - - - if((mainwin = curses_init()) == NULL){ - exit(EXIT_FAILURE); - } - getmaxyx(stdscr, maxR, maxC); - curs_set(0); - cbreak(); - nodelay(stdscr, TRUE); - - while(read(fifo, (uint16_t*)buf, 2*N_SAMPLES) != 0){ - /*usleep(45000);*/ - if(wgetch(stdscr)=='q'){ - break; - } - - fftBuf = fast_fft(N_SAMPLES, (uint16_t*)buf); - fftAvg = average_signal(fftBuf, N_SAMPLES, maxC); - free(fftBuf); - - erase(); - correction = 0; - for(i=correction; i maxR || fftAvg[i] < 0){ - fftAvg[i] = 1; - } - print_col(i-correction, fftAvg[i], maxR, atoi(argv[1])); - /*print_col(i-correction+1, fftAvg[i], maxR);*/ - } - refresh(); - free(fftAvg); - } - close(fifo); - endwin(); - delwin(mainwin); - - return 0; -} diff --git a/src/alsa_fifo.c b/src/alsa_fifo.c new file mode 100644 index 0000000..d35d9d3 --- /dev/null +++ b/src/alsa_fifo.c @@ -0,0 +1,84 @@ +#include "alsa_fifo.h" + +void +read_alsa_fifo (char* pcm_name) +{ + int i; + int err; + short buf[128]; + snd_pcm_t *capture_handle; + snd_pcm_hw_params_t *hw_params; + + if ((err = snd_pcm_open (&capture_handle, pcm_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { + fprintf (stderr, "cannot open audio device %s (%s)\n", + pcm_name, + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { + fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) { + fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + fprintf (stderr, "cannot set access type (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { + fprintf (stderr, "cannot set sample format (%s)\n", + snd_strerror (err)); + exit (1); + } + unsigned int *rate = malloc(sizeof(unsigned int));; + int *dir = malloc (sizeof (int)); + *rate = 44100; + if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, rate, dir)) < 0) { + fprintf (stderr, "cannot set sample rate (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { + fprintf (stderr, "cannot set channel count (%s)\n", + snd_strerror (err)); + exit (1); + } + + if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { + fprintf (stderr, "cannot set parameters (%s)\n", + snd_strerror (err)); + exit (1); + } + + snd_pcm_hw_params_free (hw_params); + + if ((err = snd_pcm_prepare (capture_handle)) < 0) { + fprintf (stderr, "cannot prepare audio interface for use (%s)\n", + snd_strerror (err)); + exit (1); + } + + while (1) { + if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) { + fprintf (stderr, "read from audio interface failed (%s)\n", + snd_strerror (err)); + exit (1); + } + fprintf (stdout, "%s\n", buf); + } + + snd_pcm_close (capture_handle); + free (rate); + free (dir); + exit (0); +} diff --git a/src/alsa_fifo.h b/src/alsa_fifo.h new file mode 100644 index 0000000..7739370 --- /dev/null +++ b/src/alsa_fifo.h @@ -0,0 +1,6 @@ +#include +#include +#include + +void +read_alsa_fifo (char* pcm_name); diff --git a/src/fft.c b/src/fft.c new file mode 100755 index 0000000..fa7a866 --- /dev/null +++ b/src/fft.c @@ -0,0 +1,131 @@ +#include "fft.h" +/* if flag is EVEN (0), it takes only the even elements + * otherwise if flag is ODD (1) it takes only the odd ones + */ +cplx *split_array(cplx *a, int len, int flag) +{ + int i, cnt = 0; + cplx *ret = malloc((len/2)*sizeof(cplx)); + + for(i=0+flag; i +#include // malloc +#include +#include +#include // uint16_t + +#define PI acos(-1.0) // even if it is defined as M_PI in math.h, this is more precise computationally +#define EVEN 0 +#define ODD 1 + +typedef double complex cplx; + +cplx *split_array(cplx *a, int len, int flag); +cplx *_fast_ft(cplx *compArray, int len); +void print_components(cplx *a, int len); +unsigned int amplitude(cplx c); +unsigned int* fast_fft(int inLen, uint16_t *sig); +unsigned int* average_signal(unsigned int *fftBuf, int inLen, int maxC); diff --git a/src/music_visualizer.c b/src/music_visualizer.c new file mode 100755 index 0000000..a471e86 --- /dev/null +++ b/src/music_visualizer.c @@ -0,0 +1,101 @@ +#include +#include // exit +#include // read +#include // open +#include // open +#include // uint16_t +#include // strcmp +#include "fft.h" // fast fourier transform +#include "utils_curses.h" +#include "alsa_fifo.h" + +#define MPD_FIFO "/tmp/mpd.fifo" +/*FREQ 44100*/ +#define N_SAMPLES 1024 +/*FPS FREQ/N_SAMPLES*/ + +static int maxR; +static int maxC; + +void process_mpd (int fifo) { + uint16_t buf[N_SAMPLES]; + unsigned int *fftBuf, *fftAvg; + int correction; //curses + + 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 + // not advised nor customary + correction = 0; + 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); + } + // refresh the screen, free the allocated buffer + refresh(); + free(fftAvg); + } +} + +void +process_alsa (int fifo) +{} + +int +main(int argc, char *argv[]) +{ + int fifo, i, j; + WINDOW *mainwin; + + 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); + cbreak(); + nodelay(stdscr, TRUE); + + // call the fifo processor + if (strcmp (argv[2], "--alsa") == 0) { + process_alsa(fifo); + } else { + process_mpd(fifo); + } + + // free resources + close(fifo); + endwin(); + delwin(mainwin); + + return 0; +} diff --git a/src/utils_curses.c b/src/utils_curses.c new file mode 100755 index 0000000..ee8e2e0 --- /dev/null +++ b/src/utils_curses.c @@ -0,0 +1,56 @@ +#include "utils_curses.h" + +// initialize color pairs +// used in print_col +void +init_color_pairs() +{ + if(has_colors()){ + start_color(); + use_default_colors(); + init_pair(1, COLOR_RED, -1); + init_pair(2, COLOR_GREEN, -1); + init_pair(3, COLOR_YELLOW, -1); + init_pair(4, COLOR_BLUE, -1); + init_pair(5, COLOR_CYAN, -1); + init_pair(6, COLOR_MAGENTA, -1); + init_pair(8, COLOR_WHITE, -1); + } +} + +// returns a WINDOW object +// called by main() on startup +WINDOW* +curses_init() +{ + WINDOW *w; + if((w = initscr()) == NULL){ //initialize curses library on current screen + fprintf(stderr, "Error opening screen\n"); + return NULL; + } + init_color_pairs(); + return w; +} + +// print a column to screen +// while doing so, perform a rotation of the color +// modify here to change color output +void +print_col(int col, int l, int maxR) +{ + int row, changeCol; + int color = 5; + + for(row=maxR; row>=0; row--){ + color++; + changeCol = color % 6; + if ((row > l && row < maxR-l/3)) { // center of the screen + color_set(changeCol, NULL); + mvaddch(row, col, SHARP); + } else { + color_set(changeCol, NULL); + mvaddch(row, col, HEAVY); + } + } +} + diff --git a/src/utils_curses.h b/src/utils_curses.h new file mode 100755 index 0000000..4610f8c --- /dev/null +++ b/src/utils_curses.h @@ -0,0 +1,9 @@ +#include + +// used while printing +#define SHARP 'x' +#define HEAVY '.' + +void init_color_pairs(); +WINDOW* curses_init(); +void print_col(int col, int length, int maxR); diff --git a/utils_curses.c b/utils_curses.c deleted file mode 100755 index 06ed60f..0000000 --- a/utils_curses.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "utils_curses.h" - - -void -init_color_pairs() -{ - if(has_colors()){ - start_color(); - use_default_colors(); - init_pair(1, COLOR_RED, -1); - init_pair(2, COLOR_GREEN, -1); - init_pair(3, COLOR_YELLOW, -1); - init_pair(4, COLOR_BLUE, -1); - init_pair(5, COLOR_CYAN, -1); - init_pair(6, COLOR_MAGENTA, -1); - init_pair(8, COLOR_WHITE, -1); - } -} - -WINDOW* -curses_init() -{ - WINDOW *w; - if((w = initscr()) == NULL){ //initialize curses library on current screen - fprintf(stderr, "Error opening screen\n"); - return NULL; - } - init_color_pairs(); - return w; -} - -void -print_col(int col, int l, int maxR, int color) -{ - int row; - int changeCol; - for(row=maxR; row>=0; row--){ - color++; - changeCol = color % 6; - if ((row > l && row < maxR-l/3)) { // center of the screen - color_set(changeCol, NULL); - mvaddch(row, col, SHARP); - } else { - color_set(changeCol, NULL); - mvaddch(row, col, HEAVY); - - } - } -} - diff --git a/utils_curses.h b/utils_curses.h deleted file mode 100755 index 6a866ff..0000000 --- a/utils_curses.h +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#define SHARP 'x' -#define HEAVY '.' - -void init_color_pairs(); -WINDOW* curses_init(); -void print_col(int col, int length, int maxR, int color);