From 97093a84c81827b540e7de637b52cf5466c056fc Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Thu, 6 Jun 2013 01:20:04 +0000 Subject: first draft --- Makefile | 2 +- hsv2rgb.c | 97 ++++--------------- hsv2rgb.h | 2 +- spectrogram.c | 306 +++++++++++++++++++++++++++------------------------------- 4 files changed, 160 insertions(+), 247 deletions(-) diff --git a/Makefile b/Makefile index f9842d3..f243d96 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ PROG= spectrogram SRCS= spectrogram.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/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/spectrogram.c b/spectrogram.c index e872f56..b232d4b 100644 --- a/spectrogram.c +++ b/spectrogram.c @@ -15,6 +15,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include + #include #include #include @@ -27,9 +30,6 @@ #include #include -#include -#include - #include "fft.h" #include "hsv2rgb.h" @@ -38,99 +38,94 @@ #define GAP 2 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 */ +unsigned long *wf, *sp, black, white; -#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; 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; } -SDL_Color * +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; +} + +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,29 +134,38 @@ 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(void) { - 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, 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); } int draw(double *left, double *right, int p, int step) { - int x, y, l, r, lx, rx; - double lo, mi, hi, av; + int x, l, r, lx, rx; - if (SDL_MUSTLOCK(screen)) - SDL_LockSurface(screen); + /* 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); - SDL_BlitSurface(screen, &wf_from, screen, &wf_to); + /* restore spectrogram bg */ + XCopyArea(dsp, bg, pix, gc, + sp_left.x, sp_left.y, width, sp_left.height, + sp_left.x, sp_left.y); - if (discolight) - lo = mi = hi = 0.0; - - for (x = 0; x < wf_left.w; x++) { + for (x = 0; x < wf_left.width; x++) { l = left[x] - 0.5; if (l >= p) l = p - 1; @@ -169,56 +173,28 @@ draw(double *left, double *right, int p, int step) 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; - } + lx = wf_left.x + (flip_left ? wf_left.width - x - 1 : x); + rx = wf_right.x + (flip_right ? wf_right.width - x - 1 : x); - lx = wf_left.x + (flip_left ? wf_left.w - x - 1 : x); - rx = wf_right.x + (flip_right ? wf_right.w - x - 1 : x); + /* waterfall */ + XSetForeground(dsp, gc, wf[l]); + XDrawPoint(dsp, pix, gc, lx, wf_left.y); - drawpixel(screen, lx, wf_left.y, &wf[l]); - drawpixel(screen, rx, wf_right.y, &wf[r]); + XSetForeground(dsp, gc, wf[r]); + XDrawPoint(dsp, pix, gc, rx, wf_right.y); - 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); - } + /* spectrogram neg mask */ + XSetForeground(dsp, gc, black); + 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 - l - 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; } @@ -250,7 +226,6 @@ 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"); @@ -258,8 +233,6 @@ usage(void) 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); } @@ -267,8 +240,9 @@ usage(void) int main(int argc, char **argv) { - SDL_Event event; - FPSmanager man; + + int scr; + Atom delwin; struct sio_hdl *sio; struct sio_par par; @@ -281,16 +255,12 @@ main(int argc, char **argv) size_t bufsz; size_t done; - int ch, sflag = 1, dflag = 1; + int ch, dflag = 1; int delta, resolution, fps; 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,15 +272,15 @@ 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) @@ -334,24 +304,32 @@ main(int argc, char **argv) par.sig != 1) errx(1, "unsupported audio params"); +#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); - 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)); + + XSelectInput(dsp, win, ExposureMask|KeyPressMask); + XMapWindow(dsp, win); bufsz = par.rchan * delta * sizeof(int16_t); buffer = malloc(bufsz); @@ -366,16 +344,16 @@ main(int argc, char **argv) psize = 2 * height / 3; ssize = psize >> 2; - init_rect(width, height, ssize, !!discolight * ssize); + init_rect(width, height, ssize); 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(); + fft = init_fft(delta); hamming = init_hamming(delta); - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); - sio_start(sio); done = 0; @@ -390,43 +368,37 @@ main(int argc, char **argv) dofft(fft, buffer, left, right, delta, hamming); draw(left, right, ssize, resolution); - SDL_framerateDelay(&man); + while (XPending(dsp)) { + XEvent ev; + + XNextEvent(dsp, &ev); - 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: + case XK_l: + case XK_1: flip_left ^= 1; break; - case SDLK_r: - case SDLK_2: + case XK_r: + case XK_2: flip_right ^= 1; break; - case SDLK_0: + case XK_0: flip_left ^= 1; flip_right ^= 1; 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); - break; default: break; } break; - case SDL_QUIT: - die = 1; + case ClientMessage: + die = *ev.xclient.data.l == delwin; + break; + default: break; } } @@ -439,5 +411,7 @@ main(int argc, char **argv) free(right); free(buffer); + XCloseDisplay(dsp); + return 0; } -- cgit v1.2.3