nausea

curses audio visualizer
git clone git://git.2f30.org/nausea.git
Log | Files | Refs | README | LICENSE

commit 2a946fa55dbc8ad515ae7c51804ed45dd1c27899
parent 054d0e4bcea660e64f0e5ff685bed242746283f8
Author: lostd <lostd@2f30.org>
Date:   Mon Sep 15 02:27:20 +0100

Add the fountain visualization

Diffstat:
nausea.1 | 4++++
nausea.c | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 120 insertions(+), 5 deletions(-)
diff --git a/nausea.1 b/nausea.1 @@ -27,6 +27,8 @@ Show usage line. Enable color. .It Fl p Enable falling peaks. +.It Fl k +Keep state in the fountain visualization. .El .Pp Exposed runtime options: @@ -35,6 +37,8 @@ Exposed runtime options: Select the spectrum visualization. .It 2 Select the wave visualization. +.It 3 +Select the fountain visualization. .It c Toggle color. .It p diff --git a/nausea.c b/nausea.c @@ -21,6 +21,7 @@ static char *fname = "/tmp/audio.fifo"; static char *argv0; static int colors; static int peaks; +static int keep; static int die; struct frame { @@ -28,6 +29,7 @@ struct frame { size_t width, width_old; size_t height; int *peak; + int *sav; #define PK_HIDDEN -1 int16_t *buf; unsigned *res; @@ -39,9 +41,11 @@ struct frame { /* Supported visualizations: * 1 -- spectrum - * 2 -- wave */ + * 2 -- wave + * 2 -- fountain */ static void draw_spectrum(struct frame *fr); static void draw_wave(struct frame *fr); +static void draw_fountain(struct frame *fr); static void (* draw)(struct frame *fr) = draw_spectrum; /* We assume the screen is 100 pixels in the y direction. @@ -108,6 +112,7 @@ done(struct frame *fr) free(fr->res); free(fr->buf); free(fr->peak); + free(fr->sav); close(fr->fd); } @@ -137,7 +142,7 @@ update(struct frame *fr) } /* compute the DFT if needed */ - if (draw == draw_spectrum) + if (draw == draw_spectrum || draw == draw_fountain) fftw_execute(fr->plan); } @@ -313,6 +318,95 @@ draw_wave(struct frame *fr) } static void +draw_fountain(struct frame *fr) +{ + unsigned i, j; + struct color_range *cr; + static int col = 0; + size_t bar_height = 0; + unsigned freqs; + + /* read dimensions to catch window resize */ + fr->width = COLS; + fr->height = LINES; + + /* change in width needs new keep state */ + if (fr->width != fr->width_old) { + fr->sav = realloc(fr->sav, fr->width * sizeof(int)); + for (i = 0; i < fr->width; i++) + fr->sav[i] = fr->height; + fr->width_old = fr->width; + } + + if (colors) { + /* scale color ranges */ + for (i = 0; i < LEN(color_ranges); i++) { + cr = &color_ranges[i]; + cr->scaled_min = cr->min * fr->height / 100; + cr->scaled_max = cr->max * fr->height / 100; + } + } + + /* scale each frequency to screen */ +#define BARSCALE 0.3 + for (i = 0; i < nsamples / 2; i++) { + /* complex absolute value */ + fr->res[i] = cabs(fr->out[i]); + /* normalize it */ + fr->res[i] /= (nsamples / 2); + /* scale it */ + fr->res[i] *= fr->height * BARSCALE; + } +#undef BARSCALE + + /* take most of the left part of the band */ +#define BANDCUT 0.5 + freqs = (nsamples / 2) * BANDCUT; +#undef BANDCUT + + /* compute bar height */ + for (j = 0; j < freqs; j++) + bar_height += fr->res[j]; + bar_height /= freqs; + + erase(); + attron(A_BOLD); + + /* current column wraps around */ + col %= fr->width; + + for (i = 0; i < fr->width; i++) { + size_t ybegin, yend; + + /* we draw from top to bottom */ + if (i == col) { +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + ybegin = fr->height - MIN(bar_height, fr->height); + fr->sav[col] = ybegin; +#undef MIN + } else { + if (keep) + ybegin = fr->sav[i]; + else + ybegin = fr->sav[i]++; + } + yend = fr->height; + + /* output bars */ + for (j = ybegin; j < yend; j++) { + move(j, i); + setcolor(1, j); + printw("%c", chbar); + setcolor(0, j); + } + } + col++; + + attroff(A_BOLD); + refresh(); +} + +static void initcolors(void) { unsigned i; @@ -328,7 +422,7 @@ initcolors(void) static void usage(void) { - fprintf(stderr, "usage: %s [-hcp] [fifo]\n", argv0); + fprintf(stderr, "usage: %s [-hcpk] [fifo]\n", argv0); fprintf(stderr, "default fifo path is `/tmp/audio.fifo'\n"); exit(1); } @@ -338,6 +432,7 @@ main(int argc, char *argv[]) { int c; struct frame fr; + void *draw_prev = draw; argv0 = argv[0]; while (--argc > 0 && (*++argv)[0] == '-') @@ -349,6 +444,9 @@ main(int argc, char *argv[]) case 'p': peaks = 1; break; + case 'k': + keep = 1; + break; case 'h': /* fall-through */ default: @@ -391,22 +489,35 @@ main(int argc, char *argv[]) case 'p': peaks = !peaks; break; + case 'k': + keep = !keep; + break; case '1': draw = draw_spectrum; break; case '2': draw = draw_wave; break; + case '3': + draw = draw_fountain; + break; } - /* only spectrum supports colors */ - if (colors && (draw == draw_spectrum)) + /* detect visualization change */ + if (draw != draw_prev) + fr.width_old = 0; + + /* only spectrum and fountain support colors */ + if (colors && + (draw == draw_spectrum || draw == draw_fountain)) initcolors(); else (void)use_default_colors(); update(&fr); draw(&fr); + + draw_prev = draw; } endwin(); /* restore terminal */