aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2013-06-06 01:20:04 +0000
committerDimitri Sokolyuk <demon@dim13.org>2013-06-06 01:20:04 +0000
commit97093a84c81827b540e7de637b52cf5466c056fc (patch)
treeac19d018ea35bca6ddeee158a3ac03fb266d855e
parent84632dda7f646a18893cbb363899d7e01a87f312 (diff)
first draft
-rw-r--r--Makefile2
-rw-r--r--hsv2rgb.c97
-rw-r--r--hsv2rgb.h2
-rw-r--r--spectrogram.c306
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 <stdint.h>
+#include <math.h>
-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 <X11/Xlib.h>
+#include <X11/keysym.h>
+
#include <sys/types.h>
#include <sys/time.h>
#include <err.h>
@@ -27,9 +30,6 @@
#include <math.h>
#include <signal.h>
-#include <SDL.h>
-#include <SDL_framerate.h>
-
#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;
}