aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2013-03-24 22:14:07 +0000
committerDimitri Sokolyuk <demon@dim13.org>2013-03-24 22:14:07 +0000
commitbeab9eef436342afb5391c009734d243896ed6b8 (patch)
treea143b21dcd0f58fe3b3f8c9cc527cd65ebe1149a
parent34c49f927b11dc8a587e07c234630c1b2a56e23d (diff)
simplify code
-rw-r--r--Makefile2
-rw-r--r--fft.c42
-rw-r--r--fft.h2
-rw-r--r--fifo.c101
-rw-r--r--fifo.h27
-rw-r--r--spectrogram.c225
6 files changed, 75 insertions, 324 deletions
diff --git a/Makefile b/Makefile
index 2bd7f16..257005c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# $Id$
PROG= spectrogram
-SRCS= spectrogram.c fifo.c fft.c hsv2rgb.c
+SRCS= spectrogram.c fft.c hsv2rgb.c
HEADERS=fifo.h fft.h hsv2rgb.h
LIBS= sdl fftw3
PCCF!= pkg-config --cflags ${LIBS}
diff --git a/fft.c b/fft.c
index 5372b89..5e71679 100644
--- a/fft.c
+++ b/fft.c
@@ -15,6 +15,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -32,27 +33,42 @@ init_fft(int n)
{
struct fft *p;
- p = malloc(sizeof(struct fft));
- p->in = fftw_malloc(n * sizeof(double));
- p->out = fftw_malloc(n * sizeof(double));
- p->plan = fftw_plan_r2r_1d(n, p->in, p->out, FFTW_R2HC, FFTW_MEASURE);
- p->n = n;
+ p = malloc(2 * sizeof(struct fft));
+
+ p[0].n = n;
+ p[0].in = fftw_malloc(n * sizeof(double));
+ p[0].out = fftw_malloc(n * sizeof(double));
+ p[0].plan = fftw_plan_r2r_1d(n, p[0].in, p[0].out,
+ FFTW_R2HC, FFTW_MEASURE);
+
+ p[1].n = n;
+ p[1].in = fftw_malloc(n * sizeof(double));
+ p[1].out = fftw_malloc(n * sizeof(double));
+ p[1].plan = fftw_plan_r2r_1d(n, p[1].in, p[1].out,
+ FFTW_R2HC, FFTW_MEASURE);
return p;
}
int
-dofft(struct fft *p, double *data)
+dofft(struct fft *p, int16_t *data, double *left, double *right, int n, double *wight)
{
- int i, n;
+ 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;
+ }
- memset(p->out, 0, p->n * sizeof(double));
- memcpy(p->in, data, p->n * sizeof(double));
- fftw_execute(p->plan);
+ fftw_execute(p[0].plan);
+ fftw_execute(p[1].plan);
- n = p->n / 2;
- for (i = 1; i < n; i++)
- data[i - 1] = sqrt(i * (p->out[i] * p->out[i] + p->out[p->n - i] * p->out[p->n - i]));
+ for (i = 1; i < n / 2; i++) {
+ left[i - 1] = sqrt(5 * i
+ * (pow(p[0].out[i], 2) + pow(p[0].out[n - i], 2)));
+ right[i - 1] = sqrt(5 * i
+ * (pow(p[1].out[i], 2) + pow(p[1].out[n - i], 2)));
+ }
return 0;
}
diff --git a/fft.h b/fft.h
index 851045f..77e4737 100644
--- a/fft.h
+++ b/fft.h
@@ -21,6 +21,6 @@
struct fft;
struct fft *init_fft(int);
-int dofft(struct fft *, double *);
+int dofft(struct fft *, int16_t *, double *, double *, int, double *);
#endif
diff --git a/fifo.c b/fifo.c
deleted file mode 100644
index 5b80ec8..0000000
--- a/fifo.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2010 Dimitri Sokolyuk <demon@dim13.org>
- *
- * 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 <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct buf {
- double *buf;
- double *end;
- double *wr;
- double *rd;
-};
-
-struct fifo {
- struct buf l;
- struct buf r;
- size_t sz;
-};
-
-struct fifo *
-init_fifo(int n)
-{
- struct fifo *ff;
-
- ff = malloc(sizeof(struct fifo));
-
- ff->l.buf = malloc(n * sizeof(double));
- ff->l.end = ff->l.buf + n;
- ff->l.wr = ff->l.buf;
- ff->l.rd = ff->l.buf;
-
- ff->r.buf = malloc(n * sizeof(double));
- ff->r.end = ff->r.buf + n;
- ff->r.wr = ff->r.buf;
- ff->r.rd = ff->r.buf;
-
- ff->sz = 0;
-
- return ff;
-}
-
-int
-wr_fifo(struct fifo *ff, double *l, double *r, int n)
-{
- int i;
-
- for (i = 0; i < n; i++) {
- *ff->l.wr++ = *l++;
- *ff->r.wr++ = *r++;
- if (ff->l.wr >= ff->l.end) {
- ff->l.wr = ff->l.buf;
- ff->r.wr = ff->r.buf;
- }
- }
- ff->sz += n;
-
- return ff->sz;
-}
-
-int
-rd_fifo(struct fifo *ff, double *l, double *r, int n, double *w)
-{
- int i;
- double *lnext = ff->l.rd;
- double *rnext = ff->r.rd;
-
- for (i = 0; i < n; i++) {
- if (i == n / 4) {
- lnext = ff->l.rd;
- rnext = ff->r.rd;
- }
- *l++ = *ff->l.rd++ * w[i];
- *r++ = *ff->r.rd++ * w[i];
- if (ff->l.rd >= ff->l.end) {
- ff->l.rd = ff->l.buf;
- ff->r.rd = ff->r.buf;
- }
- }
- ff->l.rd = lnext;
- ff->r.rd = rnext;
-
- ff->sz -= n / 4;
-
- return ff->sz;
-}
diff --git a/fifo.h b/fifo.h
deleted file mode 100644
index 63b6899..0000000
--- a/fifo.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* $Id$ */
-/*
- * Copyright (c) 2010 Dimitri Sokolyuk <demon@dim13.org>
- *
- * 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 __FIFO_H
-#define __FIFO_H
-
-struct fifo;
-
-struct fifo *init_fifo(size_t);
-int wr_fifo(struct fifo *, double *, double *, size_t);
-int rd_fifo(struct fifo *, double *, double *, size_t, double *);
-
-#endif
diff --git a/spectrogram.c b/spectrogram.c
index 4dbf572..64765ef 100644
--- a/spectrogram.c
+++ b/spectrogram.c
@@ -31,20 +31,12 @@
#include <SDL.h>
#include <SDL_thread.h>
-#include "fifo.h"
#include "fft.h"
#include "hsv2rgb.h"
#define PSIZE 250
#define SSIZE (PSIZE >> 1)
-#define TIMING 0
-
-struct buf {
- int16_t left;
- int16_t right;
-};
-
SDL_Surface *screen;
SDL_Color *pane;
SDL_Color *pan2;
@@ -158,60 +150,18 @@ init_palette_big(int n)
return p;
}
-int *
-init_scala(int n, int w)
-{
- int *s, i;
- float k;
-
- s = malloc(w * sizeof(int));
-
- k = n / logf(w);
-
- for (i = 0; i < w; i++)
- s[i] = n - k * logf(w - i);
-
- return s;
-}
-
-int *
-init_factor(int *scala, int w)
-{
- int *s, k, i;
-
- s = malloc(w * sizeof(int));
- k = 0;
- for (i = 0; i < w; i++) {
- s[i] = scala[i] - k;
- if (s[i] == 0)
- s[i] = 1;
- k = scala[i];
- }
-
- return s;
-}
-
-#if 1
-inline void
+void
drawpixel(SDL_Surface *s, int x, int y, SDL_Color *c)
{
Uint32 *buf = (Uint32 *)s->pixels + y * (s->pitch >> 2) + x;
Uint32 pixel = SDL_MapRGB(s->format, c->r, c->g, c->b);
*buf = pixel;
}
-#else
-#define drawpixel(s, x, y, c) do { \
- Uint32 *buf, pixel; \
- buf = (Uint32 *)(s)->pixels + (y) * ((s)->pitch >> 2) + (x); \
- pixel = SDL_MapRGB((s)->format, (c)->r, (c)->g, (c)->b); \
- *buf = pixel; \
- } while (0)
-#endif
int
-draw(double *left, double *right, int n, int *scala, int *fact, int p)
+draw(double *left, double *right, int p)
{
- int x, y, l, r, i, lx, rx;
+ int x, y, l, r, lx, rx;
if (SDL_MUSTLOCK(screen) && SDL_LockSurface(screen))
return -1;
@@ -219,22 +169,10 @@ draw(double *left, double *right, int n, int *scala, int *fact, int p)
SDL_BlitSurface(screen, &wf_from, screen, &wf_to);
for (x = 0; x < wf_left.w; x++) {
- l = 0;
- r = 0;
-
- for (i = 0; i < fact[x]; i++) {
- l += left[scala[x] - i] + 0.5;
- r += right[scala[x] - i] + 0.5;
- }
-
- l /= fact[x];
- r /= fact[x];
-
- l >>= 1;
- r >>= 1;
-
+ l = left[x] - 0.5;
if (l >= p)
l = p - 1;
+ r = right[x] - 0.5;
if (r >= p)
r = p - 1;
@@ -244,9 +182,6 @@ draw(double *left, double *right, int n, int *scala, int *fact, int p)
drawpixel(screen, lx, wf_left.y, &pane[l]);
drawpixel(screen, rx, wf_right.y, &pane[r]);
- l >>= 1;
- r >>= 1;
-
for (y = 0; y < sp_left.h; y++) {
drawpixel(screen, lx,
sp_left.y + sp_left.h - y - 1,
@@ -266,7 +201,7 @@ draw(double *left, double *right, int n, int *scala, int *fact, int p)
}
double *
-init_wights(int n)
+init_hamming(int n)
{
double *w;
int i;
@@ -275,7 +210,7 @@ init_wights(int n)
assert(w);
for (i = 0; i < n; i++)
- w[i] = (1 - cos((2 * M_PI * i) / (n - 1))) / 2;
+ w[i] = 0.54 - 0.46 * cos((2 * M_PI * i) / (n - 1));
return w;
}
@@ -299,87 +234,53 @@ usage(void)
int
main(int argc, char **argv)
{
- const SDL_VideoInfo *vi;
SDL_Event event;
- struct buf *buf;
+ int16_t *buffer;
size_t bufsz;
struct sio_hdl *sio;
struct sio_par par;
- struct fifo *ff;
struct fft *fft;
double *left, *right;
- int c, i, n, k, r, delta;
- double *wights;
- int *scala;
- int *factor;
+ int delta;
+ double *hamming;
int psize, ssize;
- int width = 1024;
- int height = 768;
- int fullscreen = 0;
- int stretch = 0;
- int sdlargs;
+ int width, height;
int pressed = 0;
-
- #if TIMING
- struct timeval ta, te;
- #endif
-
- while ((c = getopt(argc, argv, "h:w:lrFf")) != -1)
- switch (c) {
- case 'h':
- height = atoi(optarg);
- break;
- case 'w':
- width = atoi(optarg);
- break;
- case 'l':
- flip_left ^= 1;
- break;
- case 'r':
- flip_right ^= 1;
- break;
- case 'F':
- stretch = 1;
- /* FALLTHROUGH */
- case 'f':
- fullscreen = 1;
- break;
- default:
- usage();
- break;
- }
-
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return 1;
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?");
- sdlargs = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
- if (height <= 320 || width <= 200)
- errx(1, "not supported resolution");
- if (fullscreen) {
- sdlargs |= SDL_FULLSCREEN;
- vi = SDL_GetVideoInfo();
- if (!vi)
- return 1;
- warnx("%dx%d", vi->current_w, vi->current_h);
-
- if (stretch) {
- height = vi->current_h - 1;
- width = vi->current_w - 1;
- }
- }
+ sio_initpar(&par);
+ sio_getpar(sio, &par);
+
+ delta = par.round;
+ warnx("delta %d", delta);
+
+ width = delta + 2; /* XXX */
+ height = 3 * width / 4;
- screen = SDL_SetVideoMode(width, height, 32, sdlargs);
+ screen = SDL_SetVideoMode(width, height, 32,
+ SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF);
if (!screen)
return 1;
- SDL_ShowCursor(SDL_DISABLE);
+ bufsz = 2 * delta * sizeof(int16_t);
+ buffer = malloc(bufsz);
+ assert(buffer);
+
+ left = calloc(delta, sizeof(double));
+ right = calloc(delta, sizeof(double));
+ assert(left && right);
psize = 2 * height / 3;
ssize = psize >> 2;
@@ -388,54 +289,24 @@ main(int argc, char **argv)
pan2 = init_palette_small(ssize);
pane = init_palette_big(psize);
-
- sio = sio_open(NULL, SIO_REC, 0);
- if (!sio)
- errx(1, "cannot connect to sound server, is it running?");
-
- sio_initpar(&par);
- sio_getpar(sio, &par);
-
- delta = par.round / 2;
- n = 4 * delta;
- warnx("delta: %d, n: %d", delta, n);
- bufsz = delta * sizeof(struct buf);
- buf = malloc(bufsz);
- assert(buf);
-
- left = calloc(n, sizeof(double));
- right = calloc(n, sizeof(double));
- assert(left && right);
+ fft = init_fft(delta);
+ hamming = init_hamming(delta);
sio_start(sio);
- fft = init_fft(n);
- wights = init_wights(n);
- ff = init_fifo(10 * n);
- scala = init_scala(n / 2, wf_left.w);
- factor = init_factor(scala, wf_left.w);
-
- #if TIMING
- gettimeofday(&ta, NULL);
- #endif
-
while (!die) {
- k = sio_read(sio, buf, bufsz) / sizeof(struct buf);
- for (i = 0; i < k; i++) {
- left[i] = buf[i].left / (double)INT16_MAX;
- right[i] = buf[i].right / (double)INT16_MAX;
- }
- r = wr_fifo(ff, left, right, k);
+ size_t done = 0;
- if (r >= n) {
- rd_fifo(ff, left, right, n, wights);
+ do {
+ done += sio_read(sio, buffer + done, bufsz - done);
+ if (done != bufsz)
+ warnx("re-read %zu", done);
+ assert(sio_eof(sio) == 0);
+ } while (done < bufsz);
- dofft(fft, left);
- dofft(fft, right);
-
- draw(left, right, n / 2, scala, factor, psize);
- }
+ dofft(fft, buffer, left, right, delta, hamming);
+ draw(left, right, psize);
SDL_PollEvent(&event);
switch (event.type) {
@@ -472,22 +343,14 @@ main(int argc, char **argv)
pressed = 0;
break;
}
- #if TIMING
- gettimeofday(&te, NULL);
- fprintf(stderr, "%8d time elapsed: %7.6lf sec\r",
- r, te.tv_sec - ta.tv_sec
- + (te.tv_usec - ta.tv_usec)/1000000.0);
- memcpy(&ta, &te, sizeof(struct timeval));
- #endif
}
-
sio_stop(sio);
sio_close(sio);
free(left);
free(right);
- free(buf);
+ free(buffer);
return 0;
}