From 4eb398d0af04e27327d0482bf1917066420b97a2 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 22 Jun 2013 20:16:20 +0000 Subject: Switch to X11 --- Makefile | 4 +- fft.c | 39 ++++- fft.h | 3 +- hsv2rgb.c | 97 +++--------- hsv2rgb.h | 2 +- sio.c | 92 +++++++++++ sio.h | 28 ++++ spectrogram.c | 488 ++++++++++++++++++++++++++-------------------------------- 8 files changed, 397 insertions(+), 356 deletions(-) create mode 100644 sio.c create mode 100644 sio.h diff --git a/Makefile b/Makefile index f9842d3..5bcfce5 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ # $Id$ PROG= spectrogram -SRCS= spectrogram.c fft.c hsv2rgb.c +SRCS= spectrogram.c sio.c fft.c hsv2rgb.c HEADERS=fft.h hsv2rgb.h -LIBS= sdl SDL_gfx fftw3 +LIBS= fftw3 x11 PCCF!= pkg-config --cflags ${LIBS} PCLA!= pkg-config --libs ${LIBS} CFLAGS+=${PCCF} diff --git a/fft.c b/fft.c index 5e71679..a13eaad 100644 --- a/fft.c +++ b/fft.c @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -26,8 +27,25 @@ struct fft { double *in; double *out; int n; + double *window; }; +double * +hamming(int n) +{ + double *w; + int i; + + w = calloc(n, sizeof(double)); + if (!w) + errx(1, "malloc failed"); + + for (i = 0; i < n; i++) + w[i] = 0.54 - 0.46 * cos((2 * M_PI * i) / (n - 1)); + + return w; +} + struct fft * init_fft(int n) { @@ -47,28 +65,39 @@ init_fft(int n) p[1].plan = fftw_plan_r2r_1d(n, p[1].in, p[1].out, FFTW_R2HC, FFTW_MEASURE); + p->window = hamming(n); + return p; } int -dofft(struct fft *p, int16_t *data, double *left, double *right, int n, double *wight) +dofft(struct fft *p, int16_t *data, double *left, double *right, int n, float scala) { int i; for (i = 0; i < n; i++) { - p[0].in[i] = wight[i] * data[2 * i + 0] / (double)INT16_MAX; - p[1].in[i] = wight[i] * data[2 * i + 1] / (double)INT16_MAX; + p[0].in[i] = p->window[i] * data[2 * i + 0] / (double)INT16_MAX; + p[1].in[i] = p->window[i] * data[2 * i + 1] / (double)INT16_MAX; } fftw_execute(p[0].plan); fftw_execute(p[1].plan); for (i = 1; i < n / 2; i++) { - left[i - 1] = sqrt(5 * i + left[i - 1] = sqrt(scala * i * (pow(p[0].out[i], 2) + pow(p[0].out[n - i], 2))); - right[i - 1] = sqrt(5 * i + right[i - 1] = sqrt(scala * i * (pow(p[1].out[i], 2) + pow(p[1].out[n - i], 2))); } return 0; } + +void +del_fft(struct fft *fft) +{ + fftw_free(fft->in); + fftw_free(fft->out); + free(fft->window); + free(fft); +} diff --git a/fft.h b/fft.h index 77e4737..1e89451 100644 --- a/fft.h +++ b/fft.h @@ -21,6 +21,7 @@ struct fft; struct fft *init_fft(int); -int dofft(struct fft *, int16_t *, double *, double *, int, double *); +int dofft(struct fft *, int16_t *, double *, double *, int, float); +void del_fft(struct fft *); #endif diff --git a/hsv2rgb.c b/hsv2rgb.c index 6339533..bd7d7e2 100644 --- a/hsv2rgb.c +++ b/hsv2rgb.c @@ -1,96 +1,35 @@ /* $Id$ */ -/* hsv2rgb.c - * Convert Hue Saturation Value to Red Green Blue - * - * P.J. 08-Aug-98 - * - * Reference: - * D. F. Rogers - * Procedural Elements for Computer Graphics - * McGraw Hill 1985 - */ -#include +#include -int -hsv2rgb(uint8_t *r, uint8_t *g, uint8_t *b, float h, float s, float v) +/* input: h, s, v [0..1] + * output: r, g, b [0..1] + */ +void +hsv2rgb(float *r, float *g, float *b, float h, float s, float v) { - /* - * Purpose: - * Convert HSV values to RGB values - * All values are in the range [0.0 .. 1.0] - */ float F, M, N, K; int i; - /* normalize */ - if (s < 0.0) { - h += 0.5; - s = -s; - } - - if (v < 0.0) - v = -v; - - while (h > 1.0) - h -= 1.0; - while (h < 0.0) - h += 1.0; - - if (s == 0.0) { - /* - * Achromatic case, set level of grey - */ - *r = v * 255; - *g = v * 255; - *b = v * 255; + *r = *g = *b = v; } else { - /* - * Determine levels of primary colours. - */ - - h = (h >= 1.0) ? 0.0 : h * 6; - i = (int)h; /* should be in the range 0..5 */ - F = h - i; /* fractional part */ - + if (h == 1.0) + h = 0.0; + h *= 6.0; + i = floorf(h); + F = h - i; M = v * (1 - s); N = v * (1 - s * F); K = v * (1 - s * (1 - F)); switch (i) { - case 0: - *r = v * 255; - *g = K * 255; - *b = M * 255; - break; - case 1: - *r = N * 255; - *g = v * 255; - *b = M * 255; - break; - case 2: - *r = M * 255; - *g = v * 255; - *b = K * 255; - break; - case 3: - *r = M * 255; - *g = N * 255; - *b = v * 255; - break; - case 4: - *r = K * 255; - *g = M * 255; - *b = v * 255; - break; - case 5: - *r = v * 255; - *g = M * 255; - *b = N * 255; - break; + case 0: *r = v; *g = K; *b = M; break; + case 1: *r = N; *g = v; *b = M; break; + case 2: *r = M; *g = v; *b = K; break; + case 3: *r = M; *g = N; *b = v; break; + case 4: *r = K; *g = M; *b = v; break; + case 5: *r = v; *g = M; *b = N; break; } } - - return 0; } diff --git a/hsv2rgb.h b/hsv2rgb.h index 9851ca0..1cacf20 100644 --- a/hsv2rgb.h +++ b/hsv2rgb.h @@ -18,6 +18,6 @@ #ifndef __HSV2RGB_H #define __HSV2RGB_H -int hsv2rgb(uint8_t *r, uint8_t *g, uint8_t *b, float h, float s, float v); +void hsv2rgb(float *r, float *g, float *b, float h, float s, float v); #endif diff --git a/sio.c b/sio.c new file mode 100644 index 0000000..8776930 --- /dev/null +++ b/sio.c @@ -0,0 +1,92 @@ +/* $Id$ */ +/* + * Copyright (c) 2013 Dimitri Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +struct sio { + struct sio_hdl *sio; + struct sio_par par; +}; + +struct sio * +init_sio(int rchan, int bits, int sig) +{ + struct sio *sio; + + sio = malloc(sizeof(struct sio)); + if (!sio) + errx(1, "malloc failed"); + + sio->sio = sio_open(NULL, SIO_REC, 0); + + if (!sio->sio) + errx(1, "cannot connect to sound server, is it running?"); + + sio_initpar(&sio->par); + + sio->par.rchan = rchan; + sio->par.bits = bits; + sio->par.le = SIO_LE_NATIVE; + sio->par.sig = sig; + + if (!sio_setpar(sio->sio, &sio->par)) + errx(1, "SIO set params failed"); + if (!sio_getpar(sio->sio, &sio->par)) + errx(1, "SIO get params failed"); + + if (sio->par.rchan != rchan || + sio->par.bits != bits || + sio->par.le != SIO_LE_NATIVE || + sio->par.sig != sig) + errx(1, "unsupported audio params"); + + sio_start(sio->sio); + + return sio; +} + +unsigned int +get_round(struct sio *sio) +{ + return sio->par.round; +} + +int +read_sio(struct sio *sio, int16_t *buffer, size_t sz) +{ + int done = 0; + + do { + done += sio_read(sio->sio, buffer, sz); + if (sio_eof(sio->sio)) + errx(1, "SIO EOF"); + buffer += done; + sz -= done; + } while (sz); + + return done; +} + +void +del_sio(struct sio *sio) +{ + sio_stop(sio->sio); + sio_close(sio->sio); + free(sio); +} diff --git a/sio.h b/sio.h new file mode 100644 index 0000000..c771dd1 --- /dev/null +++ b/sio.h @@ -0,0 +1,28 @@ +/* $Id$ */ +/* + * Copyright (c) 2013 Dimitri Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __SIO_H +#define __SIO_H + +struct sio; + +struct sio *init_sio(int, int, int); +unsigned int get_round(struct sio *); +int read_sio(struct sio *, int16_t *, size_t); +void del_sio(struct sio *); + +#endif diff --git a/spectrogram.c b/spectrogram.c index e872f56..2755bea 100644 --- a/spectrogram.c +++ b/spectrogram.c @@ -15,10 +15,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include + #include #include #include -#include #include #include #include @@ -27,9 +29,7 @@ #include #include -#include -#include - +#include "sio.h" #include "fft.h" #include "hsv2rgb.h" @@ -37,100 +37,108 @@ #define SSIZE (PSIZE >> 1) #define GAP 2 +#define RCHAN 2 +#define BITS 16 +#define SIGNED 1 + extern char *__progname; -SDL_Surface *screen; -SDL_Color *wf, *sp; -SDL_Color black = { .r = 0, .g = 0, .b = 0 }; -SDL_Color white = { .r = 255, .g = 255, .b = 255 }; -SDL_Rect wf_from, wf_to; /* waterfall blit */ -SDL_Rect wf_left, wf_right; /* waterfall */ -SDL_Rect sp_left, sp_right; /* spectrogram */ -SDL_Rect dl_lo, dl_mi, dl_hi; /* disco light */ +Display *dsp; +Window win; +Colormap cmap; +GC gc; +Pixmap pix, bg; +int width, height; -/* Disco Light Frequencies, Hz */ -#define LOSTART 50 -#define LOEND 350 -#define MISTART 200 -#define MIEND 2000 -#define HISTART 1500 -#define HIEND 5000 +XRectangle wf_from, wf_to; /* waterfall blit */ +XRectangle wf_left, wf_right; /* waterfall */ +XRectangle sp_left, sp_right; /* spectrogram */ int die = 0; -int flip_left = 1; -int flip_right = 0; -int discolight = 0; + +struct data { + int16_t *buffer; + size_t bufsz; + double *left; + double *right; + int *left_shadow; + int *right_shadow; + int maxval; + unsigned long *wf; + unsigned long *sp; +}; void -init_rect(int w, int h, int ssz, int dlsz) +init_rect(int w, int h, int ssz) { - /* Dicolight */ - dl_lo.x = 0; - dl_lo.y = 0; - dl_lo.w = w / 3; - dl_lo.h = dlsz; - - dl_mi.x = w / 3; - dl_mi.y = 0; - dl_mi.w = w / 3; - dl_mi.h = dlsz; - - dl_hi.x = 2 * w / 3; - dl_hi.y = 0; - dl_hi.w = w / 3; - dl_hi.h = dlsz; - /* Blit */ wf_from.x = 0; - wf_from.y = 1 + dlsz; - wf_from.w = w; - wf_from.h = h - ssz - dlsz - 1; + wf_from.y = 1; + wf_from.width = w; + wf_from.height = h - ssz - 1; wf_to.x = 0; - wf_to.y = dlsz; - wf_to.w = w; - wf_to.h = h - ssz - dlsz - 1; + wf_to.y = 0; + wf_to.width = w; + wf_to.height = h - ssz - 1; /* Watterfall */ wf_left.x = 0; wf_left.y = h - ssz - 1; - wf_left.w = w / 2 - GAP; - wf_left.h = 1; + wf_left.width = w / 2 - GAP; + wf_left.height = 1; wf_right.x = w / 2 + GAP; wf_right.y = h - ssz - 1; - wf_right.w = w / 2 - GAP; - wf_right.h = 1; + wf_right.width = w / 2 - GAP; + wf_right.height = 1; /* Spectrogram */ sp_left.x = 0; sp_left.y = h - ssz; - sp_left.w = w / 2 - GAP; - sp_left.h = ssz; + sp_left.width = w / 2 - GAP; + sp_left.height = ssz; sp_right.x = w / 2 + GAP; sp_right.y = h - ssz; - sp_right.w = w / 2 - GAP; - sp_right.h = ssz; + sp_right.width = w / 2 - GAP; + sp_right.height = ssz; +} + +unsigned long +hsvcolor(float h, float s, float v) +{ + XColor c; + float r, g, b; + + hsv2rgb(&r, &g, &b, h, s, v); + + c.red = UINT16_MAX * r; + c.green = UINT16_MAX * g; + c.blue = UINT16_MAX * b; + c.flags = DoRed|DoGreen|DoBlue; + + XAllocColor(dsp, cmap, &c); + + return c.pixel; } -SDL_Color * +unsigned long * init_palette(float h, float dh, float s, float ds, float v, float dv, int n, int lg) { - SDL_Color *p; + unsigned long *p; float hstep, sstep, vstep; int i; - p = malloc(n * sizeof(SDL_Color)); + p = calloc(n, sizeof(unsigned long)); hstep = (dh - h) / n; sstep = (ds - s) / n; vstep = (dv - v) / n; for (i = 0; i < n; i++) { - hsv2rgb(&p[i].r, &p[i].g, &p[i].b, h, s, - lg ? logf(100 * v + 1) / logf(101) : v); + p[i] = hsvcolor(h, s, lg ? logf(100 * v + 1) / logf(101) : v); h += hstep; s += sstep; v += vstep; @@ -139,106 +147,93 @@ init_palette(float h, float dh, float s, float ds, float v, float dv, int n, int return p; } -static inline void -drawpixel(SDL_Surface *s, int x, int y, SDL_Color *c) +void +createbg(struct data *data) { - Uint32 *buf = (Uint32 *)s->pixels + y * (s->pitch >> 2) + x; - Uint32 pixel = SDL_MapRGB(s->format, c->r, c->g, c->b); - *buf = pixel; + int y; + + for (y = 0; y < sp_left.height; y++) { + XSetForeground(dsp, gc, data->sp[y]); + XDrawLine(dsp, bg, gc, + sp_left.x, sp_left.y + sp_left.height - y - 1, + sp_left.x + sp_left.width - 1, + sp_left.y + sp_left.height - y - 1); + } + + XCopyArea(dsp, bg, bg, gc, + sp_left.x, sp_left.y, sp_left.width, sp_left.height, + sp_right.x, sp_right.y); } +#define LIMIT(val, maxval) ((val) >= (maxval) ? ((maxval) - 1) : (val)) + int -draw(double *left, double *right, int p, int step) +draw(struct data *data) { - int x, y, l, r, lx, rx; - double lo, mi, hi, av; - - if (SDL_MUSTLOCK(screen)) - SDL_LockSurface(screen); - - SDL_BlitSurface(screen, &wf_from, screen, &wf_to); - - if (discolight) - lo = mi = hi = 0.0; - - for (x = 0; x < wf_left.w; x++) { - l = left[x] - 0.5; - if (l >= p) - l = p - 1; - r = right[x] - 0.5; - if (r >= p) - r = p - 1; - - if (discolight) { - av = pow(left[x] + right[x], 2.0); - if (x >= LOSTART / step && x <= LOEND / step) - lo += av; - if (x >= MISTART / step && x <= MIEND / step) - mi += av; - if (x >= HISTART / step && x <= HIEND / step) - hi += av; + int x, l, r, lx, rx; + + /* blit waterfall */ + XCopyArea(dsp, pix, pix, gc, + wf_from.x, wf_from.y, wf_from.width, wf_from.height, + wf_to.x, wf_to.y); + + /* restore spectrogram bg */ + XCopyArea(dsp, bg, pix, gc, + sp_left.x, sp_left.y, width, sp_left.height, + sp_left.x, sp_left.y); + + for (x = 0; x < wf_left.width; x++) { + l = LIMIT(data->left[x], data->maxval); + r = LIMIT(data->right[x], data->maxval); + + lx = wf_left.x + wf_left.width - x - 1; + rx = wf_right.x + x; + + /* waterfall */ + XSetForeground(dsp, gc, data->wf[l]); + XDrawPoint(dsp, pix, gc, lx, wf_left.y); + + XSetForeground(dsp, gc, data->wf[r]); + XDrawPoint(dsp, pix, gc, rx, wf_right.y); + + /* spectrogram neg mask */ + XSetForeground(dsp, gc, data->wf[0]); + XDrawLine(dsp, pix, gc, + lx, sp_left.y, + lx, sp_left.y + sp_left.height - l - 1); + XDrawLine(dsp, pix, gc, + rx, sp_right.y, + rx, sp_right.y + sp_right.height - r - 1); + + if (data->left_shadow[x] < l) + data->left_shadow[x] = l; + else if(data->left_shadow[x] > 0) { + data->left_shadow[x]--; + XSetForeground(dsp, gc, + data->sp[data->left_shadow[x] - 1]); + XDrawPoint(dsp, pix, gc, + lx, sp_left.y + sp_left.height + - data->left_shadow[x] - 1); } - lx = wf_left.x + (flip_left ? wf_left.w - x - 1 : x); - rx = wf_right.x + (flip_right ? wf_right.w - x - 1 : x); - - drawpixel(screen, lx, wf_left.y, &wf[l]); - drawpixel(screen, rx, wf_right.y, &wf[r]); - - for (y = 0; y < sp_left.h; y++) { - drawpixel(screen, lx, - sp_left.y + sp_left.h - y - 1, - l > y ? &sp[y] : &black); - drawpixel(screen, rx, - sp_right.y + sp_right.h - y - 1, - r > y ? &sp[y] : &black); + if (data->right_shadow[x] < r) + data->right_shadow[x] = r; + else if(data->right_shadow[x] > 0) { + data->right_shadow[x]--; + XSetForeground(dsp, gc, + data->sp[data->right_shadow[x] - 1]); + XDrawPoint(dsp, pix, gc, + rx, sp_right.y + sp_right.height + - data->right_shadow[x] - 1); } } - /* XXX */ - if (discolight) { - lo = sqrt(lo / ((LOEND - LOSTART) / step)); - if (lo > p) - lo = p; - mi = sqrt(mi / ((MIEND - MISTART) / step)); - if (mi > p) - mi = p; - hi = sqrt(hi / ((HIEND - HISTART) / step)); - if (hi > p) - hi = p; - - SDL_FillRect(screen, &dl_lo, - SDL_MapRGB(screen->format, lo, lo / 4, 0)); - SDL_FillRect(screen, &dl_mi, - SDL_MapRGB(screen->format, mi / 2, mi, 0)); - SDL_FillRect(screen, &dl_hi, - SDL_MapRGB(screen->format, hi / 4, hi / 2, hi)); - } - - if (SDL_MUSTLOCK(screen)) - SDL_UnlockSurface(screen); - - SDL_Flip(screen); + /* flip */ + XCopyArea(dsp, pix, win, gc, 0, 0, width, height, 0, 0); return 0; } -double * -init_hamming(int n) -{ - double *w; - int i; - - w = calloc(n, sizeof(double)); - if (!w) - errx(1, "malloc failed"); - - for (i = 0; i < n; i++) - w[i] = 0.54 - 0.46 * cos((2 * M_PI * i) / (n - 1)); - - return w; -} - void catch(int notused) { @@ -250,47 +245,32 @@ usage(void) { fprintf(stderr, "Usage: %s [-hsd]\n", __progname); fprintf(stderr, "\t-h\tthis help\n"); - fprintf(stderr, "\t-s\tallow scrennsaver\n"); fprintf(stderr, "\t-d\tdon't fork\n"); - fprintf(stderr, "Keys:\n"); - fprintf(stderr, "\tq\tquit\n"); - fprintf(stderr, "\t1,l\tflip left\n"); - fprintf(stderr, "\t2,r\tflip right\n"); - fprintf(stderr, "\t0\tflip both\n"); - fprintf(stderr, "\tf\ttoggle fullscreen\n"); - fprintf(stderr, "\td\ttoggle discolights\n"); - exit(0); } int main(int argc, char **argv) { - SDL_Event event; - FPSmanager man; - struct sio_hdl *sio; - struct sio_par par; - struct fft *fft; + Atom delwin; + int scr; + unsigned long black; + unsigned long white; - double *left, *right; - double *hamming; + struct sio *sio; + struct fft *fft; + struct data data; - int16_t *buffer; - size_t bufsz; - size_t done; + float scala = 1.0; - int ch, sflag = 1, dflag = 1; - int delta, resolution, fps; + int ch, dflag = 1; + int delta; int psize, ssize; - int width, height; - while ((ch = getopt(argc, argv, "hsd")) != -1) + while ((ch = getopt(argc, argv, "hd")) != -1) switch (ch) { - case 's': - sflag = 0; - break; case 'd': dflag = 0; break; @@ -302,142 +282,114 @@ main(int argc, char **argv) argc -= optind; argv += optind; - - if (sflag) - setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0); - - if (SDL_Init(SDL_INIT_VIDEO) < 0) - errx(1, "SDL init failed"); + dsp = XOpenDisplay(getenv("DISPLAY")); + if (!dsp) + errx(1, "Cannot connect to X11 server"); + scr = DefaultScreen(dsp); + black = BlackPixel(dsp, scr); + white = WhitePixel(dsp, scr); + cmap = DefaultColormap(dsp, scr); signal(SIGINT, catch); - atexit(SDL_Quit); - - sio = sio_open(NULL, SIO_REC, 0); - if (!sio) - errx(1, "cannot connect to sound server, is it running?"); - - sio_initpar(&par); - - par.rchan = 2; - par.bits = 16; - par.le = SIO_LE_NATIVE; - par.sig = 1; - if (!sio_setpar(sio, &par)) - errx(1, "SIO set params failed"); - if (!sio_getpar(sio, &par)) - errx(1, "SIO get params failed"); - - if (par.rchan != 2 || - par.bits != 16 || - par.le != SIO_LE_NATIVE || - par.sig != 1) - errx(1, "unsupported audio params"); + sio = init_sio(RCHAN, BITS, SIGNED); +#if 0 if (dflag) daemon(0, 0); +#endif - delta = par.round; - resolution = (par.rate / par.round) / par.rchan; - fps = (par.rate / par.round) * par.rchan; - - SDL_WM_SetCaption(__progname, NULL); - SDL_initFramerate(&man); - SDL_setFramerate(&man, fps); - + delta = get_round(sio); width = delta + 2 * GAP; height = 3 * width / 4; - screen = SDL_SetVideoMode(width, height, 32, - SDL_HWSURFACE | SDL_DOUBLEBUF); - if (!screen) - errx(1, "set video mode failed"); + win = XCreateSimpleWindow(dsp, RootWindow(dsp, scr), 0, 0, + width, height, 2, white, black); + XStoreName(dsp, win, __progname); + delwin = XInternAtom(dsp, "WM_DELETE_WINDOW", 0); + XSetWMProtocols(dsp, win, &delwin, 1); + + gc = XCreateGC(dsp, win, 0, NULL); + XSetGraphicsExposures(dsp, gc, False); + + pix = XCreatePixmap(dsp, win, width, height, DisplayPlanes(dsp, scr)); + bg = XCreatePixmap(dsp, win, width, height, DisplayPlanes(dsp, scr)); - bufsz = par.rchan * delta * sizeof(int16_t); - buffer = malloc(bufsz); - if (!buffer) + XSelectInput(dsp, win, ExposureMask|KeyPressMask); + XMapWindow(dsp, win); + + data.bufsz = RCHAN * delta * sizeof(int16_t); /* par.rchan */ + data.buffer = malloc(data.bufsz); + if (!data.buffer) errx(1, "malloc failed"); - left = calloc(delta, sizeof(double)); - right = calloc(delta, sizeof(double)); - if (!left || !right) + data.left = calloc(delta, sizeof(double)); + data.right = calloc(delta, sizeof(double)); + data.left_shadow = calloc(delta, sizeof(int)); + data.right_shadow = calloc(delta, sizeof(int)); + if (!data.left || !data.right) errx(1, "malloc failed"); psize = 2 * height / 3; ssize = psize >> 2; + data.maxval = ssize; + + init_rect(width, height, ssize); - init_rect(width, height, ssize, !!discolight * ssize); + data.sp = init_palette(0.30, 0.00, 0.50, 1.00, 0.75, 1.00, ssize, 0); + data.wf = init_palette(0.65, 0.35, 1.00, 0.00, 0.00, 1.00, ssize, 1); - sp = init_palette(0.30, 0.00, 0.50, 1.00, 0.75, 1.00, ssize, 0); - wf = init_palette(0.65, 0.35, 1.00, 0.00, 0.00, 1.00, ssize, 1); + createbg(&data); fft = init_fft(delta); - hamming = init_hamming(delta); - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + while (!die) { + read_sio(sio, data.buffer, data.bufsz); + dofft(fft, data.buffer, data.left, data.right, delta, scala); + draw(&data); + + while (XPending(dsp)) { + XEvent ev; - sio_start(sio); + XNextEvent(dsp, &ev); - done = 0; - while (!die) { - do { - done += sio_read(sio, buffer + done, bufsz - done); - if (sio_eof(sio)) - errx(1, "SIO EOF"); - } while (done < bufsz); - done -= bufsz; - - dofft(fft, buffer, left, right, delta, hamming); - draw(left, right, ssize, resolution); - - SDL_framerateDelay(&man); - - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_KEYDOWN: - switch (event.key.keysym.sym) { - case SDLK_q: + switch (ev.type) { + case KeyPress: + switch (XLookupKeysym(&ev.xkey, 0)) { + case XK_q: die = 1; break; - case SDLK_l: - case SDLK_1: - flip_left ^= 1; - break; - case SDLK_r: - case SDLK_2: - flip_right ^= 1; - break; - case SDLK_0: - flip_left ^= 1; - flip_right ^= 1; + case XK_KP_Add: + scala *= 2; + warnx("inc scala: %f", scala); break; - case SDLK_f: - SDL_WM_ToggleFullScreen(screen); - SDL_ShowCursor(!(screen->flags - & SDL_FULLSCREEN)); - break; - case SDLK_d: - discolight ^= 1; - init_rect(width, height, ssize, - !!discolight * ssize); + case XK_KP_Subtract: + scala /= 2; + warnx("dec scala: %f", scala); break; default: break; } break; - case SDL_QUIT: - die = 1; + case ClientMessage: + die = *ev.xclient.data.l == delwin; + break; + default: break; } } } - sio_stop(sio); - sio_close(sio); + del_sio(sio); + del_fft(fft); + + free(data.left_shadow); + free(data.right_shadow); + free(data.left); + free(data.right); + free(data.buffer); - free(left); - free(right); - free(buffer); + XCloseDisplay(dsp); return 0; } -- cgit v1.2.3